diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 7aa119f..05926ee 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -18,12 +18,13 @@ jobs: fail-fast: false matrix: include: - - {name: Linux, python: '3.9', os: ubuntu-latest, tox: py39} - - {name: Windows, python: '3.9', os: windows-latest, tox: py39} - - {name: Mac, python: '3.9', os: macos-latest, tox: py39} + - {name: Linux, python: '3.11', os: ubuntu-latest, tox: py311} + - {name: Windows, python: '3.11', os: windows-latest, tox: py311} + - {name: Mac, python: '3.11', os: macos-latest, tox: py311} + - {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310} + - {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39} - {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38} - {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37} - - {name: 'PyPy2', python: 'pypy-2.7', os: ubuntu-latest, tox: pypy} - {name: 'PyPy3', python: 'pypy-3.9', os: ubuntu-latest, tox: pypy3} steps: - uses: actions/checkout@v2 @@ -45,19 +46,3 @@ jobs: key: pip|${{ runner.os }}|${{ matrix.python }}|${{ hashFiles('setup.py') }}|${{ hashFiles('requirements/*.txt') }} - run: pip install tox - run: tox -e ${{ matrix.tox }} - tests-py27: - name: '2.7' - runs-on: ubuntu-20.04 - container: - image: python:2.7.18-buster - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v2 - - name: update pip - run: | - pip install -U wheel - pip install -U setuptools - python -m pip install -U pip - - run: pip install tox - - run: tox -e py27 \ No newline at end of file diff --git a/clastic/_version.py b/clastic/_version.py index 38ac09b..ba40cb9 100644 --- a/clastic/_version.py +++ b/clastic/_version.py @@ -1,5 +1,4 @@ -from __future__ import unicode_literals -version_info = (21, 1, 2, '') +version_info = (23, 0, 0, 'dev') __version__ = '.'.join(["%s" % part for part in version_info if part or part == 0]) diff --git a/clastic/_werkzeug_serving.py b/clastic/_werkzeug_serving.py index d4660fd..c57d653 100644 --- a/clastic/_werkzeug_serving.py +++ b/clastic/_werkzeug_serving.py @@ -39,7 +39,6 @@ :license: BSD, see LICENSE for more details. """ -from __future__ import with_statement import os import socket @@ -69,7 +68,7 @@ import werkzeug from werkzeug._internal import _log -from werkzeug._compat import iteritems, PY2, reraise, text_type, \ +from werkzeug._compat import iteritems, reraise, text_type, \ wsgi_encoding_dance from werkzeug.urls import url_parse, url_unquote from werkzeug.exceptions import InternalServerError, BadRequest @@ -602,14 +601,6 @@ def restart_with_reloader(): new_environ = os.environ.copy() new_environ['WERKZEUG_RUN_MAIN'] = 'true' - # a weird bug on windows. sometimes unicode strings end up in the - # environment and subprocess.call does not like this, encode them - # to latin1 and continue. - if os.name == 'nt' and PY2: - for key, value in iteritems(new_environ): - if isinstance(value, text_type): - new_environ[key] = value.encode('iso-8859-1') - exit_code = subprocess.call(args, env=new_environ) if exit_code != 3: return exit_code diff --git a/clastic/application.py b/clastic/application.py index c06c725..ebd278e 100644 --- a/clastic/application.py +++ b/clastic/application.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import os import itertools diff --git a/clastic/contrib/obj_browser.py b/clastic/contrib/obj_browser.py index 3ddfa8a..ab31452 100644 --- a/clastic/contrib/obj_browser.py +++ b/clastic/contrib/obj_browser.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import gc import sys diff --git a/clastic/contrib/webtop/top.py b/clastic/contrib/webtop/top.py index 2920967..57c2277 100644 --- a/clastic/contrib/webtop/top.py +++ b/clastic/contrib/webtop/top.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals import os diff --git a/clastic/meta.py b/clastic/meta.py index 880f821..2d5faa4 100644 --- a/clastic/meta.py +++ b/clastic/meta.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import os import sys diff --git a/clastic/middleware/context.py b/clastic/middleware/context.py index 5311027..357f5d4 100644 --- a/clastic/middleware/context.py +++ b/clastic/middleware/context.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import sys if sys.version_info < (3,3,): diff --git a/clastic/middleware/core.py b/clastic/middleware/core.py index f91b90f..992c0fb 100644 --- a/clastic/middleware/core.py +++ b/clastic/middleware/core.py @@ -6,7 +6,7 @@ from werkzeug.utils import cached_property from werkzeug.wrappers import BaseResponse -from ..sinter import make_chain, get_arg_names, PY3, compile_code +from ..sinter import make_chain, get_arg_names, compile_code _INNER_NAME = 'next' diff --git a/clastic/middleware/form.py b/clastic/middleware/form.py index 1d9956d..3e21541 100644 --- a/clastic/middleware/form.py +++ b/clastic/middleware/form.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import sys if sys.version_info < (3,3,): diff --git a/clastic/middleware/profile.py b/clastic/middleware/profile.py index 32114db..4368467 100644 --- a/clastic/middleware/profile.py +++ b/clastic/middleware/profile.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import cProfile from pstats import Stats diff --git a/clastic/render/ashes_templates.py b/clastic/render/ashes_templates.py index 3194bd3..b272106 100644 --- a/clastic/render/ashes_templates.py +++ b/clastic/render/ashes_templates.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals from werkzeug.wrappers import Response diff --git a/clastic/render/chameleon_templates.py b/clastic/render/chameleon_templates.py index 67d1e17..1b1046f 100644 --- a/clastic/render/chameleon_templates.py +++ b/clastic/render/chameleon_templates.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import print_function, unicode_literals import sys try: diff --git a/clastic/render/mako_templates.py b/clastic/render/mako_templates.py index 4563b9c..37baf32 100644 --- a/clastic/render/mako_templates.py +++ b/clastic/render/mako_templates.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import mako from mako import exceptions diff --git a/clastic/render/simple.py b/clastic/render/simple.py index 55dc53e..693696e 100644 --- a/clastic/render/simple.py +++ b/clastic/render/simple.py @@ -3,25 +3,12 @@ import sys import itertools from json import JSONEncoder -import sys -if sys.version_info < (3,3,): - from collections import Mapping, Sized, Iterable -else: - from collections.abc import Mapping, Sized, Iterable +from collections.abc import Mapping, Sized, Iterable from werkzeug.wrappers import Response from .tabular import TabularRender -PY2 = (sys.version_info[0] == 2) - -try: - unicode -except NameError: - # py3 - unicode = str - - class ClasticJSONEncoder(JSONEncoder): def __init__(self, **kw): self.dev_mode = kw.pop('dev_mode', False) @@ -29,8 +16,7 @@ def __init__(self, **kw): kw.setdefault('ensure_ascii', True) kw.setdefault('indent', 2) kw.setdefault('sort_keys', True) - if not PY2: - kw.pop('encoding', None) + kw.pop('encoding', None) super(ClasticJSONEncoder, self).__init__(**kw) def default(self, obj): @@ -114,10 +100,12 @@ def __init__(self, **kwargs): raise TypeError('unexpected keyword arguments: %r' % kwargs) def render_response(self, context, request, _route): - if isinstance(context, (bytes, unicode)): # already serialized + if isinstance(context, str): # already serialized but not encoded + context = context.encode('utf8') + if isinstance(context, bytes): # already serialized and encoded if self._guess_json(context): return Response(context, mimetype="application/json") - elif '=6.0 breaks py27/pypy -pip-tools==5.5.0 -psutil==5.8.0 -pytest<5.0.0 -secure-cookie==0.1.0 # werkzeug goes 1.0 but adds an 0ver dep that's been in prod since 2007. can go to 0.2.0 after py2 drop -tox==3.28.0 # py2 -Werkzeug==1.0.1 -packaging==20.9 # py2-only -platformdirs==2.0.2 # py2-only -pyparsing==2.4.7 # py2-only -pip==20.1.1 -virtualenv==20.15.1 -zipp==1.2.0 +mako +pip-tools +psutil +pytest +secure-cookie # werkzeug goes 1.0 but adds an 0ver dep that's been in prod since 2007. can go to 0.2.0 after py2 drop +tox +Werkzeug<2 + diff --git a/requirements.txt b/requirements.txt index b754a3c..3c7fd02 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,40 +1,43 @@ # -# This file is autogenerated by pip-compile with python 3.7 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.7 +# by the following command: # # pip-compile --annotation-style=line --strip-extras requirements.in # ashes==19.2.0 # via -r requirements.in -atomicwrites==1.4.1 # via pytest -attrs==21.4.0 # via -r requirements.in, glom, pytest -boltons==23.0.0 # via -r requirements.in, face, glom +boltons==23.1.1 # via -r requirements.in, face +build==1.0.3 # via pip-tools +cachetools==5.3.2 # via tox chameleon==3.9.1 # via -r requirements.in -click==7.1.2 # via -r requirements.in, pip-tools -coverage==5.5 # via -r requirements.in -distlib==0.3.7 # via virtualenv -face==20.1.1 # via -r requirements.in, glom -filelock==3.2.1 # via -r requirements.in, tox, virtualenv -glom==23.1.1 # via -r requirements.in -importlib-metadata==2.1.3 # via -r requirements.in, pytest, tox, virtualenv -mako==1.1.6 # via -r requirements.in -markupsafe==1.1.1 # via -r requirements.in, mako -more-itertools==5.0.0 # via -r requirements.in, pytest -packaging==20.9 # via -r requirements.in, pytest, tox -pip-tools==5.5.0 # via -r requirements.in -platformdirs==2.0.2 # via -r requirements.in, virtualenv -pluggy==0.13.1 # via pytest, tox -psutil==5.8.0 # via -r requirements.in -py==1.11.0 # via pytest, tox -pyparsing==2.4.7 # via -r requirements.in, packaging -pytest==4.6.11 # via -r requirements.in -secure-cookie==0.1.0 # via -r requirements.in -six==1.16.0 # via more-itertools, pytest, tox, virtualenv -# tomli==2.0.1 # via tox <- shouldn't be. tomli was added in tox>=4 -tox==3.28.0 # via -r requirements.in -virtualenv==20.15.1 # via -r requirements.in, tox -wcwidth==0.2.8 # via pytest +chardet==5.2.0 # via tox +click==8.1.7 # via pip-tools +colorama==0.4.6 # via tox +coverage==7.2.7 # via -r requirements.in +distlib==0.3.8 # via virtualenv +exceptiongroup==1.2.0 # via pytest +face==22.0.0 # via -r requirements.in +filelock==3.12.2 # via tox, virtualenv +importlib-metadata==6.7.0 # via build, click, mako, pluggy, pytest, tox, virtualenv +iniconfig==2.0.0 # via pytest +mako==1.2.4 # via -r requirements.in +markupsafe==2.1.3 # via mako +packaging==23.2 # via build, pyproject-api, pytest, tox +pip-tools==6.14.0 # via -r requirements.in +platformdirs==4.0.0 # via tox, virtualenv +pluggy==1.2.0 # via pytest, tox +psutil==5.9.7 # via -r requirements.in +pyproject-api==1.5.3 # via tox +pyproject-hooks==1.0.0 # via build +pytest==7.4.3 # via -r requirements.in +secure-cookie==0.2.0 # via -r requirements.in +tomli==2.0.1 # via build, pip-tools, pyproject-api, pytest, tox +tox==4.8.0 # via -r requirements.in +typing-extensions==4.7.1 # via importlib-metadata, platformdirs, tox +virtualenv==20.25.0 # via tox werkzeug==1.0.1 # via -r requirements.in, secure-cookie -zipp==1.2.0 # via importlib-metadata +wheel==0.42.0 # via pip-tools +zipp==3.15.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip +# setuptools diff --git a/setup.py b/setup.py index d8a4cb3..bcfebe5 100644 --- a/setup.py +++ b/setup.py @@ -5,8 +5,7 @@ """ import os -import imp -import sys +import importlib from setuptools import setup @@ -15,9 +14,15 @@ __url__ = 'https://github.com/mahmoud/clastic' __license__ = 'BSD' +def import_path(module_name, path): + spec = importlib.util.spec_from_file_location(module_name, path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + CUR_PATH = os.path.abspath(os.path.dirname(__file__)) _version_mod_path = os.path.join(CUR_PATH, 'clastic', '_version.py') -_version_mod = imp.load_source('_version', _version_mod_path) +_version_mod = import_path('_version', _version_mod_path) __version__ = _version_mod.__version__ @@ -25,8 +30,6 @@ ' explicit development practices while eliminating' ' global state.') -if sys.version_info < (2,7): - raise NotImplementedError("Sorry, clastic only supports Python >2.6") setup(name='clastic', version=__version__, @@ -48,14 +51,14 @@ 'attrs<=21.4.0', 'boltons>=20.0.0', 'glom<=23.1.1', - 'secure-cookie==0.1.0'], + 'secure-cookie==0.1.0,<=0.2.0'], license=__license__, platforms='any', tests_require=[ 'chameleon==3.9.1', - 'Mako==1.1.6', - 'pytest==4.6.9', - 'psutil==5.8.0'], + 'Mako', + 'pytest', + 'psutil'], classifiers=[ 'Intended Audience :: Developers', 'Development Status :: 5 - Production/Stable', @@ -66,11 +69,12 @@ 'Topic :: Internet :: WWW/HTTP :: WSGI :: Server', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries', 'Topic :: Software Development :: Libraries :: Application Frameworks', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10'] + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + ] ) @@ -79,13 +83,16 @@ * tox * git commit (if applicable) -* Bump setup.py version off of -dev +* Bump clastic/_version version off of -dev * git commit -a -m "bump version for x.y.z release" -* python setup.py sdist bdist_wheel upload -* git tag -a x.y.z -m "brief summary" +* rm -rf dist/* +* python setup.py sdist bdist_wheel +* twine upload dist/* +* bump docs/conf.py version * write CHANGELOG * git commit -* bump setup.py version onto n+1 dev +* git tag -a x.y.z -m "brief summary" +* bump clastic/_version.py version onto n+1 dev * git commit * git push diff --git a/tox.ini b/tox.ini index 69dec3e..491c93c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,19 +1,13 @@ [tox] -envlist = py27,py37,py38,py39,pypy,coverage-report,packaging +envlist = py37,py38,py39,py310,py311,pypy3,coverage-report,packaging [testenv] changedir = .tox deps = -rrequirements.txt commands = coverage run --parallel --rcfile {toxinidir}/.tox-coveragerc -m pytest {envsitepackagesdir}/clastic {posargs} -[testenv:pypy] -requires = pip==20.1.1 -install_command = python -m pip install {opts} pip==20.1.1 {packages} - -# Uses default basepython otherwise reporting doesn't work on Travis where -# Python 3.6 is only available in 3.6 jobs. [testenv:coverage-report] -depends = py27,py37,py38,py39,pypy +depends = py37,py38,py39,py310,py311,pypy3 changedir = .tox deps = coverage commands = coverage combine --rcfile {toxinidir}/.tox-coveragerc @@ -24,6 +18,6 @@ commands = coverage combine --rcfile {toxinidir}/.tox-coveragerc [testenv:packaging] changedir = {toxinidir} deps = - readme_renderer==37.3 + readme_renderer commands = python setup.py check --metadata --restructuredtext --strict