diff --git a/.coveragerc b/.coveragerc index 011b38b..b1b560b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,10 +1,29 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code [run] source = BTrees # 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 - class I[A-Z]\w+\((Interface|I[A-Z].*)\): - self.fail + 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 index 707e9fe..aa03952 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,7 +1,9 @@ +# 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 I (jamadden) updated at +# And later based on the version jamadden updated at # gevent/gevent, and then at zodb/relstorage and zodb/perfmetrics # # Original comment follows. @@ -35,14 +37,14 @@ name: tests -# Triggers the workflow on push or pull request events -on: [push, pull_request, workflow_dispatch] -# Limiting to particular branches might be helpful to conserve minutes. -#on: - # push: - # branches: [ $default-branch ] - # pull_request: - # branches: [ $default-branch ] +# 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`` @@ -52,12 +54,6 @@ env: PYTHONDEVMODE: 1 PYTHONFAULTHANDLER: 1 ZOPE_INTERFACE_STRICT_IRO: 1 - ZOPE_INTERFACE_LOG_CHANGED_IRO: 1 - # Require C extensions; this will be disabled later for - # PyPy because zope.interface through at least 5.3 - # tries to import its C module even on PyPy with this, but - # the wheels tend not to have it. - PURE_PYTHON: 0 PIP_UPGRADE_STRATEGY: eager # Don't get warnings about Python 2 support being deprecated. We @@ -74,11 +70,10 @@ env: ### # caching - # This is where we'd set up ccache + # 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 @@ -92,21 +87,31 @@ 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-BTrees: + build-package: # Sigh. Note that the matrix must be kept in sync # with `test`, and `docs` must use a subset. runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - python-version: [2.7, pypy-2.7, pypy-3.6, 3.5, 3.6, 3.7, 3.8, 3.9] + python-version: + - "2.7" + - "3.5" + - "pypy-2.7" + - "pypy-3.7" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" os: [ubuntu-20.04, macos-latest] exclude: - os: macos-latest - python-version: pypy-2.7 + python-version: "pypy-2.7" - os: macos-latest - python-version: pypy-3.6 + python-version: "pypy-3.7" - os: macos-latest - python-version: 3.5 + python-version: "3.5" steps: - name: checkout @@ -137,13 +142,7 @@ jobs: - name: Install Build Dependencies run: | pip install -U pip - pip install -U setuptools wheel twine - pip install -U coveralls coverage persistent - - - name: Set pure Python - if: ${{ startsWith(matrix.python-version, 'pypy') }} - run: | - echo PURE_PYTHON=1 >> $GITHUB_ENV + pip install -U setuptools wheel twine cffi - name: Build BTrees run: | @@ -152,9 +151,8 @@ jobs: 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 .[test,ZODB] + pip install .[test] - name: Check BTrees build run: | @@ -169,26 +167,40 @@ jobs: # 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') + 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-BTrees + needs: build-package runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - python-version: [2.7, pypy-2.7, pypy-3.6, 3.5, 3.6, 3.7, 3.8, 3.9] + python-version: + - "2.7" + - "3.5" + - "pypy-2.7" + - "pypy-3.7" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" os: [ubuntu-20.04, macos-latest] exclude: - os: macos-latest - python-version: pypy-2.7 + python-version: "pypy-2.7" - os: macos-latest - python-version: pypy-3.6 + python-version: "pypy-3.7" - os: macos-latest - python-version: 3.5 + python-version: "3.5" steps: - name: checkout @@ -197,6 +209,12 @@ jobs: 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: | @@ -209,10 +227,6 @@ jobs: key: ${{ runner.os }}-pip-${{ matrix.python-version }} restore-keys: | ${{ runner.os }}-pip- - - name: Set pure Python - if: ${{ startsWith(matrix.python-version, 'pypy') }} - run: | - echo PURE_PYTHON=1 >> $GITHUB_ENV - name: Download BTrees wheel uses: actions/download-artifact@v2 @@ -220,45 +234,27 @@ jobs: name: BTrees-${{ runner.os }}-${{ matrix.python-version }}.whl path: dist/ - name: Install BTrees - # ``python -m unittest discover`` only works with editable - # installs, so we have to duplicate some work and can't - # install the built wheel. (zope.testrunner - # works fine with non-editable installs.) run: | - ls -l dist - ls -l . - pip install -U wheel + 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/BTrees-*whl -d src - pip install -U -e .[test,ZODB] - - name: Set coverage status - # coverage is too slow on PyPy. We can't submit it from macOS (see that action), - # so don't bother taking the speed hit there either. - if: ${{ !startsWith(matrix.python-version, 'pypy') && startsWith(runner.os, 'Linux') }} - run: | - echo WITH_COVERAGE=1 >> $GITHUB_ENV - - name: Run native tests - # Here, run natively just once. Only run PURE_PYTHON - # again once, because these tests take awhile, and PURE_PYTHON - # runs once under PyPy anyway (but with coverage takes forever). + pip install -U -e .[test] + - name: Run tests with C extensions + if: ${{ !startsWith(matrix.python-version, 'pypy') }} run: | - if [[ "$WITH_COVERAGE" == "1" ]]; then - coverage run -p -m unittest discover -s src - else - python -m unittest discover -s src - fi - - name: Run PURE_PYTHON tests - if: (matrix.python-version == 2.7 || matrix.python-version == 3.9) && startsWith(runner.os, 'Linux') + 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: | - PURE_PYTHON=1 coverage run -p -m unittest discover -s src - - name: Report coverage - run: | - coverage combine || true - coverage report -i || true + coverage combine + coverage report -i - name: Submit to Coveralls # This is a container action, which only runs on Linux. if: ${{ startsWith(runner.os, 'Linux') }} @@ -276,11 +272,11 @@ jobs: parallel-finished: true docs: - needs: build-BTrees + needs: build-package runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.9] + python-version: ["3.9"] os: [ubuntu-20.04] steps: @@ -290,6 +286,12 @@ jobs: 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: | @@ -312,22 +314,20 @@ jobs: 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/BTrees-*.whl`[docs]" - name: Build docs env: - ZOPE_INTERFACE_STRICT_IRO: 0 + ZOPE_INTERFACE_STRICT_IRO: 1 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-BTrees + needs: build-package runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.9] + python-version: ["3.9"] os: [ubuntu-20.04] steps: @@ -337,7 +337,12 @@ jobs: 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: | @@ -360,7 +365,7 @@ jobs: run: | pip install -U pip pip install -U wheel - pip install -U `ls dist/BTrees-*`[test,ZODB] + pip install -U `ls dist/BTrees-*`[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. @@ -374,7 +379,7 @@ jobs: # We use a regular Python matrix entry to share as much code as possible. strategy: matrix: - python-version: [3.9] + python-version: ["3.9"] image: [manylinux2010_x86_64, manylinux2010_i686, manylinux2014_aarch64] steps: @@ -384,6 +389,12 @@ jobs: 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: | @@ -407,13 +418,13 @@ jobs: # 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 + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} run: | bash .manylinux.sh - name: Build BTrees (i686) if: matrix.image == 'manylinux2010_i686' env: - DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }}:2021-02-06-3d322a5 + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} PRE_CMD: linux32 run: | bash .manylinux.sh @@ -435,22 +446,11 @@ jobs: 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') + 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/.gitignore b/.gitignore index 315b87d..20b2128 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,31 @@ -bin -eggs -develop-eggs -parts -.installed.cfg -build -docs/_build -__pycache__ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +*.dll +*.egg-info/ +*.profraw *.pyc +*.pyo *.so -.tox .coverage -nosetests.xml -coverage.xml -*.egg-info -*.egg -dist +.coverage.* .eggs/ -.dir-locals.el -pip-wheel-metadata/ -htmlcov/ +.installed.cfg +.mr.developer.cfg +.tox/ +.vscode/ +__pycache__/ +bin/ +build/ +coverage.xml +develop-eggs/ +develop/ +dist/ +docs/_build +eggs/ +etc/ +lib/ +lib64 +log/ +parts/ +pyvenv.cfg +var/ diff --git a/.manylinux-install.sh b/.manylinux-install.sh index e5bef77..e1921f1 100755 --- a/.manylinux-install.sh +++ b/.manylinux-install.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code set -e -x @@ -33,33 +35,47 @@ else fi export PURE_PYTHON=0 +# https://wiki.centos.org/yum-errors suggests this might help against yum +# errors: +yum clean all +rm -rf /var/cache/yum/* +# We need some libraries because we build wheels from scratch: +yum -y install libffi-devel # Compile wheels -cd /io/ -for variant in `ls -d /opt/python/cp{27,36,37,38,39}*`; do - PYBIN="$variant/bin" - "${PYBIN}/pip" install persistent wheel setuptools - "${PYBIN}/python" setup.py bdist_wheel - ls dist - if [ `uname -m` == 'aarch64' ]; then - # Running the test suite takes forever in - # emulation; an early run (using tox, which is also slow) - # took over an hour to build and then run the 2.7 tests and move on - # to the 3.5 tests. We still want to run tests, though! - # We don't want to distribute wheels for a platform that's - # completely untested. Consequently, we limit it to running - # in just one interpreter, the newest one on the list (which in principle - # should be the fastest), and we don't install the ZODB extra. - if [[ "${PYBIN}" == *"cp39"* ]]; then - "${PYBIN}/pip" install -e .[test] - "${PYBIN}/python" -c 'import BTrees.OOBTree; print(BTrees.OOBTree.BTree, BTrees.OOBTree.BTreePy)' - "${PYBIN}/python" -m unittest discover -s src +for PYBIN in /opt/python/*/bin; do + if \ + [[ "${PYBIN}" == *"cp27"* ]] || \ + [[ "${PYBIN}" == *"cp35"* ]] || \ + [[ "${PYBIN}" == *"cp36"* ]] || \ + [[ "${PYBIN}" == *"cp37"* ]] || \ + [[ "${PYBIN}" == *"cp38"* ]] || \ + [[ "${PYBIN}" == *"cp39"* ]] || \ + [[ "${PYBIN}" == *"cp310"* ]] ; then + "${PYBIN}/pip" install -e /io/ + "${PYBIN}/pip" wheel /io/ -w wheelhouse/ + if [ `uname -m` == 'aarch64' ]; then + # Running the test suite takes forever in + # emulation; an early run (using tox, which is also slow) + # took over an hour to build and then run the 2.7 tests and move on + # to the 3.5 tests. We still want to run tests, though! + # We don't want to distribute wheels for a platform that's + # completely untested. Consequently, we limit it to running + # in just one interpreter, the newest one on the list (which in principle + # should be the fastest), and we don't install the ZODB extra. + if [[ "${PYBIN}" == *"cp39"* ]]; then + cd /io/ + "${PYBIN}/pip" install -e .[test] + "${PYBIN}/python" -c 'import BTrees.OOBTree; print(BTrees.OOBTree.BTree, BTrees.OOBTree.BTreePy)' + "${PYBIN}/python" -m unittest discover -s src + cd .. + fi fi + rm -rf /io/build /io/*.egg-info fi - rm -rf /io/build /io/*.egg-info done # Bundle external shared libraries into the wheels -for whl in dist/BTrees*.whl; do +for whl in wheelhouse/BTrees*.whl; do auditwheel repair "$whl" -w /io/wheelhouse/ done diff --git a/.manylinux.sh b/.manylinux.sh index 520d68e..ea4ef41 100755 --- a/.manylinux.sh +++ b/.manylinux.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code set -e -x diff --git a/.meta.toml b/.meta.toml new file mode 100644 index 0000000..6e4b6bb --- /dev/null +++ b/.meta.toml @@ -0,0 +1,98 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +[meta] +template = "c-code" +commit-id = "1b2a5eb60d5b2b3fcee16692b0a9a6a26172c06a" + +[python] +with-appveyor = true +with-windows = false +with-pypy = true +with-future-python = false +with-legacy-python = true +with-docs = true +with-sphinx-doctests = true + +[tox] +use-flake8 = false +additional-envlist = [ + "w_zodb", + "w_zodb-pure", + ] +testenv-setenv = [ + "PYTHONFAULTHANDLER=1", + "PYTHONDEVMODE=1", + "ZOPE_INTERFACE_STRICT_IRO=1", + "ZOPE_INTERFACE_LOG_CHANGED_IRO=1", + ] +testenv-additional = [ + "", + "[testenv:w_zodb]", + "basepython = python3.9", + "deps = ZODB", + "", + "[testenv:w_zodb-pure]", + "basepython = python3.9", + "deps = ZODB", + ] + +[coverage] +fail-under = 93 + +[manifest] +additional-rules = [ + "include *.sh", + "recursive-include docs *.bat", + "recursive-include docs *.css", + "recursive-include src *.c", + "recursive-include src *.h", + ] + +[check-manifest] +additional-ignores = [ + "docs/_build/html/_static/*", + "docs/_build/html/_static/*/*", + ] + +[appveyor] +global-env-vars = [ + "# Currently the builds use @mgedmin's Appveyor account. The PyPI token belongs", + "# to zope.wheelbuilder, which is managed by @mgedmin and @dataflake.", + "global:", + " TWINE_USERNAME: __token__", + " TWINE_PASSWORD:", + " secure: aoZC/+rvJKg8B5GMGIxd1a+XrG6uK7c37/wnoeA74KlRM9aqyayAnJxNyzyAAsCNzdLl7gz6wEC7lq/oYd3Rcb8mcK+K2U1mqbeG3SeIigCWLKtTnAK9EUiuaVGKVrKvywY7Ckp1uBh5To7PQn5ZS6QEe7YvJODljrGc8O2Z3TjofUzwE28L7P89BgZwCr+/3oOXsY3DHZXUGGYcIjkczLXoDsZ+X9/1WWbVdoTkgeXZmVQbl/a9nYilXILOh2NQtJLn0cInPZyPLfdGw88ZWw==", + ] + +[c-code] +manylinux-install-setup = [ + "export CFLAGS=\"-pipe\"", + "if [ `uname -m` == 'aarch64' ]; then", + " # Compiling with -Ofast on the arm emulator takes hours. The default settings have -O3,", + " # and adding -Os doesn't help much; -O1 seems too.", + " echo \"Compiling with -O1\"", + " export CFLAGS=\"-O1 $CFLAGS\"", + "else", + " echo \"Compiling with -Ofast\"", + " export CFLAGS=\"-Ofast $CFLAGS\"", + "fi", + "", + "export PURE_PYTHON=0", + ] +manylinux-aarch64-tests = [ + "# Running the test suite takes forever in", + "# emulation; an early run (using tox, which is also slow)", + "# took over an hour to build and then run the 2.7 tests and move on", + "# to the 3.5 tests. We still want to run tests, though!", + "# We don't want to distribute wheels for a platform that's", + "# completely untested. Consequently, we limit it to running", + "# in just one interpreter, the newest one on the list (which in principle", + "# should be the fastest), and we don't install the ZODB extra.", + "if [[ \"${PYBIN}\" == *\"cp39\"* ]]; then", + " cd /io/", + " \"${PYBIN}/pip\" install -e .[test]", + " \"${PYBIN}/python\" -c 'import BTrees.OOBTree; print(BTrees.OOBTree.BTree, BTrees.OOBTree.BTreePy)'", + " \"${PYBIN}/python\" -m unittest discover -s src", + " cd ..", + "fi", + ] diff --git a/CHANGES.rst b/CHANGES.rst index 725f2b4..ac9f756 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,10 +2,10 @@ BTrees Changelog ================== -4.9.3 (unreleased) -================== +4.10.0 (unreleased) +=================== -- Nothing changed yet. +- Add support for Python 3.10. 4.9.2 (2021-06-09) 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 b98bba5..dd97482 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,22 +1,21 @@ -include pyproject.toml - -include *.txt +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +include *.md include *.rst -include *.py +include *.txt include buildout.cfg include tox.ini +include appveyor.yml include .coveragerc -recursive-include docs * -recursive-include src * -recursive-include .github * - -global-exclude *.dll -global-exclude *.pyc -global-exclude *.pyo -global-exclude *.so -global-exclude *~ -global-exclude *\# -global-exclude coverage.xml +recursive-include docs *.py +recursive-include docs *.rst +recursive-include docs *.txt +recursive-include docs Makefile -prune docs/_build +recursive-include src *.py +include *.sh +recursive-include docs *.bat +recursive-include docs *.css +recursive-include src *.c +recursive-include src *.h diff --git a/appveyor.yml b/appveyor.yml index 30380dc..ae937ab 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,8 @@ -# 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: + # Currently the builds use @mgedmin's Appveyor account. The PyPI token belongs + # to zope.wheelbuilder, which is managed by @mgedmin and @dataflake. global: TWINE_USERNAME: __token__ TWINE_PASSWORD: @@ -20,8 +21,11 @@ environment: - python: 38-x64 - python: 39 - python: 39-x64 + - python: 310 + - python: 310-x64 install: + - "SET PYTHONVERSION=%PYTHON%" - "SET PATH=C:\\Python%PYTHON%;c:\\Python%PYTHON%\\scripts;%PATH%" - ps: | $env:PYTHON = "C:\\Python${env:PYTHON}" @@ -31,21 +35,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,ZODB] + - python -m pip install -U pip + - pip install -U setuptools wheel + - pip install -U -e .[test] + +matrix: + fast_finish: true build_script: - - python -m pip install -U pip - - pip install 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/docs/overview.rst b/docs/overview.rst index 8540254..21ecc93 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -141,7 +141,7 @@ exclusive of the range's endpoints. 'green' >>> s = t.keys() # this is a "lazy" sequence object >>> s - + <...TreeItems object at ...> >>> len(s) # it acts like a Python list 4 >>> s[-2] @@ -260,9 +260,10 @@ example, lists supply a total ordering, and then >>> L2[0] = 5 # horrible -- the set is insane now >>> s.has_key([3]) # for example, it's insane this way False - >>> s - OOSet([[1], [5], [3]]) - >>> + >>> s.__class__ + + >>> list(s) + [[1], [5], [3]] Key lookup relies on that the keys remain in sorted order (an efficient form of binary search is used). By mutating key L2 after inserting it, we destroyed the diff --git a/setup.cfg b/setup.cfg index 1da15c1..9d8b94c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,24 +1,19 @@ -[nosetests] -nocapture=1 -cover-package=BTrees -cover-erase=1 -cover-branches=1 -cover-min-percentage=100 -with-doctest=0 -where=BTrees - -[aliases] -dev = develop easy_install BTrees[testing] -docs = develop easy_install BTrees[docs] - -[check-manifest] -ignore = - .manylinux-install.sh - .manylinux.sh - appveyor.yml - +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code [bdist_wheel] -universal = 0 +universal = 1 [zest.releaser] create-wheel = no + +[flake8] +doctests = 1 + +[check-manifest] +ignore = + .editorconfig + .meta.toml + docs/_build/html/_sources/* + docs/_build/doctest/* + docs/_build/html/_static/* + docs/_build/html/_static/*/* diff --git a/setup.py b/setup.py index a413cdf..9d7488f 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ from setuptools import setup from setuptools.command.build_ext import build_ext -version = '4.9.3.dev0' +version = '4.10.0.dev0' def _read(fname): here = os.path.abspath(os.path.dirname(__file__)) @@ -197,6 +197,7 @@ def BTreeExtension(family): "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", "Framework :: ZODB", @@ -222,8 +223,7 @@ def BTreeExtension(family): 'ZODB', ], 'docs': [ - # Sphinx 4 and r.s.autointerface 0.8 are incompatible. - 'Sphinx < 4', + 'Sphinx', 'repoze.sphinx.autointerface', 'sphinx_rtd_theme', ], diff --git a/src/BTrees/_base.py b/src/BTrees/_base.py index 0f9f4f8..8a3b278 100644 --- a/src/BTrees/_base.py +++ b/src/BTrees/_base.py @@ -995,8 +995,7 @@ def has_key(self, key): index = self._search(key) if index < 0: return False - r = self._data[index].child.has_key(key) - return r and r + 1 + return self._data[index].child.has_key(key) def keys(self, min=_marker, max=_marker, excludemin=False, excludemax=False, diff --git a/tox.ini b/tox.ini index c96598a..afbf9df 100644 --- a/tox.ini +++ b/tox.ini @@ -1,59 +1,77 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code [tox] +minversion = 3.18 envlist = -# Jython support pending 2.7 support, due 2012-07-15 or so. See: -# http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html -# py27,jython,pypy,coverage,docs - py27,py27-pure,py35,py35-pure,py36,py37,py38,py39,pypy,pypy3,w_zodb,w_zodb-pure,coverage,docs + lint + py27,py27-pure + py35,py35-pure + py36,py36-pure + py37,py37-pure + py38,py38-pure + py39,py39-pure + py310,py310-pure + pypy + pypy3 + docs + coverage + w_zodb + w_zodb-pure [testenv] usedevelop = true -extras = - test -commands = - python -m zope.testrunner --test-path=src --auto-color --auto-progress {posargs} +deps = setenv = + pure: PURE_PYTHON=1 + !pure-!pypy-!pypy3: PURE_PYTHON=0 PYTHONFAULTHANDLER=1 PYTHONDEVMODE=1 ZOPE_INTERFACE_STRICT_IRO=1 ZOPE_INTERFACE_LOG_CHANGED_IRO=1 - PURE_PYTHON=0 - pure: PURE_PYTHON=1 - pypy: PURE_PYTHON=1 - pypy3: PURE_PYTHON=1 - -#[testenv:jython] -#commands = -# jython setup.py test -q +commands = + zope-testrunner --test-path=src {posargs:-vc} + !py27-!pypy: sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest +extras = + test + docs [testenv:w_zodb] -basepython = - python2.7 -deps = - ZODB +basepython = python3.9 +deps = ZODB [testenv:w_zodb-pure] -basepython = - python2.7 -deps = - ZODB +basepython = python3.9 +deps = ZODB [testenv:coverage] -basepython = - python3 -commands = - coverage run -m zope.testrunner --test-path=src --auto-color --auto-progress {posargs} - coverage report --fail-under=92 +basepython = python3 +allowlist_externals = + mkdir deps = coverage - ZODB +setenv = + PURE_PYTHON=1 +commands = + mkdir -p {toxinidir}/parts/htmlcov + coverage run -m zope.testrunner --test-path=src {posargs:-vc} + coverage html -i + coverage report -i -m --fail-under=93 + +[testenv:lint] +basepython = python3 +skip_install = true +deps = + check-manifest + check-python-versions >= 0.19.1 + wheel +commands = + check-manifest + check-python-versions [testenv:docs] -basepython = - python3 +basepython = python3 +skip_install = false +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 = - --requirement doc-requirements.txt -extras = - docs