diff --git a/.coveragerc b/.coveragerc index d70e082..f63b772 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,7 @@ [run] source = persistent +# New in 5.0; required for the GHA coveralls submission. +relative_files = True omit = persistent/_ring_build.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..c1f308d --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,437 @@ +### +# Initially copied from +# https://github.com/actions/starter-workflows/blob/main/ci/python-package.yml +# And later based on the version I (jamadden) updated at +# gevent/gevent, and then at zodb/relstorage and zodb/perfmetrics and zopefoundation/zope.interface +# +# 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 +on: [push, pull_request] +# Limiting to particular branches might be helpful to conserve minutes. +#on: + # push: + # branches: [ $default-branch ] + # pull_request: + # branches: [ $default-branch ] + +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: -Ofast -pipe + CXXFLAGS: -Ofast -pipe + # Uploading built wheels for releases. + # TWINE_PASSWORD is encrypted and stored directly in the + # github repo settings. + TWINE_USERNAME: __token__ + + # We want to require the C extensions to build and function + # everywhere (except where we specifically opt-out, currently just + # PyPy, where they build but don't quite work). + PURE_PYTHON: 0 + + ### + # 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-persistent: + # Sigh. Note that the matrix must be kept in sync + # with `test`, and `docs` must use a subset. + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: [2.7, pypy-2.7, pypy-3.6, 3.5, 3.6, 3.7, 3.8, 3.9] + os: [ubuntu-20.04, macos-latest] + exclude: + - os: macos-latest + python-version: pypy-2.7 + - os: macos-latest + python-version: pypy-3.6 + - 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 "::set-output name=dir::$(pip cache dir)" + + - 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: Set CFLAGS + # GCC, optimizations, and -fno-wrapv can be an issue. + # Have one environment (not an uploaded wheel!) + # built that way. + # https://github.com/zopefoundation/persistent/issues/86 + if: ${{ matrix.python-version == 3.6 && startsWith(runner.os, 'Linux') }} + run: | + echo CFLAGS="-O2 -fno-wrapv" >> $GITHUB_ENV + - name: Install Build Dependencies + run: | + pip install -U pip + pip install -U setuptools wheel twine cffi + pip install -U coveralls coverage + + - name: Build persistent + 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 coverage + pip install -U 'faulthandler; python_version == "2.7" and platform_python_implementation == "CPython"' + pip install -U .[test] + + - name: Check persistent build + run: | + ls -l dist + twine check dist/* + - name: Upload persistent wheel + uses: actions/upload-artifact@v2 + with: + name: persistent-${{ 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') + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + run: | + twine upload --skip-existing dist/* + + test: + needs: build-persistent + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: [2.7, pypy-2.7, pypy-3.6, 3.5, 3.6, 3.7, 3.8, 3.9] + os: [ubuntu-20.04, macos-latest] + exclude: + - os: macos-latest + python-version: pypy-2.7 + - os: macos-latest + python-version: pypy-3.6 + - 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 }} + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + + - 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 persistent wheel + uses: actions/download-artifact@v2 + with: + name: persistent-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install persistent + run: | + pip install -U wheel + pip install -U coverage + pip install -U 'faulthandler; python_version == "2.7" and platform_python_implementation == "CPython"' + pip install -U "`ls dist/persistent*whl`[test]" + # 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? (XXX: Sadly, persistent is not yet in + # src/) + unzip -n dist/persistent-*whl -d . + - name: Run tests with C extensions + if: ${{ !startsWith(matrix.python-version, 'pypy') }} + run: | + python -m coverage run -p -m zope.testrunner --test-path=. --auto-color --auto-progress + - name: Run tests without C extensions + run: + # coverage makes PyPy run about 3x slower, but the tests only take + # .4s to begin with (the whole process takes about 1.5), so that's + # still only 4.5s, which is maneagable. + PURE_PYTHON=1 python -m coverage run -p -m zope.testrunner --test-path=. --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-persistent + 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 }} + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + + - 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 persistent wheel + uses: actions/download-artifact@v2 + with: + name: persistent-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install persistent + run: | + pip install -U wheel + pip install -U coverage + pip install -U 'faulthandler; python_version == "2.7" and platform_python_implementation == "CPython"' + pip install -U "`ls dist/persistent-*.whl`[docs]" + - name: Build docs + run: | + sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html + sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest + + + lint: + needs: build-persistent + 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 }} + + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + + - 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 persistent wheel + uses: actions/download-artifact@v2 + with: + name: persistent-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install persistent + run: | + pip install -U pip + pip install -U wheel + pip install -U `ls dist/persistent-*`[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 persistent -f parseable -r n + + manylinux: + runs-on: ubuntu-20.04 + # 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 }} + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + + - 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 persistent (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 }}:2021-02-06-3d322a5 + run: | + bash .manylinux.sh + - name: Build persistent (i686) + if: matrix.image == 'manylinux2010_i686' + env: + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }}:2021-02-06-3d322a5 + PRE_CMD: linux32 + run: | + bash .manylinux.sh + - name: Build persistent (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 persistent 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/ + +# TODO: +# * Use YAML syntax to share snippets, like the old .travis.yml did +# Sadly, as of 2021-02-01, Github Actions does not support anchors at +# all. Just having an anchor results in an error: +# +# The workflow is not valid. .github/workflows/tests.yml: Anchors +# are not currently supported. Remove the anchor 'an-strategy' +# +# The alternative of using composite actions doesn't work either, +# because composite actions are limited to running shell scripts. +# Steps in them can't call other actions with `uses:`, and nor can +# they be conditional with `if:`. diff --git a/.manylinux-install.sh b/.manylinux-install.sh index ebc9d3b..bb0e7a0 100755 --- a/.manylinux-install.sh +++ b/.manylinux-install.sh @@ -2,16 +2,42 @@ 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 + +# libffi-devel needed to build CFFI; +# CFFI doesn't have wheels for aarch64 +yum -y install libffi-devel + # Compile wheels for PYBIN in /opt/python/*/bin; do if [[ "${PYBIN}" == *"cp27"* ]] || \ [[ "${PYBIN}" == *"cp35"* ]] || \ [[ "${PYBIN}" == *"cp36"* ]] || \ [[ "${PYBIN}" == *"cp37"* ]] || \ - [[ "${PYBIN}" == *"cp38"* ]]; then + [[ "${PYBIN}" == *"cp38"* ]] || \ + [[ "${PYBIN}" == *"cp39"* ]]; then "${PYBIN}/pip" install -U pip setuptools cffi - "${PYBIN}/pip" install -e /io/ + "${PYBIN}/pip" install -e /io/[test] + "${PYBIN}/zope-testrunner" --test-path=/io/ "${PYBIN}/pip" wheel /io/ -w wheelhouse/ + rm -rf /io/build /io/*.egg-info fi done diff --git a/.manylinux.sh b/.manylinux.sh index 2fed778..ccc5ed3 100755 --- a/.manylinux.sh +++ b/.manylinux.sh @@ -1,5 +1,13 @@ #!/usr/bin/env bash set -e -x +# 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 -v "$(pwd)":/io $DOCKER_IMAGE $PRE_CMD /io/.manylinux-install.sh +docker run --rm -e GITHUB_ACTIONS -v "$(pwd)":/io -v "$LCACHE:/cache" $DOCKER_IMAGE $PRE_CMD /io/.manylinux-install.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index dda3ec5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,136 +0,0 @@ -language: python - -env: - global: - - TWINE_USERNAME: zope.wheelbuilder - # this sets $PYPIPASSWORD - - secure: "NTWzDr5p8KRPNt+sniTot7csbzC87rzir/XfLtENE0GpQ49FlKw3lBhsDqAPoD8Ea5lwiHXmC/C/ci1UZhFvVEkAoQ2qJlMRnhqUdRJSrqcitmRt0fT6mLaTd+Lr+DxKlBxpssobrEm2G42V/G1s0Ggym04OqF8T+s6MF5ywgJM=" - # We want to require the C extensions to build and function - # everywhere (except where we specifically opt-out, currently just - # PyPy, where they build but don't quite work). - - PURE_PYTHON: 0 - - -python: - - 2.7 - - 3.5 - - 3.6 - - 3.7 - - 3.8 - - 3.9 - -jobs: - include: - # Don't test C extensions on PyPy. - - python: pypy - env: PURE_PYTHON=1 - - - python: pypy3 - env: PURE_PYTHON=1 - - # Special Linux builds - - name: "Python: 2.7, pure (no C extensions)" - python: 2.7 - env: PURE_PYTHON=1 - - # Test for https://github.com/zopefoundation/persistent/issues/86 - - name: "Python: 3.6, -fno-wrapv" - python: 3.6 - env: CFLAGS="-fno-wrapv" - - - name: "Python: 3.7, pure (no C extensions)" - python: 3.7 - env: PURE_PYTHON=1 - - - name: "Documentation" - python: 3.6 - install: - - pip install -U -e .[docs] - script: - - sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html - - sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest - after_success: - - # 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 - # We require at least 2.7.15 to upload wheels. - # See https://github.com/zopefoundation/BTrees/issues/113 - 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 - # NB: 3.6.0 causes https://github.com/nedbat/coveragepy/issues/703 - # NB: 3.6.1 had that ABI regression (fixed in 3.6.2) and would be a bad - # version to use - 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: - - python -m pip install -U pip setuptools cffi wheel coverage coveralls - - python -m pip install -U -e .[test] - -script: - - python --version - - # make sure we can build a wheel - - python setup.py bdist_wheel - - # coverage makes PyPy run about 3x slower, but the tests only take - # .4s to begin with (the whole process takes about 1.5), so that's - # still only 4.5s, which is maneagable. - - python -m coverage run -m zope.testrunner --test-path=. --auto-color --auto-progress - -after_success: - - python -m coveralls - - | - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then - pip install twine - python setup.py bdist_wheel - TWINE_PASSWORD=$PYPIPASSWORD twine upload --skip-existing dist/* - fi - - | - if [[ $TRAVIS_TAG && -n "$DOCKER_IMAGE" ]]; then - pip install twine - TWINE_PASSWORD=$PYPIPASSWORD twine upload --skip-existing wheelhouse/* - fi - -notifications: - email: false - -cache: pip diff --git a/CHANGES.rst b/CHANGES.rst index a655855..124939a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,14 +1,16 @@ -``persistent`` Changelog -======================== +========================== + ``persistent`` Changelog +========================== -4.6.5 (unreleased) ------------------- - -- Nothing changed yet. +4.7.0 (unreleased) +================== +- Add support for Python 3.9. +- Move from Travis CI to Github Actions. +- Supply manylinux wheels for aarch64 (ARM). 4.6.4 (2020-03-26) ------------------- +================== - Fix an overly specific test failure using zope.interface 5. See `issue 144 `_. @@ -16,7 +18,7 @@ of obscure errors. See `issue 143 `_. 4.6.3 (2020-03-18) ------------------- +================== - Fix a crash in the test suite under a 32-bit CPython on certain 32-bit platforms. See `issue 137 @@ -25,7 +27,7 @@ 4.6.2 (2020-03-12) ------------------- +================== - Fix an ``AssertionError`` clearing a non-empty ``PersistentMapping`` that has no connection. See `issue 139 @@ -33,7 +35,7 @@ 4.6.1 (2020-03-06) ------------------- +================== - Stop installing C header files on PyPy (which is what persistent before 4.6.0 used to do), fixes `issue 135 @@ -41,7 +43,7 @@ 4.6.0 (2020-03-05) ------------------- +================== - Fix slicing of ``PersistentList`` to always return instances of the same class. It was broken on Python 3 prior to 3.7.4. @@ -87,7 +89,7 @@ (except on PyPy). 4.5.1 (2019-11-06) ------------------- +================== - Add support for Python 3.8. @@ -95,7 +97,7 @@ 4.5.0 (2019-05-09) ------------------- +================== - Fully test the C implementation of the PickleCache, and fix discrepancies between it and the Python implementation: @@ -127,7 +129,7 @@ 4.4.3 (2018-10-22) ------------------- +================== - Fix the repr of the persistent objects to include the module name when using the C extension. This matches the pure-Python behaviour @@ -141,7 +143,7 @@ 4.4.2 (2018-08-28) ------------------- +================== - Explicitly use unsigned constants for packing and unpacking C timestamps, fixing an arithmetic issue for GCC when optimizations @@ -150,14 +152,14 @@ 4.4.1 (2018-08-23) ------------------- +================== - Fix installation of source packages on PyPy. See `issue 88 `_. 4.4.0 (2018-08-22) ------------------- +================== - Use unsigned constants when doing arithmetic on C timestamps, possibly avoiding some overflow issues with some compilers or @@ -208,7 +210,7 @@ 4.3.0 (2018-07-30) ------------------- +================== - Fix the possibility of a rare crash in the C extension when deallocating items. See https://github.com/zopefoundation/persistent/issues/66 @@ -224,19 +226,19 @@ 4.2.4.2 (2017-04-23) --------------------- +==================== - Packaging-only release: fix Python 2.7 ``manylinux`` wheels. 4.2.4.1 (2017-04-21) --------------------- +==================== - Packaging-only release: get ``manylinux`` wheel built automatically. 4.2.4 (2017-03-20) ------------------- +================== - Avoid raising a ``SystemError: error return without exception set`` when loading an object with slots whose jar generates an exception @@ -244,7 +246,7 @@ 4.2.3 (2017-03-08) ------------------- +================== - Fix the hashcode of Python ``TimeStamp`` objects on 64-bit Python on Windows. See https://github.com/zopefoundation/persistent/pull/55 @@ -266,7 +268,7 @@ 4.2.2 (2016-11-29) ------------------- +================== - Drop use of ``ctypes`` for determining maximum integer size, to increase pure-Python compatibility. See https://github.com/zopefoundation/persistent/pull/31 @@ -279,14 +281,14 @@ 4.2.1 (2016-05-26) ------------------- +================== - Fix the hashcode of C ``TimeStamp`` objects on 64-bit Python 3 on Windows. 4.2.0 (2016-05-05) ------------------- +================== - Fixed the Python(/PYPY) implementation ``TimeStamp.timeTime`` method to have subsecond precision. @@ -300,13 +302,13 @@ 4.1.1 (2015-06-02) ------------------- +================== - Fix manifest and re-upload to fix stray files included in 4.1.0. 4.1.0 (2015-05-19) ------------------- +================== - Make the Python implementation of ``Persistent`` and ``PickleCache`` behave more similarly to the C implementation. In particular, the @@ -316,7 +318,7 @@ 4.0.9 (2015-04-08) ------------------- +================== - Make the C and Python ``TimeStamp`` objects behave more alike. The Python version now produces the same ``repr`` and ``.raw()`` output as @@ -332,7 +334,7 @@ 4.0.8 (2014-03-20) ------------------- +================== - Add support for Python 3.4. @@ -351,7 +353,7 @@ 4.0.7 (2014-02-20) ------------------- +================== - Avoid a KeyError from ``_p_accessed()`` on newly-created objects under pure-Python: these objects may be assigned to a jar, but not yet added @@ -368,20 +370,20 @@ 4.0.6 (2013-01-03) ------------------- +================== - Updated Trove classifiers. 4.0.5 (2012-12-14) ------------------- +================== - Fixed the C-extensions under Py3k (previously they compiled but were not importable). 4.0.4 (2012-12-11) ------------------- +================== - Added support for Python 3.3. @@ -390,7 +392,7 @@ 4.0.3 (2012-11-19) ------------------- +================== - Fixed: In the C implimentation, an integer was compared with a pointer, with undefined results and a compiler warning. @@ -404,13 +406,13 @@ 4.0.2 (2012-08-27) ------------------- +================== - Correct initialization functions in renamed ``_timestamp`` extension. 4.0.1 (2012-08-26) ------------------- +================== - Worked around test failure due to overflow to long on 32-bit systems. @@ -426,10 +428,10 @@ 4.0.0 (2012-08-11) ------------------- +================== Platform Changes -################ +---------------- - Added explicit support for Python 3.2 and PyPy. @@ -439,7 +441,7 @@ Platform Changes - Dropped support for Python < 2.6. Testing Changes -############### +--------------- - 100% unit test coverage. @@ -464,7 +466,7 @@ Testing Changes run with ``setup.py test``. Documentation Changes -##################### +--------------------- - Refactored many Doctests as Sphinx documentation (snippets are exercised via 'tox'). diff --git a/MANIFEST.in b/MANIFEST.in index 47329ad..43b2718 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,6 +7,7 @@ include *.yml recursive-include docs * recursive-include persistent * +recursive-include .github *.yml global-exclude *.dll global-exclude *.pyc @@ -19,7 +20,6 @@ prune persistent/__pycache__ include .coveragerc -include .travis.yml include buildout.cfg include tox.ini include *.py diff --git a/README.rst b/README.rst index b9c6b56..c933987 100644 --- a/README.rst +++ b/README.rst @@ -1,8 +1,9 @@ -``persistent``: automatic persistence for Python objects -========================================================= +=========================================================== + ``persistent``: automatic persistence for Python objects +=========================================================== -.. image:: https://travis-ci.com/zopefoundation/persistent.svg?branch=master - :target: https://travis-ci.com/zopefoundation/persistent +.. image:: https://github.com/zopefoundation/persistent/actions/workflows/tests.yml/badge.svg + :target: https://github.com/zopefoundation/persistent/actions/workflows/tests.yml .. image:: https://coveralls.io/repos/github/zopefoundation/persistent/badge.svg?branch=master :target: https://coveralls.io/github/zopefoundation/persistent?branch=master diff --git a/appveyor.yml b/appveyor.yml index c2fb848..a220af0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,8 @@ environment: - python: 37-x64 - python: 38 - python: 38-x64 + - python: 39 + - python: 39-x64 install: - "SET PATH=C:\\Python%PYTHON%;c:\\Python%PYTHON%\\scripts;%PATH%" diff --git a/setup.py b/setup.py index d98193f..b972cc3 100644 --- a/setup.py +++ b/setup.py @@ -100,6 +100,7 @@ def _read_file(filename): "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Framework :: ZODB",