From cb6def05fdea2b2c40bcc154a159cfae0ed46b92 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Thu, 3 Nov 2022 16:23:33 +0100 Subject: - update with meta/config and add support for Python 3.9, 3.10 and 3.11 --- .coveragerc | 25 ++- .editorconfig | 39 ++++ .github/workflows/tests.yml | 485 ++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 40 ++-- .manylinux-install.sh | 53 ++++- .manylinux.sh | 13 +- .meta.toml | 26 +++ .travis.yml | 104 ---------- CHANGES.rst | 4 +- CONTRIBUTING.md | 23 +++ MANIFEST.in | 22 +- appveyor.yml | 27 ++- bootstrap.py | 210 ------------------- setup.cfg | 34 +++- setup.py | 13 +- tox.ini | 65 ++++-- 16 files changed, 804 insertions(+), 379 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/tests.yml create mode 100644 .meta.toml delete mode 100644 .travis.yml create mode 100644 CONTRIBUTING.md delete mode 100644 bootstrap.py diff --git a/.coveragerc b/.coveragerc index af40312..03f2c19 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,6 +1,29 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code [run] -source = src +source = zope.i18nmessageid +# New in 5.0; required for the GHA coveralls submission. +relative_files = True +branch = true + +[paths] +source = + src/ + .tox/*/lib/python*/site-packages/ + .tox/pypy*/site-packages/ [report] +show_missing = true +precision = 2 exclude_lines = + except ImportError: + if __name__ == '__main__': pragma: no cover + pragma: nocover + raise AssertionError + raise NotImplementedError + raise unittest.Skip + self.fail\( + +[html] +directory = parts/htmlcov diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d3c4f2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,39 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +# +# EditorConfig Configuration file, for more details see: +# http://EditorConfig.org +# EditorConfig is a convention description, that could be interpreted +# by multiple editors to enforce common coding conventions for specific +# file types + +# top-most EditorConfig file: +# Will ignore other EditorConfig files in Home directory or upper tree level. +root = true + + +[*] # For All Files +# Unix-style newlines with a newline ending every file +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +# Set default charset +charset = utf-8 +# Indent style default +indent_style = space +# Max Line Length - a hard line wrap, should be disabled +max_line_length = off + +[*.{py,cfg,ini}] +# 4 space indentation +indent_size = 4 + +[*.{yml,zpt,pt,dtml,zcml}] +# 2 space indentation +indent_size = 2 + +[{Makefile,.gitmodules}] +# Tab indentation (no size specified, but view as 4 spaces) +indent_style = tab +indent_size = unset +tab_width = unset diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..a62f6fb --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,485 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +### +# Initially copied from +# https://github.com/actions/starter-workflows/blob/main/ci/python-package.yml +# And later based on the version jamadden updated at +# gevent/gevent, and then at zodb/relstorage and zodb/perfmetrics +# +# Original comment follows. +### +### +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions +### + +### +# Important notes on GitHub actions: +# +# - We only get 2,000 free minutes a month (private repos) +# - We only get 500MB of artifact storage +# - Cache storage is limited to 7 days and 5GB. +# - macOS minutes are 10x as expensive as Linux minutes +# - windows minutes are twice as expensive. +# +# So keep those workflows light. Note: Currently, they seem to be free +# and unlimited for open source projects. But for how long... +# +# In December 2020, github only supports x86/64. If we wanted to test +# on other architectures, we can use docker emulation, but there's no +# native support. It works, but is slow. +# +# Another major downside: You can't just re-run the job for one part +# of the matrix. So if there's a transient test failure that hit, say, 3.8, +# to get a clean run every version of Python runs again. That's bad. +# https://github.community/t/ability-to-rerun-just-a-single-job-in-a-workflow/17234/65 + +name: tests + + +# Triggers the workflow on push or pull request events and periodically +on: + push: + pull_request: + schedule: + - cron: '0 12 * * 0' # run once a week on Sunday + # Allow to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + # Weirdly, this has to be a top-level key, not ``defaults.env`` + PYTHONHASHSEED: 8675309 + PYTHONUNBUFFERED: 1 + PYTHONDONTWRITEBYTECODE: 1 + PYTHONDEVMODE: 1 + PYTHONFAULTHANDLER: 1 + ZOPE_INTERFACE_STRICT_IRO: 1 + + PIP_UPGRADE_STRATEGY: eager + # Don't get warnings about Python 2 support being deprecated. We + # know. The env var works for pip 20. + PIP_NO_PYTHON_VERSION_WARNING: 1 + PIP_NO_WARN_SCRIPT_LOCATION: 1 + + CFLAGS: -O3 -pipe + CXXFLAGS: -O3 -pipe + # Uploading built wheels for releases. + # TWINE_PASSWORD is encrypted and stored directly in the + # github repo settings. + TWINE_USERNAME: __token__ + + ### + # caching + # This is where we'd set up ccache, but this compiles so fast its not worth it. + ### + + +jobs: + # Because sharing code/steps is so hard, and because it can be + # extremely valuable to be able to get binary wheels without + # uploading to PyPI and even if there is some failure, (e.g., for + # other people to test/debug), the strategy is to divide the process + # into several different jobs. The first builds and saves the binary + # wheels. It has dependent jobs that download and install the wheel + # to run tests, build docs, and perform linting. Building the + # manylinux wheels is an independent set of jobs. + # + # This division is time-saving for projects that take awhile to + # build, but somewhat less of a clear-cut win given how quick this + # is to compile (at least at this writing). + build-package: + # Sigh. Note that the matrix must be kept in sync + # with `test`, and `docs` must use a subset. + runs-on: ${{ matrix.os }} + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + strategy: + fail-fast: false + matrix: + python-version: + - "2.7" + - "3.5" + - "pypy-2.7" + - "pypy-3.7" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" + - "3.11" + os: [ubuntu-20.04, macos-latest] + exclude: + - os: macos-latest + python-version: "pypy-2.7" + - os: macos-latest + python-version: "pypy-3.7" + - os: macos-latest + python-version: "3.5" + + steps: + - name: checkout + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + ### + # Caching. + # This actually *restores* a cache and schedules a cleanup action + # to save the cache. So it must come before the thing we want to use + # the cache. + ### + - name: Get pip cache dir + id: pip-cache + run: | + echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install Build Dependencies (PyPy2) + if: > + startsWith(matrix.python-version, 'pypy-2.7') + run: | + pip install -U pip + pip install -U setuptools wheel twine "cffi != 1.15.1" + - name: Install Build Dependencies (other Python versions) + if: > + !startsWith(matrix.python-version, 'pypy-2.7') + run: | + pip install -U pip + pip install -U setuptools wheel twine cffi + + - name: Build zope.i18nmessageid (Python 3.10 on MacOS) + if: > + startsWith(runner.os, 'Mac') + && startsWith(matrix.python-version, '3.10') + env: + _PYTHON_HOST_PLATFORM: macosx-11-x86_64 + run: | + # Next, build the wheel *in place*. This helps ccache, and also lets us cache the configure + # output (pip install uses a random temporary directory, making this difficult). + python setup.py build_ext -i + python setup.py bdist_wheel + # Also install it, so that we get dependencies in the (pip) cache. + pip install -U 'faulthandler; python_version == "2.7" and platform_python_implementation == "CPython"' + pip install .[test] + + - name: Build zope.i18nmessageid (all other versions) + if: > + !startsWith(runner.os, 'Mac') + || !startsWith(matrix.python-version, '3.10') + run: | + # Next, build the wheel *in place*. This helps ccache, and also lets us cache the configure + # output (pip install uses a random temporary directory, making this difficult). + python setup.py build_ext -i + python setup.py bdist_wheel + # Also install it, so that we get dependencies in the (pip) cache. + pip install -U 'faulthandler; python_version == "2.7" and platform_python_implementation == "CPython"' + pip install .[test] + + - name: Check zope.i18nmessageid build + run: | + ls -l dist + twine check dist/* + - name: Upload zope.i18nmessageid wheel + uses: actions/upload-artifact@v2 + with: + name: zope.i18nmessageid-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/*whl + - name: Publish package to PyPI (mac) + # We cannot 'uses: pypa/gh-action-pypi-publish@v1.4.1' because + # that's apparently a container action, and those don't run on + # the Mac. + if: > + github.event_name == 'push' + && startsWith(github.ref, 'refs/tags') + && startsWith(runner.os, 'Mac') + && !startsWith(matrix.python-version, 'pypy') + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + run: | + twine upload --skip-existing dist/* + + test: + needs: build-package + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + python-version: + - "2.7" + - "3.5" + - "pypy-2.7" + - "pypy-3.7" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" + - "3.11" + os: [ubuntu-20.04, macos-latest] + exclude: + - os: macos-latest + python-version: "pypy-2.7" + - os: macos-latest + python-version: "pypy-3.7" + - os: macos-latest + python-version: "3.5" + + steps: + - name: checkout + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + ### + # Caching. + # This actually *restores* a cache and schedules a cleanup action + # to save the cache. So it must come before the thing we want to use + # the cache. + ### + - name: Get pip cache dir + id: pip-cache + run: | + echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Download zope.i18nmessageid wheel + uses: actions/download-artifact@v2 + with: + name: zope.i18nmessageid-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install zope.i18nmessageid + run: | + pip install -U wheel setuptools + pip install -U coverage + pip install -U 'faulthandler; python_version == "2.7" and platform_python_implementation == "CPython"' + # Unzip into src/ so that testrunner can find the .so files + # when we ask it to load tests from that directory. This + # might also save some build time? + unzip -n dist/zope.i18nmessageid-*whl -d src + pip install -U -e .[test] + - name: Run tests with C extensions + if: ${{ !startsWith(matrix.python-version, 'pypy') }} + run: | + python -m coverage run -p -m zope.testrunner --test-path=src --auto-color --auto-progress + - name: Run tests without C extensions + run: + # coverage makes PyPy run about 3x slower! + PURE_PYTHON=1 python -m coverage run -p -m zope.testrunner --test-path=src --auto-color --auto-progress + - name: Report Coverage + run: | + coverage combine + coverage report -i + - name: Submit to Coveralls + # This is a container action, which only runs on Linux. + if: ${{ startsWith(runner.os, 'Linux') }} + uses: AndreMiras/coveralls-python-action@develop + with: + parallel: true + + coveralls_finish: + needs: test + runs-on: ubuntu-20.04 + steps: + - name: Coveralls Finished + uses: AndreMiras/coveralls-python-action@develop + with: + parallel-finished: true + + docs: + needs: build-package + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.9"] + os: [ubuntu-20.04] + + steps: + - name: checkout + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + ### + # Caching. + # This actually *restores* a cache and schedules a cleanup action + # to save the cache. So it must come before the thing we want to use + # the cache. + ### + - name: Get pip cache dir + id: pip-cache + run: | + echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Download zope.i18nmessageid wheel + uses: actions/download-artifact@v2 + with: + name: zope.i18nmessageid-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install zope.i18nmessageid + run: | + pip install -U wheel + pip install -U coverage + pip install -U "`ls dist/zope.i18nmessageid-*.whl`[docs]" + - name: Build docs + env: + ZOPE_INTERFACE_STRICT_IRO: 1 + run: | + sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html + + lint: + needs: build-package + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.9"] + os: [ubuntu-20.04] + + steps: + - name: checkout + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + ### + # Caching. + # This actually *restores* a cache and schedules a cleanup action + # to save the cache. So it must come before the thing we want to use + # the cache. + ### + - name: Get pip cache dir + id: pip-cache + run: | + echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Download zope.i18nmessageid wheel + uses: actions/download-artifact@v2 + with: + name: zope.i18nmessageid-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install zope.i18nmessageid + run: | + pip install -U pip + pip install -U wheel + pip install -U `ls dist/zope.i18nmessageid-*`[test] + - name: Lint + # We only need to do this on one version, and it should be Python 3, because + # pylint has stopped updating for Python 2. + # TODO: Pick a linter and configuration and make this step right. + run: | + pip install -U pylint + # python -m pylint --limit-inference-results=1 --rcfile=.pylintrc zope.i18nmessageid -f parseable -r n + + manylinux: + runs-on: ubuntu-20.04 + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + # We use a regular Python matrix entry to share as much code as possible. + strategy: + matrix: + python-version: ["3.9"] + image: [manylinux2010_x86_64, manylinux2010_i686, manylinux2014_aarch64] + + steps: + - name: checkout + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + ### + # Caching. + # This actually *restores* a cache and schedules a cleanup action + # to save the cache. So it must come before the thing we want to use + # the cache. + ### + - name: Get pip cache dir + id: pip-cache + run: | + echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ runner.os }}-pip_manylinux-${{ matrix.image }}-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Update pip + run: pip install -U pip + - name: Build zope.i18nmessageid (x86_64) + if: matrix.image == 'manylinux2010_x86_64' + # An alternate way to do this is to run the container directly with a uses: + # and then the script runs inside it. That may work better with caching. + # See https://github.com/pyca/bcrypt/blob/f6b5ee2eda76d077c531362ac65e16f045cf1f29/.github/workflows/wheel-builder.yml + # The 2010 image is the most recent spec that comes with Python 2.7, + # and only up through the tag 2021-02-06-3d322a5 + env: + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} + run: | + bash .manylinux.sh + - name: Build zope.i18nmessageid (i686) + if: matrix.image == 'manylinux2010_i686' + env: + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} + PRE_CMD: linux32 + run: | + bash .manylinux.sh + - name: Build zope.i18nmessageid (aarch64) + if: matrix.image == 'manylinux2014_aarch64' + env: + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} + run: | + # First we must enable emulation + docker run --rm --privileged hypriot/qemu-register + bash .manylinux.sh + + - name: Upload zope.i18nmessageid wheels + uses: actions/upload-artifact@v2 + with: + path: wheelhouse/*whl + name: manylinux_${{ matrix.image }}_wheels.zip + - name: Restore pip cache permissions + run: sudo chown -R $(whoami) ${{ steps.pip-cache.outputs.dir }} + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@v1.4.1 + if: > + github.event_name == 'push' + && startsWith(github.ref, 'refs/tags') + with: + user: __token__ + password: ${{ secrets.TWINE_PASSWORD }} + skip_existing: true + packages_dir: wheelhouse/ diff --git a/.gitignore b/.gitignore index 3553a3a..6e5e8ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,32 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +*.dll +*.egg-info/ +*.profraw *.pyc +*.pyo *.so -__pycache__ -build -*.egg-info +.coverage +.coverage.* +.eggs/ .installed.cfg -bin -develop-eggs -eggs -parts -docs/_build -.tox -nosetests.xml +.mr.developer.cfg +.tox/ +.vscode/ +__pycache__/ +bin/ +build/ coverage.xml -.coverage -htmlcov/ +develop-eggs/ +develop/ +dist/ +docs/_build +eggs/ +etc/ +lib/ +lib64 +log/ +parts/ +pyvenv.cfg +testing.log +var/ diff --git a/.manylinux-install.sh b/.manylinux-install.sh index e9daeac..cb697de 100755 --- a/.manylinux-install.sh +++ b/.manylinux-install.sh @@ -1,16 +1,65 @@ #!/usr/bin/env bash +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code set -e -x +# Running inside docker +# Set a cache directory for pip. This was +# mounted to be the same as it is outside docker so it +# can be persisted. +export XDG_CACHE_HOME="/cache" +# XXX: This works for macOS, where everything bind-mounted +# is seen as owned by root in the container. But when the host is Linux +# the actual UIDs come through to the container, triggering +# pip to disable the cache when it detects that the owner doesn't match. +# The below is an attempt to fix that, taken from bcrypt. It seems to work on +# Github Actions. +if [ -n "$GITHUB_ACTIONS" ]; then + echo Adjusting pip cache permissions + mkdir -p $XDG_CACHE_HOME/pip + chown -R $(whoami) $XDG_CACHE_HOME +fi +ls -ld /cache +ls -ld /cache/pip + +# We need some libraries because we build wheels from scratch: +yum -y install libffi-devel + +tox_env_map() { + case $1 in + *"cp27"*) echo 'py27';; + *"cp35"*) echo 'py35';; + *"cp36"*) echo 'py36';; + *"cp37"*) echo 'py37';; + *"cp38"*) echo 'py38';; + *"cp39"*) echo 'py39';; + *"cp310"*) echo 'py310';; + *"cp311"*) echo 'py311';; + *) echo 'py';; + esac +} + # Compile wheels for PYBIN in /opt/python/*/bin; do - if [[ "${PYBIN}" == *"cp27"* ]] || \ + if \ + [[ "${PYBIN}" == *"cp27"* ]] || \ [[ "${PYBIN}" == *"cp35"* ]] || \ + [[ "${PYBIN}" == *"cp311"* ]] || \ [[ "${PYBIN}" == *"cp36"* ]] || \ [[ "${PYBIN}" == *"cp37"* ]] || \ - [[ "${PYBIN}" == *"cp38"* ]]; then + [[ "${PYBIN}" == *"cp38"* ]] || \ + [[ "${PYBIN}" == *"cp39"* ]] || \ + [[ "${PYBIN}" == *"cp310"* ]] ; then "${PYBIN}/pip" install -e /io/ "${PYBIN}/pip" wheel /io/ -w wheelhouse/ + if [ `uname -m` == 'aarch64' ]; then + cd /io/ + ${PYBIN}/pip install tox + TOXENV=$(tox_env_map "${PYBIN}") + ${PYBIN}/tox -e ${TOXENV} + cd .. + fi rm -rf /io/build /io/*.egg-info fi done diff --git a/.manylinux.sh b/.manylinux.sh index 2fed778..ea4ef41 100755 --- a/.manylinux.sh +++ b/.manylinux.sh @@ -1,5 +1,16 @@ #!/usr/bin/env bash +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code set -e -x -docker run --rm -v "$(pwd)":/io $DOCKER_IMAGE $PRE_CMD /io/.manylinux-install.sh +# Mount the current directory as /io +# Mount the pip cache directory as /cache +# `pip cache` requires pip 20.1 +echo Setting up caching +python --version +python -mpip --version +LCACHE="$(dirname `python -mpip cache dir`)" +echo Sharing pip cache at $LCACHE $(ls -ld $LCACHE) + +docker run --rm -e GITHUB_ACTIONS -v "$(pwd)":/io -v "$LCACHE:/cache" $DOCKER_IMAGE $PRE_CMD /io/.manylinux-install.sh diff --git a/.meta.toml b/.meta.toml new file mode 100644 index 0000000..f8a2810 --- /dev/null +++ b/.meta.toml @@ -0,0 +1,26 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +[meta] +template = "c-code" +commit-id = "b4dd6f9ffd3d6a2cde7dc70512c62d4c7ed22cd6" + +[python] +with-appveyor = true +with-windows = false +with-pypy = true +with-future-python = false +with-legacy-python = true +with-docs = true +with-sphinx-doctests = false + +[tox] +use-flake8 = false + +[coverage] +fail-under = 0 + +[manifest] +additional-rules = [ + "include *.sh", + "recursive-include docs *.bat", + ] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c8eb5b5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,104 +0,0 @@ -language: python - -env: - global: - TWINE_USERNAME: zope.wheelbuilder - TWINE_PASSWORD: - secure: "VQxFZo+4W6XAX94+kJY8dx90uKnmsJIBLPHruK5Xz2E7bFM3t7MlcFN5A0v90fB7BJUiKyQpO67R+wF3XIaqd7UDcI0NVcNihKkzkP8rE4CLsHIhjWU9lKuO0juXegv+0p8ztHV9anvSXN3WbaYk7elXiv4CXxpTeVBy77KK8gE=" - -python: - - 2.7 - - 3.5 - - 3.6 - - 3.7 - - 3.8 - - pypy - - pypy3 - -jobs: - include: - - # manylinux wheel builds - - name: 64-bit manylinux wheels (all Pythons) - services: docker - env: DOCKER_IMAGE=quay.io/pypa/manylinux2010_x86_64 - install: docker pull $DOCKER_IMAGE - script: bash .manylinux.sh - - - name: 32-bit manylinux wheels (all Pythons) - services: docker - env: DOCKER_IMAGE=quay.io/pypa/manylinux2010_i686 PRE_CMD=linux32 - install: docker pull $DOCKER_IMAGE - script: bash .manylinux.sh - - # It's important to use 'macpython' builds to get the least - # restrictive wheel tag. It's also important to avoid - # 'homebrew 3' because it floats instead of being a specific version. - - name: Python 2.7 wheels for MacOS - os: osx - language: generic - env: TERRYFY_PYTHON='macpython 2.7.17' - - name: Python 3.5 wheels for MacOS - os: osx - language: generic - env: TERRYFY_PYTHON='macpython 3.5' - - name: Python 3.6 wheels for MacOS - os: osx - language: generic - env: TERRYFY_PYTHON='macpython 3.6.2' - - name: Python 3.7 wheels for MacOS - os: osx - language: generic - env: TERRYFY_PYTHON='macpython 3.7.0' - - name: Python 3.8 wheels for MacOS - os: osx - language: generic - env: TERRYFY_PYTHON='macpython 3.8.0' - -before_install: - - | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - git clone https://github.com/MacPython/terryfy - source terryfy/travis_tools.sh - get_python_environment $TERRYFY_PYTHON venv - fi - -install: - - pip install -U pip setuptools - - pip install -U coveralls - - pip install -U -e ".[test]" - -script: - - python --version - - coverage run -m zope.testrunner --test-path=src --auto-color --auto-progress - - python setup.py -q bdist_wheel - -after_success: - - coveralls - - | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - # macpython 3.5 doesn't support recent TLS protocols which causes twine - # upload to fail, so we use the system Python to run twine - /usr/bin/python -m ensurepip --user - /usr/bin/python -m pip install --user -U pip - /usr/bin/python -m pip install --user -U -I twine - /usr/bin/python -m twine check dist/* - if [[ $TRAVIS_TAG ]]; then - /usr/bin/python -m twine upload --skip-existing dist/* - fi - fi - - | - if [[ -n "$DOCKER_IMAGE" ]]; then - pip install twine - twine check wheelhouse/* - if [[ $TRAVIS_TAG ]]; then - twine upload --skip-existing wheelhouse/* - fi - fi - -notifications: - email: false - -cache: pip -before_cache: - - rm -f $HOME/.cache/pip/log/debug.log diff --git a/CHANGES.rst b/CHANGES.rst index 48b1772..9f70d79 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,10 +2,10 @@ Changes ========= -5.0.2 (unreleased) +5.1.0 (unreleased) ================== -- Nothing changed yet. +- Added support for Python 3.9, 3.10 and 3.11. 5.0.1 (2020-03-10) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e6d84b8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,23 @@ + +# Contributing to zopefoundation projects + +The projects under the zopefoundation GitHub organization are open source and +welcome contributions in different forms: + +* bug reports +* code improvements and bug fixes +* documentation improvements +* pull request reviews + +For any changes in the repository besides trivial typo fixes you are required +to sign the contributor agreement. See +https://www.zope.dev/developer/becoming-a-committer.html for details. + +Please visit our [Developer +Guidelines](https://www.zope.dev/developer/guidelines.html) if you'd like to +contribute code changes and our [guidelines for reporting +bugs](https://www.zope.dev/developer/reporting-bugs.html) if you want to file a +bug report. diff --git a/MANIFEST.in b/MANIFEST.in index 9dd3f6b..079346c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,18 +1,18 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +include *.md include *.rst include *.txt -include *.py include buildout.cfg include tox.ini -include .travis.yml +include appveyor.yml include .coveragerc -recursive-include docs *.rst *.bat *.py Makefile .gitignore -recursive-include src *.zcml +recursive-include docs *.py +recursive-include docs *.rst +recursive-include docs *.txt +recursive-include docs Makefile -global-exclude *.dll -global-exclude *.pyc -global-exclude *.pyo -global-exclude *.so - -# added by check_manifest.py -include *.yml +recursive-include src *.py +include *.sh +recursive-include docs *.bat diff --git a/appveyor.yml b/appveyor.yml index f0a6c96..2311d21 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,6 @@ -# Currently the builds use @mgedmin's Appveyor account. The PyPI token belongs -# to zope.wheelbuilder, which is managed by @mgedmin and @dataflake. - +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code environment: - global: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: - secure: aoZC/+rvJKg8B5GMGIxd1VZ0Oxtmc0lPMiqT2wHP5qBRoZf6tEB7n9u7uCIifcAX1IWsLCRF7DKWvvCQTFJL5HcQvXFQSnEuXvdMT/utFFx9eCCy+Cu+WuWkasGCG+gx9uhMTe01mixi8yujgVj894Xjdv5YyNH2dPeqV5kInTzYrOmKZs1FTvKTlYZNHyYWRnYhyaLBn4FmmeuXuFcd5o05jkaa2dnerW85F3sr7mWbCgL4GpEQ59rYX34Cl4EdEXw+IViTyFWJuZp+k9GCUnzxAmA+vlfoSbZ6JfvTLaU= matrix: - python: 27 @@ -18,8 +13,15 @@ environment: - python: 37-x64 - python: 38 - python: 38-x64 + - python: 39 + - python: 39-x64 + - python: 310 + - python: 310-x64 + - python: 311 + - python: 311-x64 install: + - "SET PYTHONVERSION=%PYTHON%" - "SET PATH=C:\\Python%PYTHON%;c:\\Python%PYTHON%\\scripts;%PATH%" - ps: | $env:PYTHON = "C:\\Python${env:PYTHON}" @@ -29,20 +31,23 @@ install: } - ps: if (-not (Test-Path $env:PYTHON)) { throw "No $env:PYTHON" } - echo "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 > "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64\vcvars64.bat" - - pip install -e .[test] + - python -m pip install -U pip + - pip install -U setuptools wheel + - pip install -U -e .[test] + +matrix: + fast_finish: true build_script: - - pip install -U setuptools wheel - python -W ignore setup.py -q bdist_wheel test_script: - zope-testrunner --test-path=src - artifacts: - path: 'dist\*.whl' name: wheel deploy_script: - - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE) { pip install twine; twine upload --skip-existing dist/* } + - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE) { pip install twine; twine upload --skip-existing dist\*.whl } deploy: on diff --git a/bootstrap.py b/bootstrap.py deleted file mode 100644 index a459921..0000000 --- a/bootstrap.py +++ /dev/null @@ -1,210 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Foundation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Bootstrap a buildout-based project - -Simply run this script in a directory containing a buildout.cfg. -The script accepts buildout command-line options, so you can -use the -c option to specify an alternate configuration file. -""" - -import os -import shutil -import sys -import tempfile - -from optparse import OptionParser - -__version__ = '2015-07-01' -# See zc.buildout's changelog if this version is up to date. - -tmpeggs = tempfile.mkdtemp(prefix='bootstrap-') - -usage = '''\ -[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] - -Bootstraps a buildout-based project. - -Simply run this script in a directory containing a buildout.cfg, using the -Python that you want bin/buildout to use. - -Note that by using --find-links to point to local resources, you can keep -this script from going over the network. -''' - -parser = OptionParser(usage=usage) -parser.add_option("--version", - action="store_true", default=False, - help=("Return bootstrap.py version.")) -parser.add_option("-t", "--accept-buildout-test-releases", - dest='accept_buildout_test_releases', - action="store_true", default=False, - help=("Normally, if you do not specify a --version, the " - "bootstrap script and buildout gets the newest " - "*final* versions of zc.buildout and its recipes and " - "extensions for you. If you use this flag, " - "bootstrap and buildout will get the newest releases " - "even if they are alphas or betas.")) -parser.add_option("-c", "--config-file", - help=("Specify the path to the buildout configuration " - "file to be used.")) -parser.add_option("-f", "--find-links", - help=("Specify a URL to search for buildout releases")) -parser.add_option("--allow-site-packages", - action="store_true", default=False, - help=("Let bootstrap.py use existing site packages")) -parser.add_option("--buildout-version", - help="Use a specific zc.buildout version") -parser.add_option("--setuptools-version", - help="Use a specific setuptools version") -parser.add_option("--setuptools-to-dir", - help=("Allow for re-use of existing directory of " - "setuptools versions")) - -options, args = parser.parse_args() -if options.version: - print("bootstrap.py version %s" % __version__) - sys.exit(0) - - -###################################################################### -# load/install setuptools - -try: - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen - -ez = {} -if os.path.exists('ez_setup.py'): - exec(open('ez_setup.py').read(), ez) -else: - exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez) - -if not options.allow_site_packages: - # ez_setup imports site, which adds site packages - # this will remove them from the path to ensure that incompatible versions - # of setuptools are not in the path - import site - # inside a virtualenv, there is no 'getsitepackages'. - # We can't remove these reliably - if hasattr(site, 'getsitepackages'): - for sitepackage_path in site.getsitepackages(): - # Strip all site-packages directories from sys.path that - # are not sys.prefix; this is because on Windows - # sys.prefix is a site-package directory. - if sitepackage_path != sys.prefix: - sys.path[:] = [x for x in sys.path - if sitepackage_path not in x] - -setup_args = dict(to_dir=tmpeggs, download_delay=0) - -if options.setuptools_version is not None: - setup_args['version'] = options.setuptools_version -if options.setuptools_to_dir is not None: - setup_args['to_dir'] = options.setuptools_to_dir - -ez['use_setuptools'](**setup_args) -import setuptools -import pkg_resources - -# This does not (always?) update the default working set. We will -# do it. -for path in sys.path: - if path not in pkg_resources.working_set.entries: - pkg_resources.working_set.add_entry(path) - -###################################################################### -# Install buildout - -ws = pkg_resources.working_set - -setuptools_path = ws.find( - pkg_resources.Requirement.parse('setuptools')).location - -# Fix sys.path here as easy_install.pth added before PYTHONPATH -cmd = [sys.executable, '-c', - 'import sys; sys.path[0:0] = [%r]; ' % setuptools_path + - 'from setuptools.command.easy_install import main; main()', - '-mZqNxd', tmpeggs] - -find_links = os.environ.get( - 'bootstrap-testing-find-links', - options.find_links or - ('http://downloads.buildout.org/' - if options.accept_buildout_test_releases else None) - ) -if find_links: - cmd.extend(['-f', find_links]) - -requirement = 'zc.buildout' -version = options.buildout_version -if version is None and not options.accept_buildout_test_releases: - # Figure out the most recent final version of zc.buildout. - import setuptools.package_index - _final_parts = '*final-', '*final' - - def _final_version(parsed_version): - try: - return not parsed_version.is_prerelease - except AttributeError: - # Older setuptools - for part in parsed_version: - if (part[:1] == '*') and (part not in _final_parts): - return False - return True - - index = setuptools.package_index.PackageIndex( - search_path=[setuptools_path]) - if find_links: - index.add_find_links((find_links,)) - req = pkg_resources.Requirement.parse(requirement) - if index.obtain(req) is not None: - best = [] - bestv = None - for dist in index[req.project_name]: - distv = dist.parsed_version - if _final_version(distv): - if bestv is None or distv > bestv: - best = [dist] - bestv = distv - elif distv == bestv: - best.append(dist) - if best: - best.sort() - version = best[-1].version -if version: - requirement = '=='.join((requirement, version)) -cmd.append(requirement) - -import subprocess -if subprocess.call(cmd) != 0: - raise Exception( - "Failed to execute command:\n%s" % repr(cmd)[1:-1]) - -###################################################################### -# Import and run buildout - -ws.add_entry(tmpeggs) -ws.require(requirement) -import zc.buildout.buildout - -if not [a for a in args if '=' not in a]: - args.append('bootstrap') - -# if -c was provided, we push it back into args for buildout' main function -if options.config_file is not None: - args[0:0] = ['-c', options.config_file] - -zc.buildout.buildout.main(args) -shutil.rmtree(tmpeggs) diff --git a/setup.cfg b/setup.cfg index bac1953..7867a0d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,13 +1,27 @@ -[nosetests] -nocapture=1 -cover-package=zope.i18nmessageid -cover-erase=1 -with-doctest=0 -where=src - -[aliases] -dev = develop easy_install zope.i18nmessageid[testing] -docs = easy_install zope.i18nmessageid[docs] +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +[bdist_wheel] +universal = 1 [zest.releaser] create-wheel = no + +[flake8] +doctests = 1 + +[check-manifest] +ignore = + .editorconfig + .meta.toml + docs/_build/html/_sources/* + +[isort] +force_single_line = True +combine_as_imports = True +sections = FUTURE,STDLIB,THIRDPARTY,ZOPE,FIRSTPARTY,LOCALFOLDER +known_third_party = six, docutils, pkg_resources +known_zope = +known_first_party = +default_section = ZOPE +line_length = 79 +lines_after_imports = 2 diff --git a/setup.py b/setup.py index 378e3bb..b1ac004 100644 --- a/setup.py +++ b/setup.py @@ -94,7 +94,7 @@ class optional_build_ext(build_ext): setup( name='zope.i18nmessageid', - version='5.0.2.dev0', + version='5.1.0.dev0', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Message Identifiers for internationalization', @@ -117,6 +117,9 @@ setup( '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 :: 3.11', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Natural Language :: English', @@ -130,6 +133,14 @@ setup( package_dir={'': 'src'}, namespace_packages=['zope'], install_requires=['setuptools', 'six'], + python_requires=', '.join([ + '>=2.7', + '!=3.0.*', + '!=3.1.*', + '!=3.2.*', + '!=3.3.*', + '!=3.4.*', + ]), include_package_data=True, test_suite='zope.i18nmessageid.tests.test_suite', zip_safe=False, diff --git a/tox.ini b/tox.ini index a8a4fa9..eb70366 100644 --- a/tox.ini +++ b/tox.ini @@ -1,26 +1,63 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code [tox] +minversion = 3.18 envlist = - py27,py35,py36,py37,py38,pypy,pypy3,coverage,docs + lint + py27,py27-pure + py35,py35-pure + py36,py36-pure + py37,py37-pure + py38,py38-pure + py39,py39-pure + py310,py310-pure + py311,py311-pure + pypy + pypy3 + docs + coverage [testenv] -extras = test +usedevelop = true +deps = +setenv = + pure: PURE_PYTHON=1 + !pure-!pypy-!pypy3: PURE_PYTHON=0 commands = - zope-testrunner --test-path=src [] - + zope-testrunner --test-path=src {posargs:-vc} +extras = + test [testenv:coverage] -usedevelop = true -basepython = - python2.7 +basepython = python3 +allowlist_externals = + mkdir +deps = + coverage +setenv = + PURE_PYTHON=1 commands = - coverage run -m zope.testrunner --test-path=src [] - coverage report --fail-under=100 + mkdir -p {toxinidir}/parts/htmlcov + coverage run -m zope.testrunner --test-path=src {posargs:-vc} + coverage html -i + coverage report -i -m --fail-under=100 + +[testenv:lint] +basepython = python3 +skip_install = true +commands = + check-manifest + check-python-versions +deps = + check-manifest + check-python-versions >= 0.19.1 + wheel [testenv:docs] -basepython = - python2.7 +basepython = python3 +skip_install = false +extras = + docs +commands_pre = commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html - sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest -deps = - Sphinx -- cgit v1.2.1