diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml new file mode 100644 index 0000000..92231fe --- /dev/null +++ b/.github/workflows/ci-tests.yml @@ -0,0 +1,84 @@ +name: Build and test + +on: + # Only on pushes to master or one of the release branches we build on push + push: + branches: + - master + - "[0-9].[0-9]+-branch" + tags: + # Build pull requests + pull_request: + +jobs: + test: + strategy: + matrix: + py: + - "3.7" + - "3.8" + - "3.9" + - "3.10" + - "pypy-3.7" + os: + - "ubuntu-latest" + # - "windows-latest" + - "macos-latest" + architecture: + - x64 + - x86 + exclude: + # Linux and macOS don't have x86 python + - os: "ubuntu-latest" + architecture: x86 + - os: "macos-latest" + architecture: x86 + name: "Python: ${{ matrix.py }}-${{ matrix.architecture }} on ${{ matrix.os }}" + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.py }} + architecture: ${{ matrix.architecture }} + - run: pip install tox + - name: Running tox + run: tox -e py + # coverage: + # runs-on: ubuntu-latest + # name: Validate coverage + # steps: + # - uses: actions/checkout@v2 + # - name: Setup python 3.10 + # uses: actions/setup-python@v2 + # with: + # python-version: "3.10" + # architecture: x64 + + # - run: pip install tox + # - run: tox -e py310,coverage + docs: + runs-on: ubuntu-latest + name: Build the documentation + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: "3.10" + architecture: x64 + - run: pip install tox + - run: tox -e docs + # lint: + # runs-on: ubuntu-latest + # name: Lint the package + # steps: + # - uses: actions/checkout@v2 + # - name: Setup python + # uses: actions/setup-python@v2 + # with: + # python-version: "3.10" + # architecture: x64 + # - run: pip install tox + # - run: tox -e lint diff --git a/.gitignore b/.gitignore index accc766..57d7cfa 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ htmlcov .eggs build dist +env* +tests/fake_packages/FakeApp.egg/EGG-INFO diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 44abbb2..0000000 --- a/.hgignore +++ /dev/null @@ -1,13 +0,0 @@ -syntax: glob -*.egg-info/ -*.egg/ -*.pyc -*.class -dist/ -build/ -docs/_build/ -.tox -.project -.pydevproject -.settings -__pycache__ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 07423a8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -sudo: false -dist: xenial -language: python -install: - - pip install tox -script: - - tox -matrix: - include: - - python: 2.7 - env: TOXENV=py27 - - python: 3.4 - env: TOXENV=py34 - - python: 3.5 - env: TOXENV=py35 - - python: 3.6 - env: TOXENV=py36 - - python: 3.7 - env: TOXENV=py37 - - python: pypy - env: TOXENV=pypy - dist: trusty - - python: pypy3 - env: TOXENV=pypy3 - dist: trusty diff --git a/docs/news.rst b/docs/news.rst index a6dbee4..b827317 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -1,6 +1,11 @@ Paste Deployment News ===================== +unreleased +---------- + +* Drop support for Python 2, as well as 3.4, 3.5, and 3.6. + 2.1.1 (2020-10-12) ------------------ diff --git a/paste/deploy/compat.py b/paste/deploy/compat.py deleted file mode 100644 index 05047db..0000000 --- a/paste/deploy/compat.py +++ /dev/null @@ -1,32 +0,0 @@ -# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -"""Python 2<->3 compatibility module""" -import sys - - -def print_(template, *args, **kwargs): - template = str(template) - if args: - template = template % args - elif kwargs: - template = template % kwargs - sys.stdout.writelines(template) - -if sys.version_info < (3, 0): - basestring = basestring - from ConfigParser import ConfigParser - from urllib import unquote - iteritems = lambda d: d.iteritems() - dictkeys = lambda d: d.keys() - - def reraise(t, e, tb): - exec('raise t, e, tb', dict(t=t, e=e, tb=tb)) -else: - basestring = str - from configparser import ConfigParser - from urllib.parse import unquote - iteritems = lambda d: d.items() - dictkeys = lambda d: list(d.keys()) - - def reraise(t, e, tb): - raise e.with_traceback(tb) diff --git a/paste/deploy/converters.py b/paste/deploy/converters.py index c9d87de..30a3290 100644 --- a/paste/deploy/converters.py +++ b/paste/deploy/converters.py @@ -1,14 +1,11 @@ # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -from paste.deploy.compat import basestring - - truthy = frozenset(['true', 'yes', 'on', 'y', 't', '1']) falsy = frozenset(['false', 'no', 'off', 'n', 'f', '0']) def asbool(obj): - if isinstance(obj, basestring): + if isinstance(obj, str): obj = obj.strip().lower() if obj in truthy: return True @@ -27,7 +24,7 @@ def asint(obj): def aslist(obj, sep=None, strip=True): - if isinstance(obj, basestring): + if isinstance(obj, str): lst = obj.split(sep) if strip: lst = [v.strip() for v in lst] diff --git a/paste/deploy/loadwsgi.py b/paste/deploy/loadwsgi.py index 9f3dd0e..2c8f827 100644 --- a/paste/deploy/loadwsgi.py +++ b/paste/deploy/loadwsgi.py @@ -1,13 +1,13 @@ # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -from __future__ import with_statement +from configparser import ConfigParser import os -import sys +import pkg_resources import re +import sys +from urllib.parse import unquote -import pkg_resources -from paste.deploy.compat import ConfigParser, unquote, iteritems, dictkeys from paste.deploy.util import fix_call, lookup_object __all__ = ['loadapp', 'loadserver', 'loadfilter', 'appconfig'] @@ -70,7 +70,7 @@ def defaults(self): Mainly to support defaults using values such as %(here)s """ defaults = ConfigParser.defaults(self).copy() - for key, val in iteritems(defaults): + for key, val in defaults.items(): defaults[key] = self.get('DEFAULT', key) or val return defaults @@ -400,7 +400,7 @@ def __init__(self, filename): self.parser.read_file(f) def update_defaults(self, new_defaults, overwrite=True): - for key, value in iteritems(new_defaults): + for key, value in new_defaults.items(): if not overwrite and key in self.parser._defaults: continue self.parser._defaults[key] = value @@ -660,7 +660,7 @@ def find_egg_entry_point(self, object_type, name=None): dist.location, ', '.join(_flatten(object_type.egg_protocols)), ', '.join(_flatten([ - dictkeys(pkg_resources.get_entry_info(self.spec, prot, name) or {}) + list((pkg_resources.get_entry_info(self.spec, prot, name) or {}).keys()) for prot in protocol_options] or '(no entry points)')))) if len(possible) > 1: raise LookupError( diff --git a/paste/deploy/paster_templates.py b/paste/deploy/paster_templates.py index 9c5f942..edfa97a 100644 --- a/paste/deploy/paster_templates.py +++ b/paste/deploy/paster_templates.py @@ -4,8 +4,6 @@ from paste.script.templates import Template -from paste.deploy.compat import print_ - class PasteDeploy(Template): @@ -30,7 +28,7 @@ def post(self, command, output_dir, vars): ' main = %(package)s.wsgiapp:make_app\n') % vars, indent=False) if command.verbose: - print_('*' * 72) - print_('* Run "paster serve docs/devel_config.ini" to run the sample application') - print_('* on http://localhost:8080') - print_('*' * 72) + print('*' * 72) + print('* Run "paster serve docs/devel_config.ini" to run the sample application') + print('* on http://localhost:8080') + print('*' * 72) diff --git a/paste/deploy/util.py b/paste/deploy/util.py index b6f766a..2a56a07 100644 --- a/paste/deploy/util.py +++ b/paste/deploy/util.py @@ -3,8 +3,6 @@ import inspect import sys -from paste.deploy.compat import reraise - def fix_type_error(exc_info, callable, varargs, kwargs): """ @@ -55,7 +53,7 @@ def fix_call(callable, *args, **kw): val = callable(*args, **kw) except TypeError: exc_info = fix_type_error(None, callable, args, kw) - reraise(*exc_info) + raise exc_info[1] from None return val diff --git a/setup.py b/setup.py index b6906f9..866112a 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="PasteDeploy", - version="2.1.1", + version="3.0.dev0", description="Load, configure, and compose WSGI applications and servers", long_description=readme, classifiers=[ @@ -21,12 +21,11 @@ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP", diff --git a/tests/test_load_package.py b/tests/test_load_package.py index b3fea55..6ba1ad4 100644 --- a/tests/test_load_package.py +++ b/tests/test_load_package.py @@ -1,12 +1,9 @@ from pprint import pprint -import sys - import pkg_resources - -from paste.deploy.compat import print_ +import sys def test_load_package(): - print_('Path:') + print('Path:') pprint(sys.path) - print_(pkg_resources.require('FakeApp')) + print(pkg_resources.require('FakeApp')) diff --git a/tox.ini b/tox.ini index 7819491..4046d48 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] -envlist = py27, py34, py35, py36, py37, pypy, pypy3, +envlist = + py37,py38,py39,py310,pypy3, docs [testenv] @@ -12,8 +13,6 @@ commands = py.test --cov=paste/deploy --cov-report=xml --cov-report=html --cov-report=term-missing {posargs} [testenv:docs] -# pin to 3.5 to match what RTD uses -basepython = python3.5 whitelist_externals = make commands = make -C docs html epub BUILDDIR={envdir} "SPHINXOPTS=-W -E"