From e8debf4e4392013e1845313a8e284a3df672461a Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Fri, 12 Jan 2018 16:15:58 +0000 Subject: [PATCH 1/3] use setuptools parse_version for version comparision adds support for version strings conformin to PEP 440 See https://www.python.org/dev/peps/pep-0440/ --- modoboa/core/utils.py | 13 ++++++------- requirements.txt | 1 - 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/modoboa/core/utils.py b/modoboa/core/utils.py index 43af52c8d..4ef209dae 100644 --- a/modoboa/core/utils.py +++ b/modoboa/core/utils.py @@ -2,10 +2,9 @@ from __future__ import unicode_literals -from django.utils.translation import ugettext as _ +from pkg_resources import parse_version -from versionfield.constants import DEFAULT_NUMBER_BITS -from versionfield.version import Version +from django.utils.translation import ugettext as _ from modoboa.core.extensions import exts_pool from modoboa.lib.api_client import ModoAPIClient @@ -38,15 +37,15 @@ def check_for_updates(request): }] + extensions update_avail = False for extension in extensions: - local_version = Version(extension["version"], DEFAULT_NUMBER_BITS) pkgname = extension["name"].replace("_", "-") for api_extension in local_config.api_versions: if api_extension["name"] != pkgname: continue - last_version = Version( - api_extension["version"], DEFAULT_NUMBER_BITS) extension["last_version"] = api_extension["version"] - if last_version > local_version: + if ( + parse_version(api_extension["version"]) + > parse_version(extension["version"]) + ): extension["update"] = True extension["changelog_url"] = api_extension["url"] update_avail = True diff --git a/requirements.txt b/requirements.txt index 96dfe8d44..05e90244e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,6 @@ django-braces==1.11.0 django-ckeditor==5.2.2 django-reversion==2.0.12 django-subcommand2==0.1.1 -django-versionfield2>=0.5.0 django-xforwardedfor-middleware==2.0 dj-database-url From dfabe89899816bde241a96c382cfb353fa073366 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Thu, 11 Jan 2018 19:05:12 +0000 Subject: [PATCH 2/3] refactor setup.py - use setuptools_scm to generate version number, normal releases will use the tagged version (ie 1.9.1), versions installed from source will append the git commit number to the version number (ie 1.9.1.dev61+g4584c93) - use io.open() to read text files to correctly handle utf-8 characters - use pip to parse requirements.txt - update classifiers to specify python and django versions supported - fix classifier for license - wheel distributions can now be built using `python setup.py bdist_wheel` --- modoboa/__init__.py | 13 +++++ setup.cfg | 2 + setup.py | 128 +++++++++++++++++++++----------------------- 3 files changed, 76 insertions(+), 67 deletions(-) diff --git a/modoboa/__init__.py b/modoboa/__init__.py index baffc4882..5d2abec9b 100644 --- a/modoboa/__init__.py +++ b/modoboa/__init__.py @@ -1 +1,14 @@ +# -*- coding: utf-8 -*- + +"""Modoboa - Mail hosting made simple.""" + from __future__ import unicode_literals + +from pkg_resources import get_distribution, DistributionNotFound + + +try: + __version__ = get_distribution(__name__).version +except DistributionNotFound: + # package is not installed + pass diff --git a/setup.cfg b/setup.cfg index a7854adaf..66d21b5cc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,5 @@ +[bdist_wheel] +universal = 1 [pep8] max-line-length = 80 exclude = migrations diff --git a/setup.py b/setup.py index 5b2eec221..222e20111 100644 --- a/setup.py +++ b/setup.py @@ -1,78 +1,72 @@ #!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# -*- coding: utf-8 -*- -import os -import re +""" +A setuptools based setup module. + +See: +https://packaging.python.org/en/latest/distributing.html +""" + +from __future__ import unicode_literals + +import io +from os import path +from pip.req import parse_requirements from setuptools import setup, find_packages -ROOT = os.path.dirname(__file__) -PIP_REQUIRES = os.path.join(ROOT, "requirements.txt") - -def parse_requirements(*filenames): - """ - We generate our install_requires from the pip-requires and test-requires - files so that we don't have to maintain the dependency definitions in - two places. - """ +def get_requirements(requirements_file): + """Use pip to parse requirements file.""" requirements = [] - for f in filenames: - for line in open(f, 'r').read().split('\n'): - # Comment lines. Skip. - if re.match(r'(\s*#)|(\s*$)', line): - continue - # Editable matches. Put the egg name into our reqs list. - if re.match(r'\s*-e\s+', line): - pkg = re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', line) - requirements.append("%s" % pkg) - # File-based installs not supported/needed. Skip. - elif re.match(r'\s*-f\s+', line): - pass - else: - requirements.append(line) + if path.isfile(requirements_file): + for req in parse_requirements(requirements_file, session="hack"): + # check markers, such as + # + # rope_py3k ; python_version >= '3.0' + # + if req.match_markers(): + requirements.append(str(req.req)) return requirements -def parse_dependency_links(*filenames): - """ - We generate our dependency_links from the pip-requires and test-requires - files for the dependencies pulled from github (prepended with -e). - """ - dependency_links = [] - for f in filenames: - for line in open(f, 'r').read().split('\n'): - if re.match(r'\s*-[ef]\s+', line): - line = re.sub(r'\s*-[ef]\s+', '', line) - line = re.sub(r'\s*git\+https', 'http', line) - line = re.sub(r'\.git#', '/tarball/master#', line) - dependency_links.append(line) - return dependency_links +if __name__ == "__main__": + HERE = path.abspath(path.dirname(__file__)) + INSTALL_REQUIRES = get_requirements(path.join(HERE, "requirements.txt")) + with io.open(path.join(HERE, "README.rst"), encoding="utf-8") as readme: + LONG_DESCRIPTION = readme.read() -def read(fname): - return open(os.path.join(ROOT, fname)).read() - - -setup( - name="modoboa", - version="1.9.1", - url="http://modoboa.org/", - license="ISC", - description="Mail hosting made simple", - long_description=read("README.rst"), - author="Antoine Nguyen", - author_email="tonio@ngyn.org", - packages=find_packages(), - include_package_data=True, - scripts=["bin/modoboa-admin.py"], - zip_safe=False, - install_requires=parse_requirements(PIP_REQUIRES), - dependency_links=parse_dependency_links(PIP_REQUIRES), - classifiers=["Development Status :: 5 - Production/Stable", - "Framework :: Django", - "Intended Audience :: System Administrators", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Topic :: Internet :: WWW/HTTP"] -) + setup( + name="modoboa", + description="Mail hosting made simple", + long_description=LONG_DESCRIPTION, + license="ISC", + url="http://modoboa.org/", + author="Antoine Nguyen", + author_email="tonio@ngyn.org", + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Framework :: Django :: 1.11", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: ISC License (ISCL)", + "Operating System :: OS Independent", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Topic :: Communications :: Email", + "Topic :: Internet :: WWW/HTTP", + ], + keywords="email", + packages=find_packages(exclude=["doc", "test_data", "test_project"]), + include_package_data=True, + zip_safe=False, + scripts=["bin/modoboa-admin.py"], + install_requires=INSTALL_REQUIRES, + use_scm_version=True, + setup_requires=["setuptools_scm"], + ) From b4c0be2c9b22684240166b6f8ebceeae795a1c2f Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Fri, 12 Jan 2018 22:45:09 +0000 Subject: [PATCH 3/3] add extra optional packages Add the ability to install optional packages when installing modoboa. For example if I wanted to use modoboa with PostgreSQL `pip install modoboa[postgresql]`, or if I wanted MySQL and LDAP support `pip install modoboa[mysql,ldap]` mysqlclient minimum version has been pined to 1.3.11 due to an issue with MariaDB 10 (#1341) --- mysql-requirements.txt | 1 + postgresql-requirements.txt | 1 + setup.py | 9 +++++++++ 3 files changed, 11 insertions(+) create mode 100644 mysql-requirements.txt create mode 100644 postgresql-requirements.txt diff --git a/mysql-requirements.txt b/mysql-requirements.txt new file mode 100644 index 000000000..8498237ca --- /dev/null +++ b/mysql-requirements.txt @@ -0,0 +1 @@ +mysqlclient>=1.3.11 diff --git a/postgresql-requirements.txt b/postgresql-requirements.txt new file mode 100644 index 000000000..59041b90e --- /dev/null +++ b/postgresql-requirements.txt @@ -0,0 +1 @@ +psycopg2>=2.5.4 diff --git a/setup.py b/setup.py index 222e20111..5d4e2db31 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,10 @@ def get_requirements(requirements_file): if __name__ == "__main__": HERE = path.abspath(path.dirname(__file__)) INSTALL_REQUIRES = get_requirements(path.join(HERE, "requirements.txt")) + MYSQL_REQUIRES = get_requirements(path.join(HERE, "mysql-requirements.txt")) + POSTGRESQL_REQUIRES = get_requirements( + path.join(HERE, "postgresql-requirements.txt")) + LDAP_REQUIRES = get_requirements(path.join(HERE, "ldap-requirements.txt")) with io.open(path.join(HERE, "README.rst"), encoding="utf-8") as readme: LONG_DESCRIPTION = readme.read() @@ -69,4 +73,9 @@ if __name__ == "__main__": install_requires=INSTALL_REQUIRES, use_scm_version=True, setup_requires=["setuptools_scm"], + extras_require={ + "ldap": LDAP_REQUIRES, + "mysql": MYSQL_REQUIRES, + "postgresql": POSTGRESQL_REQUIRES, + }, )