summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Howitz <mh@gocept.com>2022-03-10 08:26:21 +0100
committerGitHub <noreply@github.com>2022-03-10 08:26:21 +0100
commit5d37b3849d7679454e1dbb83c14b3850cc795efe (patch)
treedbae9e6202932d9f3be9143afc0ef8fc57ef9029
parent55bcba2339541ef37b8ce6f599c7519bc1f118d5 (diff)
parent6960f2a46819bd44e8a85fb361fbac495a6caa14 (diff)
downloadzope-security-5d37b3849d7679454e1dbb83c14b3850cc795efe.tar.gz
Merge pull request #79 from zopefoundation/config-with-c-code
Config with c code
-rw-r--r--.coveragerc26
-rw-r--r--.editorconfig39
-rw-r--r--.github/workflows/tests.yml456
-rw-r--r--.gitignore40
-rwxr-xr-x.manylinux-install.sh38
-rwxr-xr-x.manylinux.sh13
-rw-r--r--.meta.toml62
-rw-r--r--.travis.yml121
-rw-r--r--CHANGES.rst6
-rw-r--r--CONTRIBUTING.md23
-rw-r--r--MANIFEST.in20
-rw-r--r--appveyor.yml44
-rw-r--r--bootstrap.py210
-rw-r--r--docs/proxy.rst5
-rw-r--r--setup.cfg30
-rw-r--r--setup.py16
-rw-r--r--src/zope/security/__init__.py1
-rw-r--r--src/zope/security/_compat.py4
-rw-r--r--src/zope/security/_definitions.py2
-rw-r--r--src/zope/security/adapter.py2
-rw-r--r--src/zope/security/checker.py156
-rw-r--r--src/zope/security/decorator.py5
-rw-r--r--src/zope/security/examples/sandbox.py73
-rw-r--r--src/zope/security/examples/sandbox_security.py64
-rw-r--r--src/zope/security/interfaces.py25
-rw-r--r--src/zope/security/management.py15
-rw-r--r--src/zope/security/metaconfigure.py10
-rw-r--r--src/zope/security/metadirectives.py32
-rw-r--r--src/zope/security/permission.py7
-rw-r--r--src/zope/security/protectclass.py2
-rw-r--r--src/zope/security/proxy.py93
-rw-r--r--src/zope/security/testing.py6
-rw-r--r--src/zope/security/tests/__init__.py3
-rw-r--r--src/zope/security/tests/exampleclass.py4
-rw-r--r--src/zope/security/tests/module.py18
-rw-r--r--src/zope/security/tests/test_adapter.py53
-rw-r--r--src/zope/security/tests/test_checker.py240
-rw-r--r--src/zope/security/tests/test_decorator.py25
-rw-r--r--src/zope/security/tests/test_location.py1
-rw-r--r--src/zope/security/tests/test_management.py5
-rw-r--r--src/zope/security/tests/test_metaconfigure.py35
-rw-r--r--src/zope/security/tests/test_permission.py7
-rw-r--r--src/zope/security/tests/test_protectclass.py1
-rw-r--r--src/zope/security/tests/test_proxy.py223
-rw-r--r--src/zope/security/tests/test_simplepolicies.py4
-rw-r--r--src/zope/security/tests/test_testing.py5
-rw-r--r--src/zope/security/tests/test_zcml.py21
-rw-r--r--src/zope/security/tests/test_zcml_functest.py34
-rw-r--r--src/zope/security/zcml.py5
-rw-r--r--tox.ini73
50 files changed, 1542 insertions, 861 deletions
diff --git a/.coveragerc b/.coveragerc
index 6bd02c1..54c7a9d 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,13 +1,29 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/c-code
[run]
source = zope.security
-omit = */flycheck_*.py
+# 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 =
- pragma: no cover
- pragma NO COVER
+ except ImportError:
if __name__ == '__main__':
- raise NotImplementedError
- self.fail
+ 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..3f0e223
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,456 @@
+# 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: -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__
+
+ ###
+ # 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 }}
+ 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"
+ 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 "::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: Install Build Dependencies
+ run: |
+ pip install -U pip
+ pip install -U setuptools wheel twine cffi
+
+ - name: Build zope.security
+ 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.security build
+ run: |
+ ls -l dist
+ twine check dist/*
+ - name: Upload zope.security wheel
+ uses: actions/upload-artifact@v2
+ with:
+ name: zope.security-${{ 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"
+ 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 "::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 zope.security wheel
+ uses: actions/download-artifact@v2
+ with:
+ name: zope.security-${{ runner.os }}-${{ matrix.python-version }}.whl
+ path: dist/
+ - name: Install zope.security
+ 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.security-*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 "::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 zope.security wheel
+ uses: actions/download-artifact@v2
+ with:
+ name: zope.security-${{ runner.os }}-${{ matrix.python-version }}.whl
+ path: dist/
+ - name: Install zope.security
+ run: |
+ pip install -U wheel
+ pip install -U coverage
+ pip install -U "`ls dist/zope.security-*.whl`[docs]"
+ - name: Build docs
+ env:
+ 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-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 "::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 zope.security wheel
+ uses: actions/download-artifact@v2
+ with:
+ name: zope.security-${{ runner.os }}-${{ matrix.python-version }}.whl
+ path: dist/
+ - name: Install zope.security
+ run: |
+ pip install -U pip
+ pip install -U wheel
+ pip install -U `ls dist/zope.security-*`[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.security -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 }}
+ ###
+ # 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_manylinux-${{ matrix.image }}-${{ matrix.python-version }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+
+ - name: Update pip
+ run: pip install -U pip
+ - name: Build zope.security (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.security (i686)
+ if: matrix.image == 'manylinux2010_i686'
+ env:
+ DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }}
+ PRE_CMD: linux32
+ run: |
+ bash .manylinux.sh
+ - name: Build zope.security (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.security 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 c7adc9b..20b2128 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,19 +1,31 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/c-code
+*.dll
+*.egg-info/
+*.profraw
*.pyc
*.pyo
*.so
-__pycache__
-*.egg
-*.egg-info
-build
-docs/_build
-.installed.cfg
-bin
-develop-eggs
-eggs
-parts
-.tox
.coverage
-nosetests.xml
+.coverage.*
+.eggs/
+.installed.cfg
+.mr.developer.cfg
+.tox/
+.vscode/
+__pycache__/
+bin/
+build/
coverage.xml
-.eggs
-htmlcov/
+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 f82f0c4..5ff565e 100755
--- a/.manylinux-install.sh
+++ b/.manylinux-install.sh
@@ -1,17 +1,49 @@
#!/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
+
# Compile wheels
for PYBIN in /opt/python/*/bin; do
- if [[ "${PYBIN}" == *"cp27"* ]] || \
+ if \
+ [[ "${PYBIN}" == *"cp27"* ]] || \
[[ "${PYBIN}" == *"cp35"* ]] || \
[[ "${PYBIN}" == *"cp36"* ]] || \
[[ "${PYBIN}" == *"cp37"* ]] || \
- [[ "${PYBIN}" == *"cp38"* ]]; then
- "${PYBIN}/pip" install -U pip setuptools cffi
+ [[ "${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
+ "${PYBIN}/tox" -e py
+ 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..04ee500
--- /dev/null
+++ b/.meta.toml
@@ -0,0 +1,62 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/c-code
+[meta]
+template = "c-code"
+commit-id = "15807bd13de45b79c7da560a377fe3f22cbc4338"
+
+[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 = true
+additional-envlist = [
+ "py27-watch, py37-watch",
+ ]
+testenv-setenv = [
+ "ZOPE_INTERFACE_STRICT_IRO=1",
+ "watch: ZOPE_WATCH_CHECKERS = 1",
+ ]
+
+[coverage]
+fail-under = 99.5
+
+[manifest]
+additional-rules = [
+ "include *.sh",
+ "recursive-include docs *.bat",
+ "recursive-include src *.zcml",
+ ]
+
+[check-manifest]
+additional-ignores = [
+ "docs/_build/html/_sources/api/*",
+ ]
+
+[flake8]
+additional-config = [
+ "# F401 imported but unused",
+ "per-file-ignores =",
+ " src/zope/security/__init__.py: F401",
+ ]
+
+[github-actions]
+additional-config = [
+ "- [\"2.7\", \"py27-watch\"]",
+ "- [\"3.7\", \"py37-watch\"]",
+ ]
+
+[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.",
+ "TWINE_USERNAME: __token__",
+ "TWINE_PASSWORD:",
+ " secure: aoZC/+rvJKg8B5GMGIxd1YDPcIbo2kSsckCbQ6o8fhIRqSyuhX1iLm21hgDEkq2ePuyQ7+cWnNvXGactxjzA4iUS5GCOuF/E6YTvS3nGcuoQuH607wn2hngzz1p4Z+5ClFPx27vZiRAFgBoTbIo8XODHC9qFYluZ68eiwxFOiCuXK9ONEjMn8LjoaNSPJYyJO3Wr8W5oLeYG+wGcNGuYVXEk5/LSDg5n17ujpL7qsVTdVNjTwgmtnv191n2ip1Sgh1O5Xm9eG7VDZSxr/xNMpw==",
+ "ZOPE_INTERFACE_STRICT_IRO: 1",
+ ]
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7cb9c7f..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,121 +0,0 @@
-language: python
-
-env:
- global:
- TWINE_USERNAME: zope.wheelbuilder
- TWINE_PASSWORD:
- secure: "U6CeZtNEPDN3qKXfrLcvHFLrowqNWxmapXLWygZRxKgfR+ypowe1Y0a4kCBEBZKtysbY26MmIkrMV07tEMxny1yUWVCvRvUaQw0Ic3t5CM0R019zjVh9fQUTdWGCwri86Qj/OaeuPeMR0LCr6d9nMSun0GWSWhjOUhkTCdchfQw="
- ZOPE_INTERFACE_STRICT_IRO: 1
-
-python:
- - 2.7
- - 3.5
- - 3.6
- - 3.7
- - 3.8
- - pypy
- - pypy3
-
-matrix:
- include:
-
- - name: "Python: 2.7, pure (no C extensions), with ZOPE_WATCH_CHECKERS enabled"
- python: "2.7"
- env: PURE_PYTHON=1 ZOPE_WATCH_CHECKERS=1
-
- - name: "Python: 3.7, with ZOPE_WATCH_CHECKERS enabled"
- python: 3.7
- env: ZOPE_WATCH_CHECKERS=1
-
- - name: "Python: 3.7, pure (no C extensions)"
- python: 3.7
- env: PURE_PYTHON=1
-
- # 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:
- - python -m pip install -U pip setuptools
- - python -m pip install -U coveralls coverage
- # pip install zope.proxy here because because setup_requires will use
- # easy_install, which fails on Python 3.5 on Mac OS
- - python -m pip install -U zope.proxy
- - python -m pip install -U -e .[test,docs]
-
-script:
- - python --version
- - python -m coverage run -m zope.testrunner --test-path=src
- - python -m coverage run -a -m sphinx -b doctest -d docs/_build/doctrees docs docs/_build/doctest
- - python setup.py bdist_wheel
-
-after_success:
- - python -m 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 eb201f4..1be5aa6 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -2,10 +2,10 @@
Changes
=========
-5.1.2 (unreleased)
-==================
+5.2 (unreleased)
+================
-- Nothing changed yet.
+- Add support for Python 3.9 and 3.10.
5.1.1 (2020-03-23)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..e6d84b8
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,23 @@
+<!--
+Generated from:
+https://github.com/zopefoundation/meta/tree/master/config/c-code
+-->
+# 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 3db8c41..72637ed 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,17 +1,19 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/c-code
+include *.md
include *.rst
include *.txt
-include *.py
-include .coveragerc
-include appveyor.yml
-include .travis.yml
-include tox.ini
include buildout.cfg
-include *.sh
-recursive-include docs *.bat
+include tox.ini
+include appveyor.yml
+include .coveragerc
+
recursive-include docs *.py
recursive-include docs *.rst
+recursive-include docs *.txt
recursive-include docs Makefile
+
recursive-include src *.py
+include *.sh
+recursive-include docs *.bat
recursive-include src *.zcml
-
-prune docs/_static
diff --git a/appveyor.yml b/appveyor.yml
index 532f6dd..493bf43 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,11 +1,12 @@
-# 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/+rvJKg8B5GMGIxd1YDPcIbo2kSsckCbQ6o8fhIRqSyuhX1iLm21hgDEkq2ePuyQ7+cWnNvXGactxjzA4iUS5GCOuF/E6YTvS3nGcuoQuH607wn2hngzz1p4Z+5ClFPx27vZiRAFgBoTbIo8XODHC9qFYluZ68eiwxFOiCuXK9ONEjMn8LjoaNSPJYyJO3Wr8W5oLeYG+wGcNGuYVXEk5/LSDg5n17ujpL7qsVTdVNjTwgmtnv191n2ip1Sgh1O5Xm9eG7VDZSxr/xNMpw==
+ # Currently the builds use @mgedmin's Appveyor account. The PyPI token belongs
+ # to zope.wheelbuilder, which is managed by @mgedmin and @dataflake.
+ TWINE_USERNAME: __token__
+ TWINE_PASSWORD:
+ secure: aoZC/+rvJKg8B5GMGIxd1YDPcIbo2kSsckCbQ6o8fhIRqSyuhX1iLm21hgDEkq2ePuyQ7+cWnNvXGactxjzA4iUS5GCOuF/E6YTvS3nGcuoQuH607wn2hngzz1p4Z+5ClFPx27vZiRAFgBoTbIo8XODHC9qFYluZ68eiwxFOiCuXK9ONEjMn8LjoaNSPJYyJO3Wr8W5oLeYG+wGcNGuYVXEk5/LSDg5n17ujpL7qsVTdVNjTwgmtnv191n2ip1Sgh1O5Xm9eG7VDZSxr/xNMpw==
+ ZOPE_INTERFACE_STRICT_IRO: 1
matrix:
- python: 27
@@ -18,10 +19,13 @@ environment:
- python: 37-x64
- python: 38
- python: 38-x64
- - { python: 27, PURE_PYTHON: 1 }
- - { python: 37, PURE_PYTHON: 1 }
+ - 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,31 +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"
-# We need to install the C extensions that BTrees setup-requires
-# separately because we've seen problems with the BTrees build cleanup step trying
-# to delete a .pyd that was still open.
- python -m pip install -U pip
- - pip install -U setuptools
- - pip install -U persistent
- - pip install -U BTrees
- - pip install -U zope.testrunner
- - pip install -U .[test]
+ - pip install -U setuptools wheel
+ - pip install -U -e .[test]
+
+matrix:
+ fast_finish: true
build_script:
- - pip install wheel
- python -W ignore setup.py -q bdist_wheel
test_script:
- - python -m zope.testrunner --test-path=src
-
-on_success:
- - echo Build succesful!
-
+ - zope-testrunner --test-path=src
artifacts:
- path: 'dist\*.whl'
name: wheel
deploy_script:
- - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE -and $env:PURE_PYTHON -ne 1) { 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/proxy.rst b/docs/proxy.rst
index 5262e7a..971975e 100644
--- a/docs/proxy.rst
+++ b/docs/proxy.rst
@@ -320,7 +320,10 @@ unexpectedly:
.. doctest::
- >>> from collections import Mapping
+ >>> try:
+ ... from collections.abc import Mapping
+ ... except ImportError: # PY2
+ ... from collections import Mapping
>>> from abc import ABCMeta
>>> isinstance(Mapping, ABCMeta)
True
diff --git a/setup.cfg b/setup.cfg
index 6ceb809..3aa3064 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,11 +1,21 @@
-[nosetests]
-nocapture=1
-cover-package=zope.security
-cover-erase=1
-with-doctest=0
-where=src
-exclude=untrustedpython
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/c-code
+[bdist_wheel]
+universal = 1
-[aliases]
-dev = develop easy_install zope.security[testing]
-docs = easy_install zope.security[docs]
+[zest.releaser]
+create-wheel = no
+
+[flake8]
+doctests = 1
+# F401 imported but unused
+per-file-ignores =
+ src/zope/security/__init__.py: F401
+
+[check-manifest]
+ignore =
+ .editorconfig
+ .meta.toml
+ docs/_build/html/_sources/*
+ docs/_build/doctest/*
+ docs/_build/html/_sources/api/*
diff --git a/setup.py b/setup.py
index c049a00..470416a 100644
--- a/setup.py
+++ b/setup.py
@@ -33,10 +33,12 @@ from setuptools.command.build_ext import build_ext
from setuptools import find_packages
from setuptools import setup
+
class optional_build_ext(build_ext):
"""This class subclasses build_ext and allows
the building of C extensions to fail.
"""
+
def run(self):
try:
build_ext.run(self)
@@ -59,14 +61,17 @@ class optional_build_ext(build_ext):
print('*' * 80)
-
here = os.path.abspath(os.path.dirname(__file__))
+
+
def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()
# Include directories for C extensions
# Sniff the location of the headers in the package distribution
+
+
class ModuleHeaderDir(object):
def __init__(self, require_spec, where='../..'):
@@ -84,6 +89,7 @@ class ModuleHeaderDir(object):
path = resource_filename(self._require_spec, self._where)
return os.path.abspath(path)
+
include = [ModuleHeaderDir('zope.proxy')]
codeoptimization = [
@@ -127,7 +133,7 @@ TESTS_REQUIRE = [
setup(name='zope.security',
- version='5.1.2.dev0',
+ version='5.2.dev0',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='Zope Security Framework',
@@ -150,6 +156,8 @@ setup(name='zope.security',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Natural Language :: English',
@@ -193,8 +201,10 @@ setup(name='zope.security',
'docs': [
'Sphinx',
'repoze.sphinx.autointerface',
+ 'zope.configuration',
+ 'zope.testing',
],
},
include_package_data=True,
zip_safe=False,
-)
+ )
diff --git a/src/zope/security/__init__.py b/src/zope/security/__init__.py
index 5f079f6..d6f39f4 100644
--- a/src/zope/security/__init__.py
+++ b/src/zope/security/__init__.py
@@ -21,4 +21,3 @@ from zope.security.checker import canWrite, canAccess
# zope.location's LocationProxy as soon someone uses security proxies by
# importing zope.security.proxy:
import zope.security.decorator
-
diff --git a/src/zope/security/_compat.py b/src/zope/security/_compat.py
index 07b3a02..6f7dc0a 100644
--- a/src/zope/security/_compat.py
+++ b/src/zope/security/_compat.py
@@ -22,7 +22,7 @@ py_impl = getattr(platform, 'python_implementation', lambda: None)
PYPY = py_impl() == 'PyPy'
PURE_PYTHON = os.environ.get('PURE_PYTHON', PYPY)
-if sys.version_info[0] < 3: # pragma: no cover
+if sys.version_info[0] < 3: # pragma: no cover
CLASS_TYPES = (type, types.ClassType)
_BUILTINS = '__builtin__'
@@ -30,7 +30,7 @@ if sys.version_info[0] < 3: # pragma: no cover
PYTHON3 = False
PYTHON2 = True
-else: # pragma: no cover
+else: # pragma: no cover
CLASS_TYPES = (type,)
_BUILTINS = 'builtins'
diff --git a/src/zope/security/_definitions.py b/src/zope/security/_definitions.py
index 929823c..070a345 100644
--- a/src/zope/security/_definitions.py
+++ b/src/zope/security/_definitions.py
@@ -20,10 +20,12 @@ from zope.security import interfaces
thread_local = threading.local()
+
@zope.interface.implementer(interfaces.ISystemPrincipal)
class SystemUser(object):
id = u'zope.security.management.system_user'
title = u'System'
description = u''
+
system_user = SystemUser()
diff --git a/src/zope/security/adapter.py b/src/zope/security/adapter.py
index 661e49d..c8c44b6 100644
--- a/src/zope/security/adapter.py
+++ b/src/zope/security/adapter.py
@@ -18,6 +18,7 @@ from zope.security.checker import ProxyFactory
from zope.security.proxy import removeSecurityProxy
from zope.location import ILocation, LocationProxy
+
def assertLocation(adapter, parent):
"""
Assert locatable adapters.
@@ -59,6 +60,7 @@ class LocatingTrustedAdapterFactory(object):
``__parent__`` is None, we set the ``__parent__`` to the adapter's
context.
"""
+
def __init__(self, factory):
self.factory = factory
self.__name__ = factory.__name__
diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py
index 2dbc4e1..fe570d1 100644
--- a/src/zope/security/checker.py
+++ b/src/zope/security/checker.py
@@ -36,14 +36,16 @@ You can set the environment variable ``ZOPE_WATCH_CHECKERS`` before
this module is imported to get additional security checker debugging
output on the standard error.
-Setting ``ZOPE_WATCH_CHECKERS`` to 1 will display messages about unauthorized or
-forbidden attribute access. Setting it to a larger number will also display
+Setting ``ZOPE_WATCH_CHECKERS`` to 1 will display messages about unauthorized
+or forbidden attribute access. Setting it to a larger number will also display
messages about granted attribute access.
Note that the ``ZOPE_WATCH_CHECKERS`` mechanism may eventually be
replaced with a more general security auditing mechanism.
-.. seealso:: :class:`CheckerLoggingMixin`, :class:`WatchingChecker`, :class:`WatchingCombinedChecker`
+.. seealso:: :class:`CheckerLoggingMixin`
+.. seealso:: :class:`WatchingChecker`
+.. seealso:: :class:`WatchingCombinedChecker`
API
===
@@ -88,16 +90,16 @@ from zope.security.proxy import getChecker
try:
from zope.exceptions import DuplicationError
-except ImportError: # pragma: no cover
+except ImportError: # pragma: no cover
class DuplicationError(Exception):
"""A duplicate registration was attempted"""
WATCH_CHECKERS = 0
-if os.environ.get('ZOPE_WATCH_CHECKERS'):
+if os.environ.get('ZOPE_WATCH_CHECKERS'): # pragma: no cover
try:
WATCH_CHECKERS = int(os.environ.get('ZOPE_WATCH_CHECKERS'))
- except ValueError: # pragma: no cover
+ except ValueError:
WATCH_CHECKERS = 1
@@ -129,12 +131,14 @@ def ProxyFactory(object, checker=None):
return Proxy(object, checker)
+
directlyProvides(ProxyFactory, ISecurityProxyFactory)
# This import represents part of the API for the proxy module
-from . import proxy
+from . import proxy # noqa: E402 module level import not at top
proxy.ProxyFactory = ProxyFactory
+
def canWrite(obj, name):
"""Check whether the interaction may write an attribute named name on obj.
@@ -169,6 +173,7 @@ def canWrite(obj, name):
# should be passed through uncaught, as they indicate programmer error
return True
+
def canAccess(obj, name):
"""Check whether the interaction may access an attribute named name on obj.
@@ -187,6 +192,7 @@ def canAccess(obj, name):
# indicates a programming or configuration error
return True
+
@implementer(INameBasedChecker)
class CheckerPy(object):
"""
@@ -230,7 +236,6 @@ class CheckerPy(object):
if self.set_permissions:
return self.set_permissions.get(name)
-
def check_setattr(self, object, name):
'See IChecker'
if self.set_permissions:
@@ -240,9 +245,9 @@ class CheckerPy(object):
if permission is not None:
if permission is CheckerPublic:
- return # Public
+ return # Public
if thread_local.interaction.checkPermission(permission, object):
- return # allowed
+ return # allowed
else:
__traceback_supplement__ = (TracebackSupplement, object)
raise Unauthorized(object, name, permission)
@@ -255,7 +260,7 @@ class CheckerPy(object):
permission = self.get_permissions.get(name)
if permission is not None:
if permission is CheckerPublic:
- return # Public
+ return # Public
if thread_local.interaction.checkPermission(permission, object):
return
else:
@@ -268,7 +273,7 @@ class CheckerPy(object):
__traceback_supplement__ = (TracebackSupplement, object)
raise ForbiddenAttribute(name, object)
- check_getattr = check # 'See IChecker'
+ check_getattr = check # 'See IChecker'
def proxy(self, value):
'See IChecker'
@@ -281,7 +286,9 @@ class CheckerPy(object):
return value
return Proxy(value, checker)
-Checker = CheckerPy # in case no C optimizations
+
+
+Checker = CheckerPy # in case no C optimizations
# Helper class for __traceback_supplement__
@@ -296,19 +303,19 @@ class TracebackSupplement(object):
cls = self.obj.__class__
if hasattr(cls, "__module__"):
s = "%s.%s" % (cls.__module__, cls.__name__)
- else: # pragma: no cover XXX
+ else: # pragma: no cover XXX
s = str(cls.__name__)
result.append(" - class: " + s)
- except: # pragma: no cover XXX
+ except: # pragma: no cover # noqa: E722 do not use bare 'except'
pass
try:
cls = type(self.obj)
if hasattr(cls, "__module__"):
s = "%s.%s" % (cls.__module__, cls.__name__)
- else: # pragma: no cover XXX
+ else: # pragma: no cover XXX
s = str(cls.__name__)
result.append(" - type: " + s)
- except: # pragma: no cover XXX
+ except: # pragma: no cover # noqa: E722 do not use bare 'except'
pass
return "\n".join(result)
@@ -322,7 +329,7 @@ class Global(object):
"""
def __init__(self, name, module=None):
- if module is None: # pragma: no cover XXX
+ if module is None: # pragma: no cover XXX
module = sys._getframe(1).f_locals['__name__']
self.__name__ = name
@@ -344,7 +351,7 @@ CP_HACK_XXX = CheckerPublic
# XXX: This means that we can't directly document it with
# sphinx because issubclass() will fail.
d = {}
-CheckerPublic = Proxy(CheckerPublic, Checker(d)) # XXX uses CheckerPy
+CheckerPublic = Proxy(CheckerPublic, Checker(d)) # XXX uses CheckerPy
d['__reduce__'] = CheckerPublic
d['__module__'] = CheckerPublic
del d
@@ -353,6 +360,7 @@ del d
# granted to __reduce__. We might want to bother to prevent this in
# general and only allow it in this specific case.
+
def NamesChecker(names=(), permission_id=CheckerPublic, **__kw__):
"""Return a checker that grants access to a set of names.
@@ -371,6 +379,7 @@ def NamesChecker(names=(), permission_id=CheckerPublic, **__kw__):
return Checker(data)
+
def InterfaceChecker(interface, permission_id=CheckerPublic, **__kw__):
"""
Create a :func:`NamesChecker` for all the names defined in the *interface*
@@ -378,6 +387,7 @@ def InterfaceChecker(interface, permission_id=CheckerPublic, **__kw__):
"""
return NamesChecker(interface.names(all=True), permission_id, **__kw__)
+
def MultiChecker(specs):
"""
Create a checker from a sequence of specifications
@@ -415,6 +425,7 @@ def MultiChecker(specs):
return Checker(data)
+
def selectCheckerPy(object):
"""Get a checker for the given object
@@ -428,13 +439,13 @@ def selectCheckerPy(object):
# TODO: we really need formal proxy introspection
- #if type(object) is Proxy:
+ # if type(object) is Proxy:
# # Is this already a security proxy?
# return None
checker = _getChecker(type(object), _defaultChecker)
- #checker = _getChecker(getattr(object, '__class__', type(object)),
+ # checker = _getChecker(getattr(object, '__class__', type(object)),
# _defaultChecker)
if checker is NoProxy:
@@ -447,12 +458,18 @@ def selectCheckerPy(object):
return None
return checker
-selectChecker = selectCheckerPy # in case no C optimizations
+
+
+selectChecker = selectCheckerPy # in case no C optimizations
+
def getCheckerForInstancesOf(class_):
return _checkers.get(class_)
+
DEFINABLE_TYPES = CLASS_TYPES + (types.ModuleType,)
+
+
def defineChecker(type_, checker):
"""Define a checker for a given type of object
@@ -466,9 +483,11 @@ def defineChecker(type_, checker):
raise DuplicationError(type_)
_checkers[type_] = checker
+
def undefineChecker(type_):
del _checkers[type_]
+
NoProxy = object()
# _checkers is a mapping.
@@ -488,13 +507,13 @@ _available_by_default = []
# Get optimized versions
_c_available = not PURE_PYTHON
-if _c_available:
+if _c_available: # pragma: no cover
try:
import zope.security._zope_security_checker
- except (ImportError, AttributeError): # pragma: no cover PyPy / PURE_PYTHON
+ except (ImportError, AttributeError):
_c_available = False
-if _c_available:
+if _c_available: # pragma: no cover
from zope.security._zope_security_checker import _checkers, selectChecker
from zope.security._zope_security_checker import NoProxy, Checker
from zope.security._zope_security_checker import _defaultChecker
@@ -504,6 +523,7 @@ if _c_available:
_getChecker = _checkers.get
+
@implementer_if_needed(IChecker)
class CombinedChecker(Checker):
"""A checker that combines two other checkers in a logical-or fashion.
@@ -527,7 +547,7 @@ class CombinedChecker(Checker):
+--------------------+--------------------+-------------------------------------+
| ForbiddenAttribute | ForbiddenAttribute | ForbiddenAttribute |
+--------------------+--------------------+-------------------------------------+
- """
+ """ # noqa: E501 line too long
def __init__(self, checker1, checker2):
"""Create a combined checker."""
@@ -544,7 +564,8 @@ class CombinedChecker(Checker):
except ForbiddenAttribute:
self._checker2.check(object, name)
except Unauthorized as unauthorized_exception:
- try: self._checker2.check(object, name)
+ try:
+ self._checker2.check(object, name)
except ForbiddenAttribute:
raise unauthorized_exception
@@ -562,6 +583,7 @@ class CombinedChecker(Checker):
except ForbiddenAttribute:
raise unauthorized_exception
+
class CheckerLoggingMixin(object):
"""
Debugging mixin for checkers.
@@ -649,6 +671,8 @@ class WatchingChecker(CheckerLoggingMixin, Checker):
module is imported.
"""
verbosity = WATCH_CHECKERS
+
+
class WatchingCombinedChecker(CombinedChecker, WatchingChecker):
"""
A checker that will perform verbose logging. This will be set
@@ -657,7 +681,8 @@ class WatchingCombinedChecker(CombinedChecker, WatchingChecker):
"""
verbosity = WATCH_CHECKERS
-if WATCH_CHECKERS: # pragma: no cover
+
+if WATCH_CHECKERS: # pragma: no cover
# When we make these the default, we also need to be sure
# to update the _defaultChecker's type (if it's not the C
# extension) so that selectCheckerPy can properly recognize
@@ -669,9 +694,11 @@ if WATCH_CHECKERS: # pragma: no cover
if not _c_available:
_defaultChecker.__class__ = Checker
+
def _instanceChecker(inst):
return _checkers.get(inst.__class__, _defaultChecker)
+
def moduleChecker(module):
"""
Return the :class:`zope.security.interfaces.IChecker` defined for the
@@ -713,11 +740,13 @@ _setChecker = NamesChecker([
'__le__', '__ge__',
])
+
class _BasicTypes(dict):
"""Basic Types Dictionary
Make sure that checkers are really updated, when a new type is added.
"""
+
def __setitem__(self, name, value):
dict.__setitem__(self, name, value)
_checkers[name] = value
@@ -734,6 +763,7 @@ class _BasicTypes(dict):
dict.update(self, d)
_checkers.update(d)
+
_basic_types = {
object: NoProxy,
int: NoProxy,
@@ -742,7 +772,7 @@ _basic_types = {
type(None): NoProxy,
str: NoProxy,
bytes: NoProxy,
- Message: NoProxy, # Messages are immutable, so it's okay
+ Message: NoProxy, # Messages are immutable, so it's okay
bool: NoProxy,
datetime.timedelta: NoProxy,
datetime.datetime: NoProxy,
@@ -750,10 +780,10 @@ _basic_types = {
datetime.time: NoProxy,
datetime.tzinfo: NoProxy,
}
-if PYTHON2:
- _basic_types[long] = NoProxy
- _basic_types[unicode] = NoProxy
-else: # pragma: no cover
+if PYTHON2: # pragma: no cover
+ _basic_types[long] = NoProxy # noqa: F821 undefined name 'long'
+ _basic_types[unicode] = NoProxy # noqa: F821 undefined name 'unicode'
+else:
_basic_types[type({}.values())] = NoProxy
_basic_types[type({}.keys())] = NoProxy
_basic_types[type({}.items())] = NoProxy
@@ -784,26 +814,29 @@ BasicTypes_examples = {
Message: Message('message', domain='hello')
}
-if PYTHON2:
- BasicTypes_examples[unicode] = u'uabc'
- BasicTypes_examples[long] = long(65536)
+if PYTHON2: # pragma: no cover
+ BasicTypes_examples[unicode] = u'uabc' # noqa: F821 undefined name
+ BasicTypes_examples[long] = long(65536) # noqa: F821 undefined name
class _Sequence(object):
def __len__(self):
raise NotImplementedError()
+
def __getitem__(self, i):
raise NotImplementedError()
+
_Declaration_checker = InterfaceChecker(
IDeclaration,
_implied=CheckerPublic,
subscribe=CheckerPublic,
unsubscribe=CheckerPublic,
__call__=CheckerPublic,
- )
+)
+
-def f(): # pragma: no cover
+def f(): # pragma: no cover
yield f
@@ -837,7 +870,7 @@ _default_checkers = {
'max', 'min', 'normalize',
'quantize', 'remainder_near',
'same_quantum', 'sqrt',
- 'to_eng_string', 'to_integral' ]),
+ 'to_eng_string', 'to_integral']),
# YAGNI: () a rock
tuple: NamesChecker(['__getitem__', '__getslice__', '__add__', '__radd__',
@@ -851,8 +884,8 @@ _default_checkers = {
types.BuiltinMethodType: _callableChecker,
type: _typeChecker,
types.ModuleType: lambda module: _checkers.get(module, _namedChecker),
- type(iter([])): _iteratorChecker, # Same types in Python 2.2.1,
- type(iter(())): _iteratorChecker, # different in Python 2.3.
+ type(iter([])): _iteratorChecker, # Same types in Python 2.2.1,
+ type(iter(())): _iteratorChecker, # different in Python 2.3.
type(iter({})): _iteratorChecker,
type(iter(set())): _iteratorChecker,
type(iter(_Sequence())): _iteratorChecker,
@@ -875,7 +908,7 @@ _default_checkers = {
zope.interface.declarations.Declaration: _Declaration_checker,
abc.ABCMeta: _typeChecker,
}
-if PYTHON2:
+if PYTHON2: # pragma: no cover
_default_checkers[types.ClassType] = _typeChecker
_default_checkers[types.InstanceType] = _instanceChecker
# slot description
@@ -884,6 +917,7 @@ if PYTHON2:
_default_checkers[type({}.iterkeys())] = _iteratorChecker
_default_checkers[type({}.itervalues())] = _iteratorChecker
+
def _fixup_dictlike(dict_type):
empty_dict = dict_type()
populated_dict = dict_type({1: 2})
@@ -898,20 +932,24 @@ def _fixup_dictlike(dict_type):
if iter_type not in _default_checkers:
_default_checkers[iter_type] = _iteratorChecker
+
def _fixup_odict():
# OrderedDicts have three different implementations: Python 2 (pure
# python, returns generators and lists), Python <=3.4 (pure Python,
# uses view classes) and CPython 3.5+ (implemented in C). These should
# all be iterable.
from collections import OrderedDict
- _fixup_dictlike(OrderedDict)
+ # The `_fixup_dictlike` is detected as undefined because it is deleted
+ # later on but this function is called beforehand:
+ _fixup_dictlike(OrderedDict) # noqa: F821 undefined name '_fixup_dictlike'
+
_fixup_odict()
del _fixup_odict
try:
- import BTrees
-except ImportError: # pragma: no cover
+ import BTrees # noqa: F401 'BTrees' imported but unused
+except ImportError: # pragma: no cover
pass
else:
# The C implementation of BTree.items() is its own iterator
@@ -934,13 +972,16 @@ else:
for family_name in ('family32', 'family64'):
family = getattr(BTrees, family_name)
btree = getattr(family, name).BTree
- _fixup_dictlike(btree)
+ # The `_fixup_dictlike` is detected as undefined because it is
+ # deleted later on but this function is called beforehand:
+ _fixup_dictlike(btree) # noqa: F821 undefined name
_fixup_btrees()
del _fixup_btrees
del _fixup_dictlike
+
def _fixup_zope_interface():
# Make sure the provided and implementedBy objects
# can be iterated.
@@ -948,7 +989,8 @@ def _fixup_zope_interface():
# we use NoProxy to be sure that the results (of iteration or not) are not
# proxied. On Python 2, these objects are builtin and don't go through the
# checking process at all, much like BTrees, so NoProxy is necessary for
- # compatibility. On Python 3, prior to this, iteration was simply not allowed.
+ # compatibility. On Python 3, prior to this, iteration was simply not
+ # allowed.
from zope.interface import providedBy
from zope.interface import alsoProvides
@@ -959,11 +1001,10 @@ def _fixup_zope_interface():
pass
@implementer(I1)
- class O(object):
+ class Obj(object):
pass
- o = O()
-
+ o = Obj()
# This will be athe zope.interface.implementedBy from the class
# a zope.interface.declarations.Implements
@@ -973,6 +1014,7 @@ def _fixup_zope_interface():
# This will be the zope.interface.Provides from the instance
_default_checkers[type(providedBy(o))] = NoProxy
+
_fixup_zope_interface()
del _fixup_zope_interface
@@ -998,8 +1040,10 @@ def _fixup_itertools():
_default_checkers[type_grouper] = _iteratorChecker
# There are also many other custom types in itertools that need the
- # same treatment. See a similar list in test_checker.py:test_itertools_checkers
- pred = lambda x: x
+ # same treatment. See a similar list in
+ # test_checker.py:test_itertools_checkers
+ def pred(x):
+ return x
iterable = (1, 2, 3)
pred_iterable = (pred, iterable)
missing_in_py3 = {'ifilter', 'ifilterfalse', 'imap',
@@ -1034,7 +1078,8 @@ def _fixup_itertools():
func = getattr(itertools, func)
except AttributeError:
assert func in missing, "Expected %s but not found" % (func,)
- continue # pragma: no cover This is hit on Python 2, but it doesn't always show
+ # The following line is hit on PY2, but it doesn't always show:
+ continue # pragma: no cover
result = func(*args)
if func == itertools.tee:
@@ -1043,19 +1088,22 @@ def _fixup_itertools():
if tresult not in _default_checkers:
_default_checkers[tresult] = _iteratorChecker
+
_fixup_itertools()
del _fixup_itertools
+
def _clear():
_checkers.clear()
_checkers.update(_default_checkers)
_checkers.update(BasicTypes)
+
_clear()
try:
from zope.testing.cleanup import addCleanUp
-except ImportError: # pragma: no cover
+except ImportError: # pragma: no cover
pass
else:
addCleanUp(_clear)
diff --git a/src/zope/security/decorator.py b/src/zope/security/decorator.py
index 82ae6e2..0f9f2f4 100644
--- a/src/zope/security/decorator.py
+++ b/src/zope/security/decorator.py
@@ -30,6 +30,7 @@ from zope.security.proxy import getChecker
class DecoratedSecurityCheckerDescriptor(object):
"""Descriptor for a Decorator that provides a decorated security checker.
"""
+
def __get__(self, inst, cls=None):
if inst is None:
return self
@@ -58,7 +59,7 @@ class DecoratedSecurityCheckerDescriptor(object):
class SecurityCheckerDecoratorBase(ProxyBase):
- """Base class for a proxy that provides additional security declarations."""
+ """Base class for proxy that provides additional security declarations."""
__Security_checker__ = DecoratedSecurityCheckerDescriptor()
@@ -73,6 +74,6 @@ class DecoratorBase(SpecificationDecoratorBase, SecurityCheckerDecoratorBase):
# location proxy from here.
# This is the only sane place we found for doing it: it kicks in as soon
# as someone starts using security proxies.
-import zope.location.location
+import zope.location.location # noqa: E402 module level import not at top
zope.location.location.LocationProxy.__Security_checker__ = (
DecoratedSecurityCheckerDescriptor())
diff --git a/src/zope/security/examples/sandbox.py b/src/zope/security/examples/sandbox.py
index 8a17984..eb6499f 100644
--- a/src/zope/security/examples/sandbox.py
+++ b/src/zope/security/examples/sandbox.py
@@ -13,13 +13,15 @@
##############################################################################
"""A small sandbox application.
"""
-import time, random
+import time
+import random
from zope.interface import Interface, implementer
+
class IAgent(Interface):
"""A player/agent in the world.
-
+
The agent represents an autonomous unit, that lives in various
homes/sandboxes and accesses services present at the sandboxes. Agents are
imbued with a sense of wanderlust and attempt to find new homes after a
@@ -40,7 +42,7 @@ class IAgent(Interface):
class IService(Interface):
"""Marker to designate some form of functionality.
-
+
Services are available from sandboxes, examples include time service,
agent discovery, and sandbox discovery.
"""
@@ -63,20 +65,21 @@ class ISandbox(Interface):
class SandboxError(Exception):
- """A sandbox error is thrown, if any action could not be performed."""
+ """A sandbox error is thrown, if any action could not be performed."""
pass
class Identity(object):
"""Mixin for pretty printing and identity method"""
+
def __init__(self, id, *args, **kw):
self.id = id
def getId(self):
return self.id
- def __str__ (self):
- return "<%s> %s"%(str(self.__class__.__name__), str(self.id))
+ def __str__(self):
+ return "<%s> %s" % (str(self.__class__.__name__), str(self.id))
__repr__ = __str__
@@ -124,92 +127,109 @@ class Sandbox(Identity):
def getAgentIds(self):
return self._agents.keys()
+
def getAgents(self):
return self._agents.values()
+
def getServiceIds(self):
return self._services.keys()
+
def getService(self, sid):
return self._services.get(sid)
+
def getHome(self):
return self
-
def addAgent(self, agent):
- if not self._agents.has_key(agent.getId()) \
- and IAgent.providedBy(agent):
- self._agents[agent.getId()]=agent
+ if agent.getId() not in self._agents \
+ and IAgent.providedBy(agent):
+ self._agents[agent.getId()] = agent
agent.setHome(self)
else:
- raise SandboxError("couldn't add agent %s"%agent)
+ raise SandboxError("couldn't add agent %s" % agent)
def addService(self, service):
- if not self._services.has_key(service.getId()) \
- and IService.providedBy(service):
- self._services[service.getId()]=service
+ if not service.getId() in self._services \
+ and IService.providedBy(service):
+ self._services[service.getId()] = service
service.setHome(self)
else:
- raise SandboxError("couldn't add service %s"%service)
+ raise SandboxError("couldn't add service %s" % service)
def transportAgent(self, agent, destination):
- if self._agents.has_key(agent.getId()) \
- and destination is not self \
- and ISandbox.providedBy(destination):
+ if agent.getId() in self._agents \
+ and destination is not self \
+ and ISandbox.providedBy(destination):
destination.addAgent(agent)
del self._agents[agent.getId()]
else:
- raise SandboxError("couldn't transport agent %s to %s"%(
+ raise SandboxError("couldn't transport agent %s to %s" % (
agent, destination)
- )
+ )
+
@implementer(IService)
class Service(object):
def getId(self):
return self.__class__.__name__
+
def setHome(self, home):
self._home = home
+
def getHome(self):
return getattr(self, '_home')
+
class HomeDiscoveryService(Service):
"""
returns the ids of available agent homes
"""
+
def getAvailableHomes(self):
return _homes.keys()
+
class AgentDiscoveryService(Service):
"""
returns the agents available at a given home
"""
+
def getLocalAgents(self, home):
return home.getAgents()
+
class TimeService(Service):
"""
returns the local time
"""
+
def getTime(self):
return time.time()
+
default_service_factories = (
HomeDiscoveryService,
AgentDiscoveryService,
TimeService
- )
+)
+
def action_find_homes(agent, home):
home_service = home.getService('HomeDiscoveryService')
return home_service.getAvailableHomes()
+
def action_find_neighbors(agent, home):
agent_service = home.getService('AgentDiscoveryService')
return agent_service.getLocalAgents(home)
+
def action_find_time(agent, home):
time_service = home.getService('TimeService')
return time_service.getTime()
+
class TimeGenerator(object):
"""Represents the passage of time in the agent simulation.
@@ -238,7 +258,7 @@ class TimeGenerator(object):
except Exception as e:
print('-- Exception --')
print('"%s" in "%s" not allow to "%s"'
- % (a, h, a._action.__name__))
+ % (a, h, a._action.__name__))
print(e)
print()
self.teardownAgent(a)
@@ -253,7 +273,8 @@ class TimeGenerator(object):
home.transportAgent(a, new_home)
except Exception as e:
print('-- Exception --')
- print('moving "%s" from "%s" to "%s"' %(a, h, repr(new_home)))
+ print('moving "%s" from "%s" to "%s"' %
+ (a, h, repr(new_home)))
print(e)
print()
self.teardownAgent(a)
@@ -264,6 +285,7 @@ def WanderLust(agent):
if int(random.random()*100) <= 30:
return 1
+
def GreenerPastures(agent):
""" where do they want to go today """
global _homes
@@ -286,7 +308,7 @@ all_homes = (
origin = all_homes[1]
for h in all_homes:
- _homes[h.getId()]=h
+ _homes[h.getId()] = h
agents = [
@@ -296,7 +318,7 @@ agents = [
Agent('thucydides', None, 'greek men', action_find_time),
Agent('archimedes', None, 'greek men', action_find_neighbors),
Agent('prometheus', None, 'greek men', action_find_homes),
- ]
+]
for a in agents:
origin.addAgent(a)
@@ -312,5 +334,6 @@ def main():
for h in _homes.values():
print(h.getId(), h.getAgentIds())
+
if __name__ == '__main__':
main()
diff --git a/src/zope/security/examples/sandbox_security.py b/src/zope/security/examples/sandbox_security.py
index d0bfe15..5115ca7 100644
--- a/src/zope/security/examples/sandbox_security.py
+++ b/src/zope/security/examples/sandbox_security.py
@@ -17,13 +17,13 @@ This module is responsible of securing the sandbox application and run it in a
secure mode. There are several steps that are taken to set up the security
1. map permissions to actions
-
+
2. map authentication tokens/principals onto permissions
-
+
3. implement checker and security policies that affect 1,2
-
+
4. bind checkers to classes/instances
-
+
5. proxy wrap as necessary
"""
import sandbox
@@ -32,7 +32,7 @@ from zope.security import checker, management, simplepolicies
from zope.interface import implementer
-# Define all permissions that will be available
+# Define all permissions that will be available
NotAllowed = 'Not Allowed'
Public = checker.CheckerPublic
TransportAgent = 'Transport Agent'
@@ -43,9 +43,10 @@ AccessAgentService = 'Access Agent Service'
AccessHomeService = 'Access Home Service'
AddAgent = 'Add Agent'
-ALL='All'
+ALL = 'All'
+
-NoSetAttr = lambda name: NotAllowed
+def NoSetAttr(name): return NotAllowed
class SimulationSecurityDatabase(object):
@@ -55,20 +56,20 @@ class SimulationSecurityDatabase(object):
permissions.
"""
origin = {
- 'any' : [ALL]
- }
+ 'any': [ALL]
+ }
jail = {
- 'norse legend' : [TransportAgent, AccessServices, AccessAgentService,
- AccessHomeService, TransportAgent, AccessAgents],
- 'any' : [AccessTimeService, AddAgent]
- }
+ 'norse legend': [TransportAgent, AccessServices, AccessAgentService,
+ AccessHomeService, TransportAgent, AccessAgents],
+ 'any': [AccessTimeService, AddAgent]
+ }
valhalla = {
- 'norse legend' : [AddAgent],
- 'any' : [AccessServices, AccessTimeService, AccessAgentService,
- AccessHomeService, TransportAgent, AccessAgents]
- }
+ 'norse legend': [AddAgent],
+ 'any': [AccessServices, AccessTimeService, AccessAgentService,
+ AccessHomeService, TransportAgent, AccessAgents]
+ }
class SimulationSecurityPolicy(simplepolicies.ParanoidSecurityPolicy):
@@ -108,7 +109,6 @@ class AgentParticipation(object):
A very simple participation that is specific to the simulations.
"""
-
def __init__(self, agent):
self.principal = agent
self.interaction = None
@@ -130,27 +130,27 @@ def PermissionMapChecker(permissions_map=None, set_permissions=None):
#################################
# sandbox security settings
sandbox_security = {
- AccessServices : ['getService', 'addService', 'getServiceIds'],
- AccessAgents : ['getAgentsIds', 'getAgents'],
- AddAgent : ['addAgent'],
- TransportAgent : ['transportAgent'],
- Public : ['getId','getHome']
- }
+ AccessServices: ['getService', 'addService', 'getServiceIds'],
+ AccessAgents: ['getAgentsIds', 'getAgents'],
+ AddAgent: ['addAgent'],
+ TransportAgent: ['transportAgent'],
+ Public: ['getId', 'getHome']
+}
sandbox_checker = PermissionMapChecker(sandbox_security)
#################################
# service security settings
# time service
-tservice_security = { AccessTimeService:['getTime'] }
+tservice_security = {AccessTimeService: ['getTime']}
time_service_checker = PermissionMapChecker(tservice_security)
# home service
-hservice_security = { AccessHomeService:['getAvailableHomes'] }
+hservice_security = {AccessHomeService: ['getAvailableHomes']}
home_service_checker = PermissionMapChecker(hservice_security)
# agent service
-aservice_security = { AccessAgentService:['getLocalAgents'] }
+aservice_security = {AccessAgentService: ['getLocalAgents']}
agent_service_checker = PermissionMapChecker(aservice_security)
@@ -164,14 +164,14 @@ def wire_security():
checker.defineChecker(sandbox.HomeDiscoveryService, home_service_checker)
def addAgent(self, agent):
- if not self._agents.has_key(agent.getId()) \
- and sandbox.IAgent.providedBy(agent):
- self._agents[agent.getId()]=agent
+ if (agent.getId() not in self._agents
+ and sandbox.IAgent.providedBy(agent)):
+ self._agents[agent.getId()] = agent
agentChecker = checker.selectChecker(self)
wrapped_home = agentChecker.proxy(self)
agent.setHome(wrapped_home)
else:
- raise sandbox.SandboxError("couldn't add agent %s" %agent)
+ raise sandbox.SandboxError("couldn't add agent %s" % agent)
sandbox.Sandbox.addAgent = addAgent
@@ -191,7 +191,7 @@ def wire_security():
_homes = sandbox._homes
possible_homes = _homes.keys()
possible_homes.remove(agent.getHome().getId())
- new_home = _homes.get(random.choice(possible_homes))
+ new_home = _homes.get(random.choice(possible_homes))
return checker.selectChecker(new_home).proxy(new_home)
sandbox.GreenerPastures = GreenerPastures
diff --git a/src/zope/security/interfaces.py b/src/zope/security/interfaces.py
index 74cd385..890e6fc 100644
--- a/src/zope/security/interfaces.py
+++ b/src/zope/security/interfaces.py
@@ -62,6 +62,7 @@ from zope.security.i18n import ZopeMessageFactory as _
#: .. versionadded:: 4.2.0
PUBLIC_PERMISSION_NAME = 'zope.Public'
+
class IUnauthorized(IException):
"""
The action is not authorized.
@@ -69,6 +70,7 @@ class IUnauthorized(IException):
Implemented in :class:`Unauthorized`.
"""
+
@implementer(IUnauthorized)
class Unauthorized(Exception):
"""
@@ -77,6 +79,7 @@ class Unauthorized(Exception):
Default implementation of :class:`IUnauthorized`.
"""
+
class IForbidden(IException):
"""
A resource cannot be accessed under any circumstances
@@ -84,6 +87,7 @@ class IForbidden(IException):
Implemented in :class:`Forbidden`.
"""
+
@implementer(IForbidden)
class Forbidden(Exception):
"""
@@ -92,6 +96,7 @@ class Forbidden(Exception):
Default implementation if :class:`IForbidden`.
"""
+
class IForbiddenAttribute(IForbidden, IAttributeError):
"""
An attribute is unavailable because it is forbidden (private).
@@ -99,6 +104,7 @@ class IForbiddenAttribute(IForbidden, IAttributeError):
Implemented in :class:`ForbiddenAttribute`.
"""
+
@implementer(IForbiddenAttribute)
class ForbiddenAttribute(Forbidden, AttributeError):
"""
@@ -137,9 +143,9 @@ class ISecurityChecking(Interface):
:param str permission: The permission name.
:param object: The object being accessed according to the permission.
- :keyword interaction: An :class:`IInteraction`, providing access to information
- such as authenticated principals. If it is None, the current
- interaction is used.
+ :keyword interaction: An :class:`IInteraction`, providing access to
+ information such as authenticated principals. If it is None, the
+ current interaction is used.
"""
@@ -257,7 +263,8 @@ class INameBasedChecker(IChecker):
"""
Return the permission used to check attribute access on *name*.
- This permission is used by both :meth:`check` and :meth:`check_getattr`.
+ This permission is used by both :meth:`check` and
+ :meth:`check_getattr`.
"""
def setattr_permission_id(name):
@@ -322,6 +329,7 @@ class NoInteraction(Exception):
"""No interaction started
"""
+
class IInteractionManagement(Interface):
"""
Interaction management API.
@@ -362,6 +370,7 @@ class IInteractionManagement(Interface):
Does nothing if there is no interaction.
"""
+
class IPrincipal(Interface):
"""
Principals are security artifacts that execute actions in a
@@ -417,7 +426,9 @@ class IGroupAwarePrincipal(IPrincipal):
"""
groups = Attribute(
- 'An iterable of :class:`IGroup` objects to which the principal directly belongs')
+ 'An iterable of :class:`IGroup` objects to which the principal'
+ ' directly belongs')
+
class IGroupClosureAwarePrincipal(IGroupAwarePrincipal):
"""
@@ -428,11 +439,13 @@ class IGroupClosureAwarePrincipal(IGroupAwarePrincipal):
allGroups = Attribute(
"An iterable of the full closure of the principal's groups.")
+
class IGroup(IPrincipal):
"""
Group of principals
"""
+
class IMemberGetterGroup(IGroup):
"""
A group that can get its members.
@@ -441,6 +454,7 @@ class IMemberGetterGroup(IGroup):
def getMembers():
"""Return an iterable of the members of the group"""
+
class IMemberAwareGroup(IMemberGetterGroup):
"""
A group that can both set and get its members.
@@ -452,6 +466,7 @@ class IMemberAwareGroup(IMemberGetterGroup):
*value*.
"""
+
class IPermission(Interface):
"""A permission object.
diff --git a/src/zope/security/management.py b/src/zope/security/management.py
index 1acc3d3..2daf0ce 100644
--- a/src/zope/security/management.py
+++ b/src/zope/security/management.py
@@ -52,10 +52,12 @@ moduleProvides(
# ISecurityManagement implementation
#
+
def getSecurityPolicy():
"""Get the system default security policy."""
return _defaultPolicy
+
def setSecurityPolicy(aSecurityPolicy):
"""Set the system default security policy, and return the previous
value.
@@ -78,6 +80,7 @@ def queryInteraction():
"""Return a current interaction, if there is one."""
return getattr(thread_local, 'interaction', None)
+
def getInteraction():
"""Get the current interaction."""
try:
@@ -85,14 +88,16 @@ def getInteraction():
except AttributeError:
raise NoInteraction
+
class ExistingInteraction(ValueError,
- AssertionError, #BBB
- ):
+ AssertionError, # BBB
+ ):
"""
The exception that :func:`newInteraction` will raise if called
during an existing interaction.
"""
+
def newInteraction(*participations):
"""Start a new interaction."""
if queryInteraction() is not None:
@@ -100,6 +105,7 @@ def newInteraction(*participations):
" while another interaction is active.")
thread_local.interaction = getSecurityPolicy()(*participations)
+
def endInteraction():
"""End the current interaction."""
@@ -116,6 +122,7 @@ def endInteraction():
else:
del thread_local.interaction
+
def restoreInteraction():
try:
previous = thread_local.previous_interaction
@@ -127,6 +134,7 @@ def restoreInteraction():
else:
thread_local.interaction = previous
+
def checkPermission(permission, object, interaction=None):
"""Return whether security policy allows permission on object.
@@ -155,9 +163,10 @@ def _clear():
global _defaultPolicy
_defaultPolicy = ParanoidSecurityPolicy
+
try:
from zope.testing.cleanup import addCleanUp
-except ImportError: # pragma: no cover
+except ImportError: # pragma: no cover
pass
else:
addCleanUp(_clear)
diff --git a/src/zope/security/metaconfigure.py b/src/zope/security/metaconfigure.py
index a9ac6ed..ee437da 100644
--- a/src/zope/security/metaconfigure.py
+++ b/src/zope/security/metaconfigure.py
@@ -40,16 +40,18 @@ def dottedName(klass):
return 'None'
return klass.__module__ + '.' + klass.__name__
+
class ProtectionDeclarationException(Exception):
"""Security-protection-specific exceptions."""
pass
+
class ClassDirective(object):
def __init__(self, _context, class_):
- self.__id = dottedName(class_) # this would barf on a module, anyway
+ self.__id = dottedName(class_) # this would barf on a module, anyway
self.__class = class_
- if isinstance(self.__class, ModuleType): #pragma NO COVER
+ if isinstance(self.__class, ModuleType): # pragma: no cover
raise ConfigurationError('Content class attribute must be a class')
self.__context = _context
@@ -198,12 +200,12 @@ def protectModule(module, name, permission):
def _names(attributes, interfaces):
seen = {}
for name in attributes:
- if not name in seen:
+ if name not in seen:
seen[name] = 1
yield name
for interface in interfaces:
for name in interface:
- if not name in seen:
+ if name not in seen:
seen[name] = 1
yield name
diff --git a/src/zope/security/metadirectives.py b/src/zope/security/metadirectives.py
index c0830d6..3e85cfd 100644
--- a/src/zope/security/metadirectives.py
+++ b/src/zope/security/metadirectives.py
@@ -26,13 +26,15 @@ import zope.security.zcml
from zope.security.i18n import ZopeMessageFactory as _
from zope.security.zcml import Permission
+
class IClassDirective(zope.interface.Interface):
"""Make statements about a class"""
class_ = zope.configuration.fields.GlobalObject(
title=_("Class"),
required=True
- )
+ )
+
class IImplementsSubdirective(zope.interface.Interface):
"""Declare that the class given by the content directive's class
@@ -43,7 +45,8 @@ class IImplementsSubdirective(zope.interface.Interface):
title=_("One or more interfaces"),
required=True,
value_type=zope.configuration.fields.GlobalInterface()
- )
+ )
+
class IRequireSubdirective(zope.interface.Interface):
"""Indicate that the a specified list of names or the names in a
@@ -56,7 +59,7 @@ class IRequireSubdirective(zope.interface.Interface):
Specifies the permission by id that will be required to
access or mutate the attributes and methods specified."""),
required=False,
- )
+ )
attributes = zope.configuration.fields.Tokens(
title=_("Attributes and methods"),
@@ -64,7 +67,7 @@ class IRequireSubdirective(zope.interface.Interface):
" that can be accessed."),
required=False,
value_type=zope.configuration.fields.PythonIdentifier(),
- )
+ )
set_attributes = zope.configuration.fields.Tokens(
title=_("Attributes that can be set"),
@@ -72,7 +75,7 @@ class IRequireSubdirective(zope.interface.Interface):
" modified/mutated."),
required=False,
value_type=zope.configuration.fields.PythonIdentifier(),
- )
+ )
interface = zope.configuration.fields.Tokens(
title=_("Interfaces"),
@@ -80,7 +83,7 @@ class IRequireSubdirective(zope.interface.Interface):
" can be accessed."),
required=False,
value_type=zope.configuration.fields.GlobalInterface(),
- )
+ )
set_schema = zope.configuration.fields.Tokens(
title=_("The attributes specified by the schema can be set"),
@@ -88,7 +91,7 @@ class IRequireSubdirective(zope.interface.Interface):
" modified/mutated."),
required=False,
value_type=zope.configuration.fields.GlobalInterface(),
- )
+ )
like_class = zope.configuration.fields.GlobalObject(
title=_("Configure like this class"),
@@ -97,7 +100,8 @@ class IRequireSubdirective(zope.interface.Interface):
same way the specified class' security is. If this argument is
specified, no other argument can be used."""),
required=False,
- )
+ )
+
class IAllowSubdirective(zope.interface.Interface):
"""
@@ -110,13 +114,14 @@ class IAllowSubdirective(zope.interface.Interface):
title=_("Attributes"),
required=False,
value_type=zope.configuration.fields.PythonIdentifier(),
- )
+ )
interface = zope.configuration.fields.Tokens(
title=_("Interface"),
required=False,
value_type=zope.configuration.fields.GlobalInterface(),
- )
+ )
+
class IFactorySubdirective(zope.interface.Interface):
"""Specify the factory used to create this content object"""
@@ -128,21 +133,22 @@ class IFactorySubdirective(zope.interface.Interface):
identification scheme. If not given, defaults to the literal
string given as the content directive's 'class' attribute."""),
required=False,
- )
+ )
title = zope.configuration.fields.MessageID(
title=_("Title"),
description=_("Text suitable for use in the 'add content' menu"
" of a management interface"),
required=False,
- )
+ )
description = zope.configuration.fields.MessageID(
title=_("Description"),
description=_("Longer narrative description of what this"
" factory does"),
required=False,
- )
+ )
+
class IModule(Interface):
"""Group security declarations about a module"""
diff --git a/src/zope/security/permission.py b/src/zope/security/permission.py
index 88ba978..da0dd40 100644
--- a/src/zope/security/permission.py
+++ b/src/zope/security/permission.py
@@ -29,6 +29,7 @@ from zope.security.checker import CheckerPublic
from zope.security.interfaces import IPermission
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public
+
@implementer(IPermission)
class Permission(object):
"""
@@ -40,6 +41,7 @@ class Permission(object):
self.title = title
self.description = description
+
def checkPermission(context, permission_id):
"""
Check whether a given permission object exists in the provided
@@ -50,6 +52,7 @@ def checkPermission(context, permission_id):
if not queryUtility(IPermission, permission_id, context=context):
raise ValueError("Undefined permission ID", permission_id)
+
def allPermissions(context=None):
"""
Get the IDs of all defined permission object utilities.
@@ -58,6 +61,7 @@ def allPermissions(context=None):
if name != zope_Public:
yield name
+
def PermissionsVocabulary(context=None):
"""
A vocabulary of permission IDs.
@@ -69,8 +73,10 @@ def PermissionsVocabulary(context=None):
terms.append(SimpleTerm(permission, name))
return SimpleVocabulary(terms)
+
directlyProvides(PermissionsVocabulary, IVocabularyFactory)
+
def PermissionIdsVocabulary(context=None):
"""
A vocabulary of permission IDs.
@@ -100,4 +106,5 @@ def PermissionIdsVocabulary(context=None):
terms.insert(0, SimpleTerm(CheckerPublic, zope_Public, u'Public'))
return SimpleVocabulary(terms)
+
directlyProvides(PermissionIdsVocabulary, IVocabularyFactory)
diff --git a/src/zope/security/protectclass.py b/src/zope/security/protectclass.py
index 1b93994..ee897cd 100644
--- a/src/zope/security/protectclass.py
+++ b/src/zope/security/protectclass.py
@@ -37,6 +37,7 @@ def protectName(class_, name, permission):
protections = checker.get_permissions
protections[name] = permission
+
def protectSetAttribute(class_, name, permission):
"""Set a permission on a particular name."""
checker = getCheckerForInstancesOf(class_)
@@ -58,6 +59,7 @@ def protectSetAttribute(class_, name, permission):
protections = checker.set_permissions
protections[name] = permission
+
def protectLikeUnto(class_, like_unto):
"""Use the protections from like_unto for the given class."""
diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py
index b64fd0a..1f4281c 100644
--- a/src/zope/security/proxy.py
+++ b/src/zope/security/proxy.py
@@ -22,10 +22,11 @@ import sys
from zope.proxy import PyProxyBase
from zope.security._compat import PURE_PYTHON
from zope.security._compat import _BUILTINS
-from zope.security.interfaces import ForbiddenAttribute
+
def _check_name(meth, wrap_result=True):
name = meth.__name__
+
def _wrapper(self, *args, **kw):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
@@ -36,8 +37,10 @@ def _check_name(meth, wrap_result=True):
return checker.proxy(res)
return functools.update_wrapper(_wrapper, meth)
+
def _check_name_inplace(meth):
name = meth.__name__
+
def _wrapper(self, *args, **kw):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
@@ -47,19 +50,20 @@ def _check_name_inplace(meth):
# The proxy object cannot change; we are modifying in place.
self._wrapped = w_meth(*args, **kw)
return self
- x_name = '__%s__' % name[3:-2]
+ x_name = '__%s__' % name[3:-2]
return ProxyPy(getattr(wrapped, x_name)(*args, **kw), checker)
return functools.update_wrapper(_wrapper, meth)
+
def _fmt_address(obj):
# Try to replicate PyString_FromString("%p", obj), which actually uses
# the platform sprintf(buf, "%p", obj), which we cannot access from Python
# directly (and ctypes seems like overkill).
if sys.platform != 'win32':
return '0x%0x' % id(obj)
- if sys.maxsize < 2**32: # pragma: no cover
+ if sys.maxsize < 2**32: # pragma: no cover
return '0x%08X' % id(obj)
- return '0x%016X' % id(obj) # pragma: no cover
+ return '0x%016X' % id(obj) # pragma: no cover
class ProxyPy(PyProxyBase):
@@ -114,15 +118,16 @@ class ProxyPy(PyProxyBase):
# of this object just like the Python language spec states, letting
# them have precedence over things found in the instance. This
# normally makes us a better proxy implementation. However, the
- # C version of this code in _proxy doesn't take that same care and instead
- # uses the generic object attribute access methods directly on
- # the wrapped object. This is a behaviour difference; so far, it's
- # only been noticed for the __module__ attribute, which checker:Global
- # wants to override but couldn't because this object's type's __module__ would
- # get in the way. That broke pickling, and checker:Global can't return
- # anything more sophisticated than a str (a tuple) because it gets proxied
- # and breaks pickling again. Our solution is to match the C version for this
- # one attribute.
+ # C version of this code in _proxy doesn't take that same care and
+ # instead uses the generic object attribute access methods directly
+ # on the wrapped object. This is a behaviour difference; so far,
+ # it's only been noticed for the __module__ attribute, which
+ # checker:Global wants to override but couldn't because this
+ # object's type's __module__ would get in the way. That broke
+ # pickling, and checker:Global can't return anything more
+ # sophisticated than a str (a tuple) because it gets proxied and
+ # breaks pickling again. Our solution is to match the C version for
+ # this one attribute.
val = getattr(wrapped, name)
else:
val = super(ProxyPy, self).__getattribute__(name)
@@ -146,8 +151,8 @@ class ProxyPy(PyProxyBase):
# explicitly do the same. The consequence is that we lose a
# good stack trace if the object implemented its own methods
# but we're consistent. We would provide a better error
- # message or even subclass of AttributeError, but that's liable to break
- # (doc)tests.
+ # message or even subclass of AttributeError, but that's liable to
+ # break (doc)tests.
wrapped = super(ProxyPy, self).__getattribute__('_wrapped')
checker = super(ProxyPy, self).__getattribute__('_checker')
checker.check_getattr(wrapped, name)
@@ -170,7 +175,7 @@ class ProxyPy(PyProxyBase):
delattr(wrapped, name)
@_check_name
- def __getslice__(self, start, end):
+ def __getslice__(self, start, end): # pragma: no cover PY2
wrapped = object.__getattribute__(self, '_wrapped')
try:
getslice = wrapped.__getslice__
@@ -179,7 +184,7 @@ class ProxyPy(PyProxyBase):
return getslice(start, end)
@_check_name
- def __setslice__(self, start, end, value):
+ def __setslice__(self, start, end, value): # pragma: no cover PY2
wrapped = object.__getattribute__(self, '_wrapped')
try:
setslice = wrapped.__setslice__
@@ -187,10 +192,10 @@ class ProxyPy(PyProxyBase):
return wrapped.__setitem__(slice(start, end), value)
return setslice(start, end, value)
- def __cmp__(self, other):
+ def __cmp__(self, other): # pragma: no cover PY2
# no check
wrapped = super(ProxyPy, self).__getattribute__('_wrapped')
- return cmp(wrapped, other)
+ return cmp(wrapped, other) # noqa: F821 undefined name 'cmp'
def __lt__(self, other):
# no check
@@ -243,7 +248,7 @@ class ProxyPy(PyProxyBase):
else:
return hint()
- def __coerce__(self, other):
+ def __coerce__(self, other): # pragma: no cover PY2
# For some reason _check_name does not work for coerce()
wrapped = super(ProxyPy, self).__getattribute__('_wrapped')
checker = super(ProxyPy, self).__getattribute__('_checker')
@@ -258,10 +263,10 @@ class ProxyPy(PyProxyBase):
# the wrong type of object.
except TypeError:
raise
- except:
+ except: # noqa: E722 do not use bare 'except'
# The C implementation catches all exceptions.
wrapped = super(ProxyPy, self).__getattribute__('_wrapped')
- return '<security proxied %s.%s instance at %s>' %(
+ return '<security proxied %s.%s instance at %s>' % (
wrapped.__class__.__module__, wrapped.__class__.__name__,
_fmt_address(wrapped))
@@ -273,28 +278,29 @@ class ProxyPy(PyProxyBase):
# the wrong type of object.
except TypeError:
raise
- except:
+ except: # noqa: E722 do not use bare 'except'
wrapped = super(ProxyPy, self).__getattribute__('_wrapped')
- return '<security proxied %s.%s instance at %s>' %(
+ return '<security proxied %s.%s instance at %s>' % (
wrapped.__class__.__module__, wrapped.__class__.__name__,
_fmt_address(wrapped))
+
for name in ['__call__',
- #'__repr__',
- #'__str__',
- #'__unicode__', # Unchecked in C proxy
+ # '__repr__',
+ # '__str__',
+ # '__unicode__', # Unchecked in C proxy
'__reduce__',
'__reduce_ex__',
- #'__lt__', # Unchecked in C proxy (rich coparison)
- #'__le__', # Unchecked in C proxy (rich coparison)
- #'__eq__', # Unchecked in C proxy (rich coparison)
- #'__ne__', # Unchecked in C proxy (rich coparison)
- #'__ge__', # Unchecked in C proxy (rich coparison)
- #'__gt__', # Unchecked in C proxy (rich coparison)
- #'__nonzero__', # Unchecked in C proxy (rich coparison)
- #'__bool__', # Unchecked in C proxy (rich coparison)
- #'__hash__', # Unchecked in C proxy (rich coparison)
- #'__cmp__', # Unchecked in C proxy
+ # '__lt__', # Unchecked in C proxy (rich coparison)
+ # '__le__', # Unchecked in C proxy (rich coparison)
+ # '__eq__', # Unchecked in C proxy (rich coparison)
+ # '__ne__', # Unchecked in C proxy (rich coparison)
+ # '__ge__', # Unchecked in C proxy (rich coparison)
+ # '__gt__', # Unchecked in C proxy (rich coparison)
+ # '__nonzero__', # Unchecked in C proxy (rich coparison)
+ # '__bool__', # Unchecked in C proxy (rich coparison)
+ # '__hash__', # Unchecked in C proxy (rich coparison)
+ # '__cmp__', # Unchecked in C proxy
'__getitem__',
'__setitem__',
'__delitem__',
@@ -341,7 +347,7 @@ for name in ['__call__',
'__rand__',
'__rxor__',
'__ror__',
- ]:
+ ]:
meth = getattr(PyProxyBase, name)
setattr(ProxyPy, name, _check_name(meth))
@@ -364,16 +370,18 @@ for name in ['__iadd__',
'__ixor__',
'__ior__',
'__ipow__',
- ]:
+ ]:
meth = getattr(PyProxyBase, name)
setattr(ProxyPy, name, _check_name_inplace(meth))
+
def getCheckerPy(proxy):
return super(ProxyPy, proxy).__getattribute__('_checker')
_builtin_isinstance = sys.modules[_BUILTINS].isinstance
+
def getObjectPy(proxy):
if not _builtin_isinstance(proxy, ProxyPy):
return proxy
@@ -381,10 +389,10 @@ def getObjectPy(proxy):
_c_available = not PURE_PYTHON
-if _c_available:
+if _c_available: # pragma: no cover
try:
from zope.security._proxy import _Proxy
- except (ImportError, AttributeError): # pragma: no cover PyPy / PURE_PYTHON
+ except (ImportError, AttributeError):
_c_available = False
@@ -392,13 +400,14 @@ getChecker = getCheckerPy
getObject = getObjectPy
Proxy = ProxyPy
-if _c_available:
+if _c_available: # pragma: no cover
from zope.security._proxy import getChecker
from zope.security._proxy import getObject
Proxy = _Proxy
removeSecurityProxy = getObject
+
def getTestProxyItems(proxy):
"""Return a sorted sequence of checker names and permissions for testing
"""
diff --git a/src/zope/security/testing.py b/src/zope/security/testing.py
index bd4b889..792813f 100644
--- a/src/zope/security/testing.py
+++ b/src/zope/security/testing.py
@@ -37,6 +37,7 @@ rules = [
]
output_checker = renormalizing.RENormalizing(rules)
+
@interface.implementer(interfaces.IPrincipal)
class Principal(object):
"""
@@ -55,8 +56,10 @@ class Principal(object):
@interface.implementer(interfaces.IParticipation)
class Participation(object):
"""
- A trivial implementation of :class:`zope.security.interfaces.IParticipation`.
+ A trivial implementation of
+ :class:`zope.security.interfaces.IParticipation`.
"""
+
def __init__(self, principal):
self.principal = principal
self.interaction = None
@@ -82,6 +85,7 @@ def addCheckerPublic():
return perm
+
def create_interaction(principal_id, **kw):
"""
Create a new interaction for the given principal ID, make it the
diff --git a/src/zope/security/tests/__init__.py b/src/zope/security/tests/__init__.py
index cab4c90..e8db221 100644
--- a/src/zope/security/tests/__init__.py
+++ b/src/zope/security/tests/__init__.py
@@ -9,7 +9,8 @@ class QuietWatchingChecker(object):
def setUp(self):
from zope.security import checker
self.__old_file = checker.CheckerLoggingMixin._file
- checker.CheckerLoggingMixin._file = io.StringIO() if bytes is not str else io.BytesIO()
+ checker.CheckerLoggingMixin._file = (
+ io.StringIO() if bytes is not str else io.BytesIO())
def tearDown(self):
from zope.security import checker
diff --git a/src/zope/security/tests/exampleclass.py b/src/zope/security/tests/exampleclass.py
index 1d73b4b..385dda0 100644
--- a/src/zope/security/tests/exampleclass.py
+++ b/src/zope/security/tests/exampleclass.py
@@ -15,14 +15,18 @@
"""
from zope.interface import Interface
+
class ExampleClass(object):
pass
+
class IExample(Interface):
pass
+
class IExample2(Interface):
pass
+
class IExampleContainer(Interface):
pass
diff --git a/src/zope/security/tests/module.py b/src/zope/security/tests/module.py
index 5b26ff5..a4f9e73 100644
--- a/src/zope/security/tests/module.py
+++ b/src/zope/security/tests/module.py
@@ -21,23 +21,28 @@ modules, themselves.
from zope.interface import Interface
from zope.schema import Text
-class I(Interface):
+
+class I(Interface): # noqa: E742 ambiguous class definition 'I'
def m1():
- "m1"
+ """m1"""
+
def m2():
- "m2"
+ """m2"""
+
class I2(I):
def m4():
- "m4"
+ """m4"""
+
class I3(Interface):
def m3():
- "m3"
+ """m3"""
+
class I4(Interface):
def m2():
- "m2"
+ """m2"""
class S(Interface):
@@ -45,6 +50,7 @@ class S(Interface):
bar = Text()
baro = Text(readonly=True)
+
class S2(Interface):
foo2 = Text()
bar2 = Text()
diff --git a/src/zope/security/tests/test_adapter.py b/src/zope/security/tests/test_adapter.py
index a3dd541..2d68b0e 100644
--- a/src/zope/security/tests/test_adapter.py
+++ b/src/zope/security/tests/test_adapter.py
@@ -21,6 +21,7 @@ from zope.proxy import getProxiedObject
# pylint:disable=attribute-defined-outside-init,protected-access
+
class Test_assertLocation(unittest.TestCase):
def _callFUT(self, adapter, parent):
@@ -49,6 +50,7 @@ class Test_assertLocation(unittest.TestCase):
def test_w_ILocation_w_parent(self):
parent = object()
+
@implementer(ILocation)
class _Adapter(object):
__parent__ = parent
@@ -73,6 +75,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
__name__ = 'testing'
__module__ = 'zope.security.tests.test_adapter'
_called_with = ()
+
def __call__(self, *args):
self._called_with = args
return self
@@ -88,6 +91,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
def test__call__w_non_ILocation_non_spacesuit(self):
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -97,11 +101,12 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in returned.__dict__.items()
if k != '_called_with'}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_non_ILocation_non_spacesuit_multiple_args(self):
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -112,13 +117,14 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in returned.__dict__.items()
if k != '_called_with'}
self.assertEqual(factory._called_with, (adapter, extra))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_ILocation_w_existing_parent_non_spacesuit(self):
factory = self._makeFactory()
parent = factory.__parent__ = object()
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -131,6 +137,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
factory.__parent__ = None
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -143,6 +150,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
from zope.security.proxy import removeSecurityProxy
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -157,13 +165,14 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with',)}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_non_ILocation_w_spacesuit_multiple_args(self):
from zope.security.proxy import ProxyFactory
from zope.security.proxy import removeSecurityProxy
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -179,15 +188,17 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with',)}
self.assertEqual(factory._called_with, (adapter, extra))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_non_ILocation_multiple_args_extra_spacesuit(self):
from zope.security.proxy import ProxyFactory
from zope.security.proxy import removeSecurityProxy
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
+
class _Extra(object):
pass
adapter = _NotAdapter()
@@ -203,7 +214,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with',)}
self.assertEqual(factory._called_with, (adapter, extra))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_ILocation_w_spacesuit(self):
from zope.security.proxy import getObject
@@ -213,6 +224,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
factory.__parent__ = factory.__name__ = None
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _Adapter(object):
pass
adapter = _Adapter()
@@ -229,7 +241,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
if k not in ('_called_with', '__parent__')}
self.assertEqual(factory._called_with, (adapter,))
self.assertIs(factory.__parent__, adapter)
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_ILocation_w_spacesuit_w_existing_parent(self):
from zope.security.proxy import getObject
@@ -240,6 +252,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
factory.__parent__ = parent = object()
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _Adapter(object):
pass
adapter = _Adapter()
@@ -255,7 +268,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with', '__parent__')}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
class TrustedAdapterFactoryTests(unittest.TestCase):
@@ -271,6 +284,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
class _Factory(object):
__name__ = 'testing'
__module__ = 'zope.security.tests.test_adapter'
+
def __call__(self, *args):
self._called_with = args
return self
@@ -281,6 +295,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
from zope.security.proxy import removeSecurityProxy
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -294,13 +309,14 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with',)}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_non_ILocation_w_spacesuit_multiple_args(self):
from zope.security.proxy import ProxyFactory
from zope.security.proxy import removeSecurityProxy
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -315,15 +331,17 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with',)}
self.assertEqual(factory._called_with, (adapter, extra))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_non_ILocation_multiple_args_extra_spacesuit(self):
from zope.security.proxy import ProxyFactory
from zope.security.proxy import removeSecurityProxy
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
+
class _Extra(object):
pass
adapter = _NotAdapter()
@@ -338,7 +356,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with',)}
self.assertEqual(factory._called_with, (adapter, extra))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_ILocation_w_spacesuit(self):
from zope.security.proxy import ProxyFactory
@@ -347,6 +365,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
factory.__parent__ = factory.__name__ = None
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _Adapter(object):
pass
adapter = _Adapter()
@@ -361,7 +380,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with', '__parent__')}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_ILocation_w_spacesuit_w_existing_parent(self):
from zope.security.proxy import ProxyFactory
@@ -371,6 +390,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
factory.__parent__ = parent = object()
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _Adapter(object):
pass
adapter = _Adapter()
@@ -385,7 +405,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in unwrapped.__dict__.items()
if k not in ('_called_with', '__parent__')}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
class LocatingUntrustedAdapterFactoryTests(unittest.TestCase):
@@ -402,6 +422,7 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase):
__name__ = 'testing'
__module__ = 'zope.security.tests.test_adapter'
_called_with = ()
+
def __call__(self, *args):
self._called_with = args
return self
@@ -417,6 +438,7 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase):
def test__call__w_non_ILocation(self):
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -428,11 +450,12 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in returned.__dict__.items()
if k != '_called_with'}
self.assertEqual(factory._called_with, (adapter,))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_non_ILocation_multiple_args(self):
factory = self._makeFactory()
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -445,13 +468,14 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase):
after = {k: v for k, v in returned.__dict__.items()
if k != '_called_with'}
self.assertEqual(factory._called_with, (adapter, extra))
- self.assertEqual(after, before) # no added attrs
+ self.assertEqual(after, before) # no added attrs
def test__call__w_ILocation_w_existing_parent(self):
factory = self._makeFactory()
parent = factory.__parent__ = object()
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
@@ -464,6 +488,7 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase):
factory.__parent__ = None
directlyProvides(factory, ILocation)
ltaf = self._makeOne(factory)
+
class _NotAdapter(object):
pass
adapter = _NotAdapter()
diff --git a/src/zope/security/tests/test_checker.py b/src/zope/security/tests/test_checker.py
index 3473886..a8b3990 100644
--- a/src/zope/security/tests/test_checker.py
+++ b/src/zope/security/tests/test_checker.py
@@ -33,6 +33,7 @@ class Test_ProxyFactory(unittest.TestCase):
def test_w_already_proxied_no_checker(self):
from zope.security.proxy import Proxy, getChecker
obj = object()
+
def _check(*x):
raise AssertionError("Never called")
proxy = Proxy(obj, _check)
@@ -43,6 +44,7 @@ class Test_ProxyFactory(unittest.TestCase):
def test_w_already_proxied_same_checker(self):
from zope.security.proxy import Proxy, getChecker
obj = object()
+
def _check(*x):
raise AssertionError("Never called")
proxy = Proxy(obj, _check)
@@ -53,9 +55,11 @@ class Test_ProxyFactory(unittest.TestCase):
def test_w_already_proxied_different_checker(self):
from zope.security.proxy import Proxy
obj = object()
+
def _check(*x):
raise AssertionError("Never called")
proxy = Proxy(obj, _check)
+
def _sneaky(*x):
raise AssertionError("Never called")
self.assertRaises(TypeError, self._callFUT, proxy, _sneaky)
@@ -63,6 +67,7 @@ class Test_ProxyFactory(unittest.TestCase):
def test_w_explicit_checker(self):
from zope.security.proxy import getChecker
obj = object()
+
def _check(*x):
raise AssertionError("Never called")
returned = self._callFUT(obj, _check)
@@ -76,7 +81,8 @@ class Test_ProxyFactory(unittest.TestCase):
def test_no_checker_w_dunder(self):
from zope.security.proxy import getChecker, getObject
- _check = object() # don't use a func, due to bound method
+ _check = object() # don't use a func, due to bound method
+
class _WithChecker(object):
__Security_checker__ = _check
obj = _WithChecker()
@@ -90,10 +96,12 @@ class Test_ProxyFactory(unittest.TestCase):
from zope.security.checker import _checkers
from zope.security.checker import _clear
from zope.security.proxy import getChecker, getObject
+
class _Obj(object):
pass
obj = _Obj()
_checker = Checker({})
+
def _check(*args):
return _checker
_checkers[_Obj] = _check
@@ -117,6 +125,7 @@ class Test_canWrite(unittest.TestCase):
def check_getattr(self, obj, name):
if ch_get is not None:
raise ch_get()
+
def check_setattr(self, obj, name):
if ch_set is not None:
raise ch_set()
@@ -196,6 +205,7 @@ class Test_canAccess(unittest.TestCase):
_marker = object()
+
class CheckerTestsBase(QuietWatchingChecker):
# pylint:disable=no-member
@@ -267,6 +277,7 @@ class CheckerTestsBase(QuietWatchingChecker):
def test_check_setattr_w_interaction_allows(self):
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return True
@@ -281,6 +292,7 @@ class CheckerTestsBase(QuietWatchingChecker):
def test_check_setattr_w_interaction_denies(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
@@ -313,6 +325,7 @@ class CheckerTestsBase(QuietWatchingChecker):
def test_check_non_public_w_interaction_allows(self):
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return True
@@ -327,6 +340,7 @@ class CheckerTestsBase(QuietWatchingChecker):
def test_check_non_public_w_interaction_denies(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
@@ -342,6 +356,7 @@ class CheckerTestsBase(QuietWatchingChecker):
def test_proxy_already_proxied(self):
from zope.security.proxy import Proxy, getChecker
obj = object()
+
def _check(*x):
raise AssertionError("Never called")
proxy = Proxy(obj, _check)
@@ -358,7 +373,8 @@ class CheckerTestsBase(QuietWatchingChecker):
def test_proxy_no_checker_w_dunder(self):
from zope.security.proxy import getChecker, getObject
- _check = object() # don't use a func, due to bound method
+ _check = object() # don't use a func, due to bound method
+
class _WithChecker(object):
__Security_checker__ = _check
obj = _WithChecker()
@@ -373,10 +389,12 @@ class CheckerTestsBase(QuietWatchingChecker):
from zope.security.checker import _checkers
from zope.security.checker import _clear
from zope.security.proxy import getChecker, getObject
+
class _Obj(object):
pass
obj = _Obj()
_checker = Checker({})
+
def _check(*args):
return _checker
_checkers[_Obj] = _check
@@ -420,8 +438,8 @@ class CheckerTestsBase(QuietWatchingChecker):
self.assertEqual(proxy // Decimal('1'), Decimal('1'))
self.assertEqual(float(proxy), 1.1)
self.assertEqual(int(proxy), 1)
- if PY2:
- self.assertEqual(long(proxy), 1)
+ if PY2: # pragma: no cover PY2
+ self.assertEqual(long(proxy), 1) # noqa: F821 undefined name
self.assertEqual(proxy ** 2, Decimal('1.21'))
self.assertEqual(1 ** proxy, Decimal('1'))
self.assertEqual(proxy.adjusted(), 0)
@@ -451,7 +469,6 @@ class CheckerTestsBase(QuietWatchingChecker):
self.assertEqual([1], list(proxy))
self.assertEqual([2], list(proxy.values()))
-
def test_iteration_of_btree_items_keys_values(self):
# iteration of BTree.items() is allowed by default.
import BTrees
@@ -486,10 +503,10 @@ class CheckerTestsBase(QuietWatchingChecker):
pass
@implementer(I1)
- class O(object):
+ class Obj(object):
pass
- o = O()
+ o = Obj()
checker = Checker({})
@@ -497,9 +514,9 @@ class CheckerTestsBase(QuietWatchingChecker):
# Since the object itself doesn't have any interfaces,
# the providedBy will return the implementedBy of the class
- l = list(providedBy(proxy))
+ provided_by = list(providedBy(proxy))
- self.assertEqual(l, [I1])
+ self.assertEqual(provided_by, [I1])
def test_iteration_of_interface_providesBy(self):
# Iteration of zope.interface.Provides is allowed by default
@@ -519,10 +536,10 @@ class CheckerTestsBase(QuietWatchingChecker):
pass
@implementer(I1)
- class O(object):
+ class Obj(object):
pass
- o = O()
+ o = Obj()
alsoProvides(o, I2)
checker = Checker({})
@@ -531,9 +548,9 @@ class CheckerTestsBase(QuietWatchingChecker):
# Since the object has its own interfaces, provided
# by will return a zope.interface.Provides object
- l = list(providedBy(proxy))
+ provided_by = list(providedBy(proxy))
- self.assertEqual(l, [I2, I1])
+ self.assertEqual(provided_by, [I2, I1])
def test_iteration_with_length_hint(self):
# PEP 424 implemented officially in Python 3.4 and
@@ -577,19 +594,16 @@ class CheckerTestsBase(QuietWatchingChecker):
# The hint is called when we proxy the root object
i = Iter()
proxy = Proxy(i, _iteratorChecker)
- l = list(proxy)
- self.assertEqual(l, [0, 1, 2])
+ self.assertEqual(list(proxy), [0, 1, 2])
self.assertTrue(i.hint_called, "__length_hint__ should be called")
# The hint is called when we proxy its iterator
i = Iter()
it = iter(i)
proxy = Proxy(it, _iteratorChecker)
- l = list(proxy)
- self.assertEqual(l, [0, 1, 2])
+ self.assertEqual(list(proxy), [0, 1, 2])
self.assertTrue(i.hint_called, "__length_hint__ should be called")
-
def test_iteration_of_itertools_groupby(self):
# itertools.groupby is a custom iterator type.
# The groups it returns are also custom.
@@ -630,6 +644,7 @@ class TestChecker(CheckerTestsBase, unittest.TestCase):
def _getTargetClass(self):
return sec_checker.Checker
+
@unittest.skipIf(sec_checker.Checker is sec_checker.WatchingChecker,
"WatchingChecker is the default")
class TestWatchingChecker(TestChecker):
@@ -637,6 +652,7 @@ class TestWatchingChecker(TestChecker):
def _getTargetClass(self):
return sec_checker.WatchingChecker
+
class TestTracebackSupplement(unittest.TestCase):
def _getTargetClass(self):
@@ -654,12 +670,12 @@ class TestTracebackSupplement(unittest.TestCase):
((), 'tuple'),
([], 'list'),
({}, 'dict'),
- ]:
+ ]:
tbs = self._makeOne(val)
self.assertEqual(tbs.getInfo().splitlines(),
[' - class: %s.%s' % (_BUILTINS, typ),
' - type: %s.%s' % (_BUILTINS, typ),
- ])
+ ])
def test_getInfo_newstyle_instance(self):
class C(object):
@@ -668,7 +684,7 @@ class TestTracebackSupplement(unittest.TestCase):
self.assertEqual(tbs.getInfo().splitlines(),
[' - class: %s.C' % self.__class__.__module__,
' - type: %s.C' % self.__class__.__module__,
- ])
+ ])
def test_getInfo_classic_instance(self):
class C:
@@ -678,7 +694,9 @@ class TestTracebackSupplement(unittest.TestCase):
lines = tbs.getInfo().splitlines()
self.assertEqual(lines[0],
' - class: %s.C' % self.__class__.__module__)
- kind = '__builtin__.instance' if PY2 else '%s.C' % self.__class__.__module__
+ kind = ('__builtin__.instance'
+ if PY2
+ else '%s.C' % self.__class__.__module__)
self.assertEqual(lines[1],
' - type: ' + kind)
@@ -763,6 +781,7 @@ class Test_InterfaceChecker(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.checker import CheckerPublic
+
class IFoo(Interface):
bar = Attribute('Bar')
checker = self._callFUT(IFoo)
@@ -772,6 +791,7 @@ class Test_InterfaceChecker(unittest.TestCase):
def test_simple_iface_w_explicit_permission(self):
from zope.interface import Attribute
from zope.interface import Interface
+
class IFoo(Interface):
bar = Attribute('Bar')
other_perm = object()
@@ -782,6 +802,7 @@ class Test_InterfaceChecker(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.checker import CheckerPublic
+
class IFoo(Interface):
bar = Attribute('Bar')
other_perm = object()
@@ -794,8 +815,10 @@ class Test_InterfaceChecker(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.checker import CheckerPublic
+
class IFoo(Interface):
bar = Attribute('Bar')
+
class IBar(IFoo):
baz = Attribute('Baz')
checker = self._callFUT(IBar)
@@ -807,6 +830,7 @@ class Test_InterfaceChecker(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.checker import DuplicationError
+
class IFoo(Interface):
bar = Attribute('Bar')
bam = Attribute('Bam')
@@ -839,6 +863,7 @@ class Test_MultiChecker(unittest.TestCase):
def test_w_spec_as_iface(self):
from zope.interface import Attribute
from zope.interface import Interface
+
class IFoo(Interface):
bar = Attribute('Bar')
other_perm = object()
@@ -850,6 +875,7 @@ class Test_MultiChecker(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.checker import CheckerPublic
+
class IFoo(Interface):
bar = Attribute('Bar')
other_perm = object()
@@ -865,6 +891,7 @@ class Test_MultiChecker(unittest.TestCase):
from zope.interface import Interface
from zope.security.checker import CheckerPublic
from zope.security.checker import DuplicationError
+
class IFoo(Interface):
bar = Attribute('Bar')
other_perm = object()
@@ -877,7 +904,7 @@ class Test_MultiChecker(unittest.TestCase):
other_perm = object()
spec = {'foo': CheckerPublic,
'bar': other_perm,
- }
+ }
checker = self._callFUT([spec])
self.assertIs(checker.permission_id('foo'), CheckerPublic)
self.assertIs(checker.permission_id('bar'), other_perm)
@@ -895,7 +922,6 @@ class Test_MultiChecker(unittest.TestCase):
[(('foo', 'bar'), CheckerPublic), spec])
-
class _SelectCheckerBase(object):
# pylint:disable=no-member
@@ -927,12 +953,13 @@ class _SelectCheckerBase(object):
datetime.date.today(),
datetime.datetime.now().time(),
datetime.tzinfo(),
- ]:
+ ]:
self.assertIsNone(self._callFUT(obj))
def test_w_checker_inst(self):
from zope.security.checker import Checker
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = _checkers[Foo] = Checker({})
@@ -941,9 +968,11 @@ class _SelectCheckerBase(object):
def test_w_factory_returning_checker(self):
from zope.security.checker import Checker
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = Checker({})
+
def _factory(obj):
return checker
_checkers[Foo] = _factory
@@ -952,8 +981,10 @@ class _SelectCheckerBase(object):
def test_w_factory_returning_NoProxy(self):
from zope.security.checker import NoProxy
from zope.security.checker import _checkers
+
class Foo(object):
pass
+
def _factory(obj):
return NoProxy
_checkers[Foo] = _factory
@@ -961,8 +992,10 @@ class _SelectCheckerBase(object):
def test_w_factory_returning_None(self):
from zope.security.checker import _checkers
+
class Foo(object):
pass
+
def _factory(obj):
pass
_checkers[Foo] = _factory
@@ -971,11 +1004,14 @@ class _SelectCheckerBase(object):
def test_w_factory_factory(self):
from zope.security.checker import Checker
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = Checker({})
+
def _factory(obj):
return checker
+
def _factory_factory(obj):
return _factory
_checkers[Foo] = _factory_factory
@@ -983,16 +1019,17 @@ class _SelectCheckerBase(object):
def test_itertools_checkers(self):
from zope.security.checker import _iteratorChecker
- import sys
import itertools
- pred = lambda x: x
+
+ def pred(x):
+ return x
iterable = (1, 2, 3)
pred_iterable = (pred, iterable)
missing_in_py3 = {'ifilter', 'ifilterfalse', 'imap',
'izip', 'izip_longest'}
missing_in_py2 = {'zip_longest', 'accumulate', 'compress',
'combinations', 'combinations_with_replacement'}
- missing = missing_in_py3 if sys.version_info[0] >= 3 else missing_in_py2
+ missing = missing_in_py3 if PY3 else missing_in_py2
for func, args in (
('count', ()),
('cycle', ((),)),
@@ -1037,12 +1074,11 @@ class Test_selectCheckerPy(_SelectCheckerBase, unittest.TestCase):
return selectCheckerPy(obj)
-
@unittest.skipIf(sec_checker.selectChecker is sec_checker.selectCheckerPy,
"Pure Python")
class Test_selectChecker(_SelectCheckerBase, unittest.TestCase):
- def _callFUT(self, obj):
+ def _callFUT(self, obj): # pragma: no cover
from zope.security.checker import selectChecker
return selectChecker(obj)
@@ -1068,6 +1104,7 @@ class Test_getCheckerForInstancesOf(unittest.TestCase):
def test_hit(self):
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = _checkers[Foo] = object()
@@ -1097,12 +1134,13 @@ class Test_defineChecker(unittest.TestCase):
u'text',
b'binary',
True,
- ]:
+ ]:
self.assertRaises(TypeError, self._callFUT, obj, checker)
def test_w_duplicate(self):
from zope.exceptions import DuplicationError
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker1, checker2 = object(), object()
@@ -1112,6 +1150,7 @@ class Test_defineChecker(unittest.TestCase):
def test_w_newstyle_class(self):
from zope.security.checker import _checkers
checker = object()
+
class Foo(object):
pass
self._callFUT(Foo, checker)
@@ -1127,6 +1166,7 @@ class Test_defineChecker(unittest.TestCase):
def test_w_oldstyle_class(self):
from zope.security.checker import _checkers
checker = object()
+
class Foo:
pass
self._callFUT(Foo, checker)
@@ -1154,6 +1194,7 @@ class Test_undefineChecker(unittest.TestCase):
def test_hit(self):
from zope.security.checker import _checkers
+
class Foo(object):
pass
_checkers[Foo] = object()
@@ -1196,40 +1237,43 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_lhs_ok_rhs_not_called(self):
from zope.security.checker import CheckerPublic
from zope.security.checker import Checker
+
class _NeverCalled(Checker):
- def check(self, object, name): # pylint:disable=redefined-builtin
+ def check(self, object, name): # pylint:disable=redefined-builtin
raise AssertionError("Never called")
lhs = self._makeOther({'name': CheckerPublic})
rhs = _NeverCalled({})
combined = self._makeOne(lhs, rhs)
- combined.check(object(), 'name') # no raise
+ combined.check(object(), 'name') # no raise
def test_check_lhs_unauth_rhs_ok(self):
from zope.security.checker import CheckerPublic
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther({'name': 'view'}) # unauth
+ lhs = self._makeOther({'name': 'view'}) # unauth
rhs = self._makeOther({'name': CheckerPublic})
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
try:
- combined.check(object(), 'name') #no raise
+ combined.check(object(), 'name') # no raise
finally:
del thread_local.interaction
def test_check_lhs_unauth_rhs_forbidden(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther({'name': 'view'}) # unauth
- rhs = self._makeOther() # forbidden
+ lhs = self._makeOther({'name': 'view'}) # unauth
+ rhs = self._makeOther() # forbidden
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
try:
@@ -1241,11 +1285,12 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_lhs_unauth_rhs_unauth(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther({'name': 'view'}) # unauth
+ lhs = self._makeOther({'name': 'view'}) # unauth
rhs = self._makeOther({'name': 'inspect'})
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
@@ -1258,16 +1303,16 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_lhs_forbidden_rhs_ok(self):
from zope.security.checker import CheckerPublic
- lhs = self._makeOther() # forbidden
+ lhs = self._makeOther() # forbidden
rhs = self._makeOther({'name': CheckerPublic})
combined = self._makeOne(lhs, rhs)
- combined.check(object(), 'name') # no raise
+ combined.check(object(), 'name') # no raise
def test_check_lhs_forbidden_rhs_forbidden(self):
from zope.security.interfaces import Forbidden
- lhs = self._makeOther() # forbidden
- rhs = self._makeOther() # forbidden
+ lhs = self._makeOther() # forbidden
+ rhs = self._makeOther() # forbidden
combined = self._makeOne(lhs, rhs)
self.assertRaises(Forbidden,
combined.check, object(), 'name')
@@ -1275,11 +1320,12 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_lhs_forbidden_rhs_unauth(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther() # Forbidden
+ lhs = self._makeOther() # Forbidden
rhs = self._makeOther({'name': 'inspect'})
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
@@ -1292,40 +1338,43 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_setattr_lhs_ok_rhs_not_called(self):
from zope.security.checker import CheckerPublic
from zope.security.checker import Checker
+
class _NeverCalled(Checker):
- def check_setattr(self, object, name): # pylint:disable=redefined-builtin
+ def check_setattr(self, object, name):
raise AssertionError("Never called")
lhs = self._makeOther(set_permissions={'name': CheckerPublic})
rhs = _NeverCalled({})
combined = self._makeOne(lhs, rhs)
- combined.check_setattr(object(), 'name') # no raise
+ combined.check_setattr(object(), 'name') # no raise
def test_check_setattr_lhs_unauth_rhs_ok(self):
from zope.security.checker import CheckerPublic
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther(set_permissions={'name': 'update'}) # unauth
+ lhs = self._makeOther(set_permissions={'name': 'update'}) # unauth
rhs = self._makeOther(set_permissions={'name': CheckerPublic})
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
try:
- combined.check_setattr(object(), 'name') # no raise
+ combined.check_setattr(object(), 'name') # no raise
finally:
del thread_local.interaction
def test_check_setattr_lhs_unauth_rhs_forbidden(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth
- rhs = self._makeOther() # forbidden
+ lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth
+ rhs = self._makeOther() # forbidden
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
try:
@@ -1337,12 +1386,13 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_setattr_lhs_unauth_rhs_unauth(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth
- rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth
+ lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth
+ rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
try:
@@ -1354,16 +1404,16 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_setattr_lhs_forbidden_rhs_ok(self):
from zope.security.checker import CheckerPublic
- lhs = self._makeOther() # forbidden
+ lhs = self._makeOther() # forbidden
rhs = self._makeOther(set_permissions={'name': CheckerPublic})
combined = self._makeOne(lhs, rhs)
- combined.check_setattr(object(), 'name') # no raise
+ combined.check_setattr(object(), 'name') # no raise
def test_check_setattr_lhs_forbidden_rhs_forbidden(self):
from zope.security.interfaces import Forbidden
- lhs = self._makeOther() # forbidden
- rhs = self._makeOther() # forbidden
+ lhs = self._makeOther() # forbidden
+ rhs = self._makeOther() # forbidden
combined = self._makeOne(lhs, rhs)
self.assertRaises(Forbidden,
combined.check_setattr, object(), 'name')
@@ -1371,12 +1421,13 @@ class TestCombinedChecker(QuietWatchingChecker,
def test_check_setattr_lhs_forbidden_rhs_unauth(self):
from zope.security.interfaces import Unauthorized
from zope.security._definitions import thread_local
+
class _Interaction(object):
def checkPermission(self, obj, perm):
return False
- lhs = self._makeOther() # forbidden
- rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth
+ lhs = self._makeOther() # forbidden
+ rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth
combined = self._makeOne(lhs, rhs)
thread_local.interaction = _Interaction()
try:
@@ -1385,13 +1436,16 @@ class TestCombinedChecker(QuietWatchingChecker,
finally:
del thread_local.interaction
-@unittest.skipIf(sec_checker.WatchingCombinedChecker is sec_checker.CombinedChecker,
- "WatchingCombinedChecker is the default")
+
+@unittest.skipIf(
+ sec_checker.WatchingCombinedChecker is sec_checker.CombinedChecker,
+ "WatchingCombinedChecker is the default")
class TestWatchingCombinedChecker(TestCombinedChecker):
def _getTargetClass(self):
return sec_checker.WatchingCombinedChecker
+
class TestCheckerLoggingMixin(unittest.TestCase):
def _getTargetClass(self):
@@ -1403,10 +1457,12 @@ class TestCheckerLoggingMixin(unittest.TestCase):
def __init__(self, raising, stream):
self._file = stream
self._raising = raising
+
def check(self, obj, name):
if self._raising:
raise self._raising
check_getattr = check_setattr = check
+
class _Derived(self._getTargetClass(), _Checker):
pass
return _Derived(raising, self._makeStream())
@@ -1572,12 +1628,14 @@ class Test__instanceChecker(unittest.TestCase):
def test_miss(self):
from zope.security.checker import _defaultChecker
+
class Foo(object):
pass
self.assertIs(self._callFUT(Foo()), _defaultChecker)
def test_hit(self):
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = _checkers[Foo] = object()
@@ -1609,8 +1667,6 @@ class Test_moduleChecker(unittest.TestCase):
self.assertIs(self._callFUT(verify), checker)
-
-
# Pre-geddon tests start here
class TestSecurityPolicy(QuietWatchingChecker,
@@ -1645,6 +1701,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
def _makeSecurityPolicy(self):
from zope.interface import implementer
from zope.security.interfaces import ISecurityPolicy
+
@implementer(ISecurityPolicy)
class SecurityPolicy(object):
def checkPermission(self, permission, _object):
@@ -1655,6 +1712,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
from zope.security.checker import defineChecker
from zope.security.checker import NamesChecker
old_type = self._get_old_class_type()
+
class ClassicClass:
__metaclass__ = old_type
self.assertIsInstance(ClassicClass, old_type)
@@ -1664,6 +1722,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
def test_defineChecker_newstyle_class(self):
from zope.security.checker import defineChecker
from zope.security.checker import NamesChecker
+
class NewStyleClass(object):
pass
self.assertIsInstance(NewStyleClass, type)
@@ -1684,16 +1743,21 @@ class TestSecurityPolicy(QuietWatchingChecker,
def _makeClasses(self):
old_type = self._get_old_class_type()
+
class OldInst:
a = 1
+
def b(self):
raise AssertionError("Never called")
c = 2
+
def gete(self):
raise AssertionError("Never called")
e = property(gete)
+
def __getitem__(self, x):
raise AssertionError("Never called")
+
def __setitem__(self, x, v):
raise AssertionError("Never called")
@@ -1704,6 +1768,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
# __metaclass__ = type
def gete(self):
raise AssertionError("Never called")
+
def sete(self, v):
raise AssertionError("Never called")
e = property(gete, sete)
@@ -1851,10 +1916,11 @@ class TestSecurityPolicy(QuietWatchingChecker,
self.assertEqual(next(proxy), 1)
def testLayeredProxies(self):
- #Test that a Proxy will not be re-proxied.
+ # Test that a Proxy will not be re-proxied.
from zope.security.proxy import Proxy, getObject
from zope.security.checker import Checker
from zope.security.checker import NamesChecker
+
class Base:
__Security_checker__ = NamesChecker(['__Security_checker__'])
base = Base()
@@ -1870,7 +1936,6 @@ class TestSecurityPolicy(QuietWatchingChecker,
self.assertIs(proxy2, proxy1)
self.assertIs(getObject(proxy2), base)
-
def testMultiChecker(self):
from zope.interface import Interface
@@ -1925,6 +1990,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
def testAlwaysAvailable(self):
from zope.security.checker import NamesChecker
checker = NamesChecker(())
+
class C(object):
pass
self.assertEqual(checker.check(C, '__hash__'), None)
@@ -1965,6 +2031,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
from zope.security.checker import ProxyFactory
from zope.security.proxy import getChecker
from zope.security.proxy import Proxy
+
class SomeClass(object):
pass
checker = NamesChecker()
@@ -1997,6 +2064,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
from zope.security.checker import defineChecker
from zope.security.checker import NamesChecker
from zope.security.checker import undefineChecker
+
class SomeClass(object):
pass
obj = SomeClass()
@@ -2012,6 +2080,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
def test_ProxyFactory_using_proxy(self):
from zope.security.checker import ProxyFactory
from zope.security.checker import NamesChecker
+
class SomeClass(object):
pass
obj = SomeClass()
@@ -2045,6 +2114,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
from zope.security.checker import canAccess
from zope.security.checker import canWrite
from zope.security.checker import defineChecker
+
class SomeClass(object):
pass
obj = SomeClass()
@@ -2057,24 +2127,24 @@ class TestSecurityPolicy(QuietWatchingChecker,
# For these tests, the SecurityPolicy defined at the top of this file
# is in place. It is a stub. Normally, the security policy would
# have knowledge of interactions and participants, and would determine
- # on the basis of the particpants and the object if a certain permission
- # were authorized. This stub simply says that the 'test_allowed'
- # permission is authorized and nothing else is, for any object you pass
- # it.
+ # on the basis of the participants and the object if a certain
+ # permission were authorized. This stub simply says that the
+ # 'test_allowed' permission is authorized and nothing else is, for any
+ # object you pass it.
# Therefore, according to the checker created here, the current
# 'interaction' (as stubbed out in the security policy) will be allowed
# to access and write foo, and access bar. The interaction is
# unauthorized for accessing baz and writing bar. Any other access or
- # write is not merely unauthorized but forbidden--including write access
- # for baz.
+ # write is not merely unauthorized but forbidden--including write
+ # access for baz.
checker = Checker(
- {'foo':'test_allowed', # these are the read settings
- 'bar':'test_allowed',
- 'baz':'you_will_not_have_this_permission'},
- {'foo':'test_allowed', # these are the write settings
- 'bar':'you_will_not_have_this_permission',
- 'bing':'you_will_not_have_this_permission'})
+ {'foo': 'test_allowed', # these are the read settings
+ 'bar': 'test_allowed',
+ 'baz': 'you_will_not_have_this_permission'},
+ {'foo': 'test_allowed', # these are the write settings
+ 'bar': 'you_will_not_have_this_permission',
+ 'bing': 'you_will_not_have_this_permission'})
defineChecker(SomeClass, checker)
# so, our hapless interaction may write and access foo...
@@ -2110,6 +2180,7 @@ class TestSecurityPolicy(QuietWatchingChecker,
self.assertTrue(not canWrite(obj, 'bing'))
self.assertRaises(Forbidden, canAccess, obj, 'bing')
+
class TestCheckerPublic(unittest.TestCase):
def test_that_pickling_CheckerPublic_retains_identity(self):
@@ -2154,14 +2225,17 @@ class TestMixinDecoratedChecker(unittest.TestCase):
def _makeSecurityPolicy(self):
from zope.interface import implementer
from zope.security.interfaces import ISecurityPolicy
+
@implementer(ISecurityPolicy)
class RecordedSecurityPolicy(object):
def __init__(self):
self._checked = []
self.permissions = {}
+
def checkPermission(self, permission, _obj):
self._checked.append(permission)
return self.permissions.get(permission, True)
+
def checkChecked(self, checked):
res = self._checked == checked
self._checked = []
@@ -2209,6 +2283,7 @@ class TestMixinDecoratedChecker(unittest.TestCase):
from zope.security.checker import Checker
return Checker(self.decorationGetMap, self.decorationSetMap)
+
class TestCombinedCheckerMixin(QuietWatchingChecker,
TestMixinDecoratedChecker,
unittest.TestCase):
@@ -2235,7 +2310,7 @@ class TestCombinedCheckerMixin(QuietWatchingChecker,
self.assertTrue(
self.interaction.checkChecked(['dc_get_permission',
'get_permission'])
- )
+ )
# This should raise Unauthorized instead of ForbiddenAttribute, since
# access can be granted if you e.g. login with different credentials.
@@ -2263,6 +2338,7 @@ class TestBasicTypes(unittest.TestCase):
def test___setitem__(self):
from zope.security.checker import BasicTypes
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = object()
@@ -2273,6 +2349,7 @@ class TestBasicTypes(unittest.TestCase):
def test___delitem__(self):
from zope.security.checker import BasicTypes
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = object()
@@ -2288,6 +2365,7 @@ class TestBasicTypes(unittest.TestCase):
def test_update(self):
from zope.security.checker import BasicTypes
from zope.security.checker import _checkers
+
class Foo(object):
pass
checker = object()
@@ -2295,14 +2373,15 @@ class TestBasicTypes(unittest.TestCase):
self.assertIs(BasicTypes[Foo], checker)
self.assertIs(_checkers[Foo], checker)
-
def test(self):
from zope.security.checker import BasicTypes
from zope.security.checker import NoProxy
from zope.security.checker import _checkers
from zope.security.checker import _clear
+
class MyType(object):
pass
+
class MyType2(object):
pass
@@ -2342,10 +2421,10 @@ class TestBasicTypes(unittest.TestCase):
self.assertIn(str, keys)
try:
unicode
- except NameError: # pragma: no cover Py3k
+ except NameError:
pass
- else: # pragma: no cover Python2
- self.assertIn(unicode, keys)
+ else: # pragma: no cover PY2
+ self.assertIn(unicode, keys) # noqa: F821 undefined name 'unicode'
self.assertIn(object, keys)
# ...
@@ -2353,5 +2432,6 @@ class TestBasicTypes(unittest.TestCase):
# unwanted deletions.
self.assertRaises(NotImplementedError, BasicTypes.clear)
+
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
diff --git a/src/zope/security/tests/test_decorator.py b/src/zope/security/tests/test_decorator.py
index 650380d..285f7ef 100644
--- a/src/zope/security/tests/test_decorator.py
+++ b/src/zope/security/tests/test_decorator.py
@@ -64,27 +64,27 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker,
class Foo(object):
a = 'a'
- fooChecker = NamesChecker(['a']) # a is public
+ fooChecker = NamesChecker(['a']) # a is public
defineChecker(Foo, fooChecker)
foo = Foo()
- fooChecker.check(foo, 'a') # no raise
+ fooChecker.check(foo, 'a') # no raise
self.assertRaises(ForbiddenAttribute,
fooChecker.check, foo, 'b')
class Wrapper(ProxyBase):
b = 'b'
__Security_checker__ = self._makeOne()
- wrapperChecker = NamesChecker(['b']) # b is public
+ wrapperChecker = NamesChecker(['b']) # b is public
defineChecker(Wrapper, wrapperChecker)
wrapper = Wrapper(foo)
self.assertRaises(ForbiddenAttribute,
wrapperChecker.check, foo, 'a')
- wrapperChecker.check(foo, 'b') # no raise
+ wrapperChecker.check(foo, 'b') # no raise
checker = wrapper.__Security_checker__
self.assertTrue(isinstance(checker, CombinedChecker))
- checker.check(wrapper, 'a') # no raise
- checker.check(wrapper, 'b') # no raise
+ checker.check(wrapper, 'a') # no raise
+ checker.check(wrapper, 'b') # no raise
def test_only_wrapper_has_checker(self):
from zope.proxy import ProxyBase
@@ -100,7 +100,7 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker,
class Wrapper(ProxyBase):
b = 'b'
__Security_checker__ = self._makeOne()
- wrapperChecker = NamesChecker(['b']) # b is public
+ wrapperChecker = NamesChecker(['b']) # b is public
defineChecker(Wrapper, wrapperChecker)
wrapper = Wrapper(foo)
self.assertTrue(wrapper.__Security_checker__ is wrapperChecker)
@@ -113,7 +113,7 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker,
class Foo(object):
a = 'a'
- fooChecker = NamesChecker(['a']) # a is public
+ fooChecker = NamesChecker(['a']) # a is public
defineChecker(Foo, fooChecker)
foo = Foo()
@@ -124,7 +124,6 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker,
wrapper = Wrapper(foo)
self.assertTrue(wrapper.__Security_checker__ is fooChecker)
-
def test_both_wrapper_and_object_have_checkers_security_proxied(self):
from zope.proxy import ProxyBase
from zope.security.checker import CombinedChecker
@@ -134,7 +133,7 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker,
class Foo(object):
a = 'a'
- fooChecker = NamesChecker(['a']) # a is public
+ fooChecker = NamesChecker(['a']) # a is public
defineChecker(Foo, fooChecker)
foo = Foo()
f_sec = ProxyFactory(foo)
@@ -142,14 +141,14 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker,
class Wrapper(ProxyBase):
b = 'b'
__Security_checker__ = self._makeOne()
- wrapperChecker = NamesChecker(['b']) # b is public
+ wrapperChecker = NamesChecker(['b']) # b is public
defineChecker(Wrapper, wrapperChecker)
w_sec = Wrapper(f_sec)
checker = w_sec.__Security_checker__
self.assertTrue(isinstance(checker, CombinedChecker))
- checker.check(w_sec, 'a') # no raise
- checker.check(w_sec, 'b') # no raise
+ checker.check(w_sec, 'a') # no raise
+ checker.check(w_sec, 'b') # no raise
def test_cannot_overwrite(self):
from zope.proxy import ProxyBase
diff --git a/src/zope/security/tests/test_location.py b/src/zope/security/tests/test_location.py
index bc5fb03..194fc52 100644
--- a/src/zope/security/tests/test_location.py
+++ b/src/zope/security/tests/test_location.py
@@ -26,6 +26,7 @@ class LocationSecurityProxyTests(QuietWatchingChecker,
from zope.security.checker import defineChecker
from zope.security.checker import NamesChecker
from zope.security.proxy import ProxyFactory
+
class Unlocated(object):
a = 'a'
unlocated = Unlocated()
diff --git a/src/zope/security/tests/test_management.py b/src/zope/security/tests/test_management.py
index 93ce19d..78dd78d 100644
--- a/src/zope/security/tests/test_management.py
+++ b/src/zope/security/tests/test_management.py
@@ -83,7 +83,7 @@ class Test(unittest.TestCase):
from zope.security.management import newInteraction
from zope.security.management import queryInteraction
newInteraction()
- interaction = queryInteraction()
+ queryInteraction()
endInteraction()
self.assertEqual(queryInteraction(), None)
endInteraction()
@@ -106,7 +106,7 @@ class Test(unittest.TestCase):
from zope.security.management import restoreInteraction
newInteraction()
self.assertTrue(queryInteraction() is not None)
- restoreInteraction() # restore to no interaction
+ restoreInteraction() # restore to no interaction
self.assertTrue(queryInteraction() is None)
def test_restoreInteraction_after_neither(self):
@@ -170,7 +170,6 @@ class Test(unittest.TestCase):
self.assertEqual(checkPermission(None, obj), True)
self.assertEqual(checkPermission(CheckerPublic, obj), True)
-
def test_system_user(self):
from zope.interface.verify import verifyObject
from zope.security.interfaces import IPrincipal
diff --git a/src/zope/security/tests/test_metaconfigure.py b/src/zope/security/tests/test_metaconfigure.py
index 20477c0..c8631e9 100644
--- a/src/zope/security/tests/test_metaconfigure.py
+++ b/src/zope/security/tests/test_metaconfigure.py
@@ -16,6 +16,7 @@
import unittest
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public
+
class Test_dottedName(unittest.TestCase):
def _callFUT(self, obj):
@@ -40,7 +41,7 @@ class ClassDirectiveTests(unittest.TestCase):
def _makeOne(self, _context, class_):
return self._getTargetClass()(_context, class_)
- #def test_ctor_non_class(self): TODO needs better guard in __init__
+ # def test_ctor_non_class(self): TODO needs better guard in __init__
def test_implements_empty(self):
context = DummyZCMLContext()
@@ -52,6 +53,7 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.component.interface import provideInterface
from zope.interface import Interface
from zope.interface import classImplements
+
class IFoo(Interface):
pass
context = DummyZCMLContext()
@@ -59,7 +61,7 @@ class ClassDirectiveTests(unittest.TestCase):
directive.implements(context, [IFoo])
self.assertEqual(len(context._actions), 2)
self.assertEqual(context._actions[0]['discriminator'][:2],
- ('ContentDirective', Foo, )) #3rd is object()
+ ('ContentDirective', Foo, )) # 3rd is object()
self.assertTrue(context._actions[0]['callable'] is classImplements)
self.assertEqual(context._actions[0]['args'], (Foo, IFoo))
self.assertTrue(context._actions[1]['discriminator'] is None)
@@ -71,8 +73,10 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.component.interface import provideInterface
from zope.interface import Interface
from zope.interface import classImplements
+
class IFoo(Interface):
pass
+
class IBar(Interface):
pass
context = DummyZCMLContext()
@@ -80,7 +84,7 @@ class ClassDirectiveTests(unittest.TestCase):
directive.implements(context, [IFoo, IBar])
self.assertEqual(len(context._actions), 4)
self.assertEqual(context._actions[0]['discriminator'][:2],
- ('ContentDirective', Foo, )) #3rd is object()
+ ('ContentDirective', Foo, )) # 3rd is object()
self.assertTrue(context._actions[0]['callable'] is classImplements)
self.assertEqual(context._actions[0]['args'], (Foo, IFoo))
self.assertTrue(context._actions[1]['discriminator'] is None)
@@ -88,7 +92,7 @@ class ClassDirectiveTests(unittest.TestCase):
self.assertEqual(context._actions[1]['args'],
('zope.security.tests.test_metaconfigure.IFoo', IFoo))
self.assertEqual(context._actions[2]['discriminator'][:2],
- ('ContentDirective', Foo, )) #3rd is object()
+ ('ContentDirective', Foo, )) # 3rd is object()
self.assertTrue(context._actions[2]['callable'] is classImplements)
self.assertEqual(context._actions[2]['args'], (Foo, IBar))
self.assertTrue(context._actions[3]['discriminator'] is None)
@@ -98,6 +102,7 @@ class ClassDirectiveTests(unittest.TestCase):
def test_require_only_like_class(self):
from zope.security.protectclass import protectLikeUnto
+
class Bar(object):
pass
context = DummyZCMLContext()
@@ -105,7 +110,7 @@ class ClassDirectiveTests(unittest.TestCase):
directive.require(context, like_class=Bar)
self.assertEqual(len(context._actions), 1)
self.assertEqual(context._actions[0]['discriminator'][:2],
- ('mimic', Foo, )) #3rd is object()
+ ('mimic', Foo, )) # 3rd is object()
self.assertTrue(context._actions[0]['callable'] is protectLikeUnto)
self.assertEqual(context._actions[0]['args'], (Foo, Bar))
@@ -120,14 +125,15 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.configuration.exceptions import ConfigurationError
context = DummyZCMLContext()
directive = self._makeOne(context, Foo)
- self.assertRaises(ConfigurationError,
- directive.require, context, attributes=('foo', 'bar'))
+ with self.assertRaises(ConfigurationError):
+ directive.require(context, attributes=('foo', 'bar'))
def test_require_w_single_interface(self):
from zope.component.interface import provideInterface
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.protectclass import protectName
+
class IFoo(Interface):
bar = Attribute("Bar")
baz = Attribute("Baz")
@@ -153,13 +159,16 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.protectclass import protectName
+
class IFoo(Interface):
bar = Attribute("Bar")
+
class IBar(Interface):
baz = Attribute("Baz")
context = DummyZCMLContext()
directive = self._makeOne(context, Foo)
- directive.require(context, permission='testing', interface=[IFoo, IBar])
+ directive.require(context, permission='testing',
+ interface=[IFoo, IBar])
self.assertEqual(len(context._actions), 4)
self.assertEqual(context._actions[0]['discriminator'],
('protectName', Foo, 'bar'))
@@ -215,6 +224,7 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.schema import Field
from zope.interface import Interface
from zope.security.protectclass import protectSetAttribute
+
class IFoo(Interface):
bar = Field(u"Bar")
baz = Field(u"Baz")
@@ -239,6 +249,7 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.component.interface import provideInterface
from zope.interface import Attribute
from zope.interface import Interface
+
class IFoo(Interface):
bar = Attribute("Bar")
context = DummyZCMLContext()
@@ -254,6 +265,7 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.component.interface import provideInterface
from zope.schema import Field
from zope.interface import Interface
+
class IFoo(Interface):
bar = Field(u"Bar", readonly=True)
context = DummyZCMLContext()
@@ -276,6 +288,7 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.protectclass import protectName
+
class IFoo(Interface):
bar = Attribute("Bar")
baz = Attribute("Baz")
@@ -303,8 +316,10 @@ class ClassDirectiveTests(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.protectclass import protectName
+
class IFoo(Interface):
bar = Attribute("Bar")
+
class IBar(Interface):
baz = Attribute("Baz")
context = DummyZCMLContext()
@@ -489,6 +504,7 @@ class Test_allow(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.metaconfigure import protectModule
+
class IFoo(Interface):
bar = Attribute('Bar')
context = DummyZCMLContext()
@@ -506,6 +522,7 @@ class Test_allow(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.metaconfigure import protectModule
+
class IFoo(Interface):
bar = Attribute('Bar')
baz = Attribute('Baz')
@@ -586,6 +603,7 @@ class Test_requre(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.metaconfigure import protectModule
+
class IFoo(Interface):
bar = Attribute('Bar')
context = DummyZCMLContext()
@@ -604,6 +622,7 @@ class Test_requre(unittest.TestCase):
from zope.interface import Attribute
from zope.interface import Interface
from zope.security.metaconfigure import protectModule
+
class IFoo(Interface):
bar = Attribute('Bar')
baz = Attribute('Baz')
diff --git a/src/zope/security/tests/test_permission.py b/src/zope/security/tests/test_permission.py
index 82ddea2..9e03496 100644
--- a/src/zope/security/tests/test_permission.py
+++ b/src/zope/security/tests/test_permission.py
@@ -17,6 +17,7 @@ import unittest
from zope.component.testing import PlacelessSetup
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public
+
class PermissionTests(unittest.TestCase):
def _getTargetClass(self):
@@ -62,7 +63,7 @@ class Test_checkPermission(PlacelessSetup, unittest.TestCase):
def test_w_CheckerPublic(self):
from zope.security.checker import CheckerPublic
- self._callFUT(None, CheckerPublic) # no raise
+ self._callFUT(None, CheckerPublic) # no raise
def test_miss(self):
self.assertRaises(ValueError, self._callFUT, None, 'nonesuch')
@@ -72,7 +73,7 @@ class Test_checkPermission(PlacelessSetup, unittest.TestCase):
from zope.security.interfaces import IPermission
permission = object()
provideUtility(permission, IPermission, 'testing')
- self._callFUT(None, 'testing') # no raise
+ self._callFUT(None, 'testing') # no raise
class Test_allPermissions(PlacelessSetup, unittest.TestCase):
@@ -143,7 +144,6 @@ class Test_PermissionsVocabulary(PlacelessSetup, unittest.TestCase):
from zope.security.interfaces import IPermission
from zope.schema import getValidationErrors
-
xmlconfig.file('configure.zcml', zope.security)
vocabulary = self._callFUT()
vocabulary = sorted(vocabulary, key=lambda term: term.token)
@@ -155,6 +155,7 @@ class Test_PermissionsVocabulary(PlacelessSetup, unittest.TestCase):
verifyObject(IPermission, p)
self.assertEqual([], getValidationErrors(IPermission, p))
+
class Test_PermissionIdsVocabulary(PlacelessSetup, unittest.TestCase):
def _callFUT(self):
diff --git a/src/zope/security/tests/test_protectclass.py b/src/zope/security/tests/test_protectclass.py
index 759f151..2f8e490 100644
--- a/src/zope/security/tests/test_protectclass.py
+++ b/src/zope/security/tests/test_protectclass.py
@@ -16,6 +16,7 @@
import unittest
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public
+
class Test_protectName(unittest.TestCase):
def setUp(self):
diff --git a/src/zope/security/tests/test_proxy.py b/src/zope/security/tests/test_proxy.py
index cecac86..adbb4f2 100644
--- a/src/zope/security/tests/test_proxy.py
+++ b/src/zope/security/tests/test_proxy.py
@@ -17,18 +17,21 @@ import unittest
from zope.security._compat import PYTHON2, PURE_PYTHON
+
def _skip_if_not_Py2(testfunc):
return unittest.skipUnless(PYTHON2, "Only on Py2")(testfunc)
# pylint:disable=protected-access,eval-used,too-many-lines,too-many-public-methods
-if not PYTHON2: # pragma: no cover (Python 3)
+
+if not PYTHON2: # pragma: PY3
def coerce(*args):
raise NotImplementedError("Not on Python 3")
cmp = coerce
long = int
unicode = str
+
class AbstractProxyTestBase(object):
# pylint:disable=no-member,blacklisted-name
@@ -67,6 +70,7 @@ class AbstractProxyTestBase(object):
def test___getattr___w_checker_unauthorized(self):
from zope.security.interfaces import Unauthorized
+
class Foo(object):
bar = 'Bar'
target = Foo()
@@ -77,6 +81,7 @@ class AbstractProxyTestBase(object):
def test___getattr___w_checker_forbidden_attribute(self):
from zope.security.interfaces import ForbiddenAttribute
+
class Foo(object):
bar = 'Bar'
target = Foo()
@@ -90,6 +95,7 @@ class AbstractProxyTestBase(object):
def test__getattr__w_checker_ok_dynamic_attribute_called_once(self):
class Dynamic(object):
count = 0
+
def __getattr__(self, name):
self.count += 1
if self.count == 1:
@@ -118,6 +124,7 @@ class AbstractProxyTestBase(object):
def test___setattr___w_checker_unauthorized(self):
from zope.security.interfaces import Unauthorized
+
class Foo(object):
bar = 'Bar'
target = Foo()
@@ -128,6 +135,7 @@ class AbstractProxyTestBase(object):
def test___setattr___w_checker_forbidden_attribute(self):
from zope.security.interfaces import ForbiddenAttribute
+
class Foo(object):
bar = 'Bar'
target = Foo()
@@ -150,6 +158,7 @@ class AbstractProxyTestBase(object):
def test___delattr___w_checker_unauthorized(self):
from zope.security.interfaces import Unauthorized
+
class Foo(object):
def __init__(self):
self.bar = 'Bar'
@@ -162,6 +171,7 @@ class AbstractProxyTestBase(object):
def test___delattr___w_checker_forbidden_attribute(self):
from zope.security.interfaces import ForbiddenAttribute
+
class Foo(object):
def __init__(self):
self.bar = 'Bar'
@@ -192,9 +202,10 @@ class AbstractProxyTestBase(object):
def test___str___fails_return(self):
from zope.security.interfaces import ForbiddenAttribute
+
class CustomStr(object):
def __str__(self):
- "<CustomStr>" # Docstring, not a return
+ "<CustomStr>" # Docstring, not a return
target = CustomStr()
checker = DummyChecker(ForbiddenAttribute, allowed=('__str__'))
@@ -224,12 +235,14 @@ class AbstractProxyTestBase(object):
def test___str___falls_through_to_repr_when_both_allowed(self):
from zope.security.interfaces import ForbiddenAttribute
+
class CustomRepr(object):
def __repr__(self):
return "<CustomRepr>"
target = CustomRepr()
- checker = DummyChecker(ForbiddenAttribute, allowed=("__str__", '__repr__'))
+ checker = DummyChecker(
+ ForbiddenAttribute, allowed=("__str__", '__repr__'))
proxy = self._makeOne(target, checker)
self.assertEqual(repr(proxy), "<CustomRepr>")
self.assertEqual(str(target), "<CustomRepr>")
@@ -237,6 +250,7 @@ class AbstractProxyTestBase(object):
def test___str___doesnot_fall_through_to_repr_when_str_not_allowed(self):
from zope.security.interfaces import ForbiddenAttribute
+
class CustomRepr(object):
def __repr__(self):
return "<CustomRepr>"
@@ -250,6 +264,7 @@ class AbstractProxyTestBase(object):
def test___str___doesnot_fall_through_to_repr_when_repr_not_allowed(self):
from zope.security.interfaces import ForbiddenAttribute
+
class CustomRepr(object):
def __repr__(self):
return "<CustomRepr>"
@@ -263,9 +278,10 @@ class AbstractProxyTestBase(object):
def test___str___falls_through_to_repr_but_repr_fails_return(self):
from zope.security.interfaces import ForbiddenAttribute
+
class CustomRepr(object):
def __repr__(self):
- "<CustomRepr>" # Docstring, not a return
+ "<CustomRepr>" # Docstring, not a return
target = CustomRepr()
checker = DummyChecker(ForbiddenAttribute, allowed=('__repr__'))
@@ -276,62 +292,62 @@ class AbstractProxyTestBase(object):
repr(proxy)
@_skip_if_not_Py2
- def test___cmp___w_self(self):
+ def test___cmp___w_self(self): # pragma: no cover
target = object()
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertEqual(cmp(proxy, proxy), 0)
@_skip_if_not_Py2
- def test___cmp___w_target(self):
+ def test___cmp___w_target(self): # pragma: no cover
target = object()
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertEqual(cmp(proxy, target), 0)
@_skip_if_not_Py2
- def test___cmp___w_other(self):
+ def test___cmp___w_other(self): # pragma: no cover
target = object()
other = object()
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertNotEqual(cmp(proxy, other), 0)
@_skip_if_not_Py2
- def test___cmp___w_other_proxy(self):
+ def test___cmp___w_other_proxy(self): # pragma: no cover
target = object()
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
o_proxy = self._makeOne(target, checker)
self.assertEqual(cmp(proxy, o_proxy), 0)
def test__le__(self):
target = 1
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertTrue(proxy <= 1)
def test__ne__(self):
target = 1
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertFalse(proxy != 1)
def test__ge__(self):
target = 1
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertTrue(proxy >= 1)
def test__gt__(self):
target = 1
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertTrue(proxy > 0)
def test___hash___w_self(self):
target = object()
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
proxy = self._makeOne(target, checker)
self.assertEqual(hash(proxy), hash(target))
@@ -348,6 +364,7 @@ class AbstractProxyTestBase(object):
def test___call___w_checker_unauthorized(self):
from zope.security.interfaces import Unauthorized
+
class Foo(object):
def __call__(self):
raise AssertionError("Never called")
@@ -359,6 +376,7 @@ class AbstractProxyTestBase(object):
def test___call___w_checker_forbidden_attribute(self):
from zope.security.interfaces import ForbiddenAttribute
+
class Foo(object):
def __call__(self):
raise AssertionError("Never called")
@@ -399,7 +417,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__float__')
@_skip_if_not_Py2
- def test___long___w_checker_allows(self):
+ def test___long___w_checker_allows(self): # pragma: no cover
target = 3.0
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -407,7 +425,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__long__')
@_skip_if_not_Py2
- def test___long___w_checker_forbids(self):
+ def test___long___w_checker_forbids(self): # pragma: no cover
from zope.security.interfaces import ForbiddenAttribute
target = 3
checker = DummyChecker(ForbiddenAttribute)
@@ -416,7 +434,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__long__')
@_skip_if_not_Py2
- def test___oct___w_checker_allows(self):
+ def test___oct___w_checker_allows(self): # pragma: no cover
target = 3
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -424,7 +442,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__oct__')
@_skip_if_not_Py2
- def test___oct___w_checker_forbids(self):
+ def test___oct___w_checker_forbids(self): # pragma: no cover
from zope.security.interfaces import ForbiddenAttribute
target = 3
checker = DummyChecker(ForbiddenAttribute)
@@ -433,7 +451,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__oct__')
@_skip_if_not_Py2
- def test___hex___w_checker_allows(self):
+ def test___hex___w_checker_allows(self): # pragma: no cover
target = 3
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -441,7 +459,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__hex__')
@_skip_if_not_Py2
- def test___hex___w_checker_forbids(self):
+ def test___hex___w_checker_forbids(self): # pragma: no cover
from zope.security.interfaces import ForbiddenAttribute
target = 3
checker = DummyChecker(ForbiddenAttribute)
@@ -599,21 +617,6 @@ class AbstractProxyTestBase(object):
self.assertRaises(ForbiddenAttribute, lambda: pow(x, proxy))
self.assertEqual(checker._checked, '__rpow__')
- def test___pow___w_z_proxied_allowed(self):
- x, y, z = 3, 4, 7
- checker = DummyChecker()
- proxy = self._makeOne(z, checker)
- self.assertEqual(pow(x, y, proxy), pow(x, y, z))
- self.assertEqual(checker._checked, '__3pow__')
-
- def test___pow___w_z_proxied_forbidden(self):
- from zope.security.interfaces import ForbiddenAttribute
- x, y, z = 3, 4, 7
- checker = DummyChecker(ForbiddenAttribute)
- proxy = self._makeOne(z, checker)
- self.assertRaises(ForbiddenAttribute, lambda: pow(x, y, proxy))
- self.assertEqual(checker._checked, '__3pow__')
-
def test___neg___w_checker_allows(self):
target = 3
checker = DummyChecker()
@@ -756,7 +759,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__or__')
@_skip_if_not_Py2
- def test___coerce___w_checker_allows(self):
+ def test___coerce___w_checker_allows(self): # pragma: no cover
target = 3
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -764,7 +767,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__coerce__')
@_skip_if_not_Py2
- def test___coerce___w_checker_forbids(self):
+ def test___coerce___w_checker_forbids(self): # pragma: no cover
from zope.security.interfaces import ForbiddenAttribute
target = 3
checker = DummyChecker(ForbiddenAttribute)
@@ -785,6 +788,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __iadd__(self, rhs):
self.value += rhs
return self
@@ -818,6 +822,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __isub__(self, rhs):
self.value -= rhs
return self
@@ -851,6 +856,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __imul__(self, rhs):
self.value *= rhs
return self
@@ -884,6 +890,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __idiv__(self, rhs):
self.value /= rhs
return self
@@ -918,6 +925,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __itruediv__(self, rhs):
self.value /= rhs
return self
@@ -952,6 +960,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __ifloordiv__(self, rhs):
self.value //= rhs
return self
@@ -985,6 +994,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __imod__(self, rhs):
self.value %= rhs
return self
@@ -1018,6 +1028,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __ipow__(self, rhs):
self.value **= rhs
return self
@@ -1051,6 +1062,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __ilshift__(self, rhs):
self.value <<= rhs
return self
@@ -1084,6 +1096,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __irshift__(self, rhs):
self.value >>= rhs
return self
@@ -1117,6 +1130,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __iand__(self, rhs):
self.value &= rhs
return self
@@ -1150,6 +1164,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __ixor__(self, rhs):
self.value ^= rhs
return self
@@ -1185,6 +1200,7 @@ class AbstractProxyTestBase(object):
class Foo(object):
def __init__(self, value):
self.value = value
+
def __ior__(self, rhs):
self.value |= rhs
return self
@@ -1290,6 +1306,7 @@ class AbstractProxyTestBase(object):
target = [0, 1, 2]
checker = DummyChecker()
proxy = self._makeOne(target, checker)
+
def _try():
proxy[4] = 7
self.assertRaises(IndexError, _try)
@@ -1300,13 +1317,14 @@ class AbstractProxyTestBase(object):
target = [0, 1, 2]
checker = DummyChecker(ForbiddenAttribute)
proxy = self._makeOne(target, checker)
+
def _try():
proxy[4] = 7
self.assertRaises(ForbiddenAttribute, _try)
self.assertEqual(checker._checked, '__setitem__')
@_skip_if_not_Py2
- def test___getslice___w_checker_allows(self):
+ def test___getslice___w_checker_allows(self): # pragma: no cover
target = [0, 1, 2]
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -1316,11 +1334,13 @@ class AbstractProxyTestBase(object):
def test___getslice___error_propagates(self):
class Missing(Exception):
pass
+
class Get(object):
def __getitem__(self, x):
- raise Missing('__getitem__') # pragma: no cover (only py3)
- def __getslice__(self, start, stop):
- raise Missing("__getslice__")
+ raise Missing('__getitem__')
+
+ def __getslice__(self, start, stop): # PY2
+ raise Missing("__getslice__") # pragma: no cover
target = Get()
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -1333,6 +1353,7 @@ class AbstractProxyTestBase(object):
def test___getslice___dne_uses_getitem(self):
class Missing(Exception):
pass
+
class Get(object):
def __getitem__(self, x):
raise Missing('__getitem__')
@@ -1347,7 +1368,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, self.getslice)
@_skip_if_not_Py2
- def test___getslice___w_checker_forbids(self):
+ def test___getslice___w_checker_forbids(self): # pragma: no cover
from zope.security.interfaces import ForbiddenAttribute
target = [0, 1, 2]
checker = DummyChecker(ForbiddenAttribute)
@@ -1356,7 +1377,7 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__getslice__')
@_skip_if_not_Py2
- def test___setslice___w_checker_allows(self):
+ def test___setslice___w_checker_allows(self): # pragma: no cover
target = [0, 1, 2]
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -1365,11 +1386,12 @@ class AbstractProxyTestBase(object):
self.assertEqual(checker._checked, '__setslice__')
@_skip_if_not_Py2
- def test___setslice___w_checker_forbids(self):
+ def test___setslice___w_checker_forbids(self): # pragma: no cover
from zope.security.interfaces import ForbiddenAttribute
target = [0, 1, 2]
checker = DummyChecker(ForbiddenAttribute)
proxy = self._makeOne(target, checker)
+
def _try():
proxy[1:3] = [3, 4]
self.assertRaises(ForbiddenAttribute, _try)
@@ -1378,11 +1400,13 @@ class AbstractProxyTestBase(object):
def test___setslice___error_propagates(self):
class Missing(Exception):
pass
+
class Set(object):
def __setitem__(self, k, v):
- raise Missing('__setitem__') # pragma: no cover (only py3)
- def __setslice__(self, start, stop, value):
- raise Missing("__setslice__")
+ raise Missing('__setitem__')
+
+ def __setslice__(self, start, stop, value): # PY2
+ raise Missing("__setslice__") # pragma: no cover
target = Set()
checker = DummyChecker()
proxy = self._makeOne(target, checker)
@@ -1395,6 +1419,7 @@ class AbstractProxyTestBase(object):
def test___setslice___dne_uses_setitem(self):
class Missing(Exception):
pass
+
class Set(object):
def __setitem__(self, k, v):
raise Missing('__setitem__')
@@ -1443,6 +1468,7 @@ class AbstractProxyTestBase(object):
target = {'a': 0, 'b': 1, 'c': 2}
checker = DummyChecker(ForbiddenAttribute)
proxy = self._makeOne(target, checker)
+
def _try():
proxy['a'] = 7
self.assertRaises(ForbiddenAttribute, _try)
@@ -1451,7 +1477,7 @@ class AbstractProxyTestBase(object):
binops = [
"x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y",
"x<<y", "x>>y", "x&y", "x|y", "x^y",
- ]
+ ]
def test_binops(self):
from zope.security.proxy import removeSecurityProxy
@@ -1467,28 +1493,27 @@ class AbstractProxyTestBase(object):
self.assertEqual(removeSecurityProxy(eval(expr)), z,
"x=%r; y=%r; expr=%r" % (x, y, expr))
-
@_skip_if_not_Py2
- def test___unicode___allowed_by_default(self):
+ def test___unicode___allowed_by_default(self): # pragma: no cover
# https://github.com/zopefoundation/zope.security/issues/10
class Foo(object):
def __unicode__(self):
return u'I am unicode'
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
target = Foo()
proxy = self._makeOne(target, checker)
self.assertEqual(unicode(target), u'I am unicode')
self.assertEqual(unicode(target), unicode(proxy))
@_skip_if_not_Py2
- def test___unicode___falls_through_to_str_by_default(self):
+ def test___unicode___falls_through_to_str_by_default(self): # pragma: no cover # noqa: E501 line too long
# https://github.com/zopefoundation/zope.security/issues/10
class Foo(object):
def __str__(self):
return 'I am str'
- checker = object() # checker not consulted
+ checker = object() # checker not consulted
target = Foo()
proxy = self._makeOne(target, checker)
self.assertEqual(unicode(target), u'I am str')
@@ -1497,11 +1522,12 @@ class AbstractProxyTestBase(object):
self.assertIsInstance(unicode(proxy), unicode)
@_skip_if_not_Py2
- def test___unicode___falls_through_to_str_even_if_str_not_allowed(self):
+ def test___unicode___falls_through_to_str_even_if_str_not_allowed(self): # pragma: no cover # noqa: E501 line too long
# https://github.com/zopefoundation/zope.security/issues/10
# Note that this is inconsistent with str() and probably not a good
# idea overall, so this test is strictly a regression test.
from zope.security.interfaces import ForbiddenAttribute
+
class Foo(object):
def __str__(self):
return 'I am str'
@@ -1525,7 +1551,7 @@ class AbstractProxyTestBase(object):
class ProxyCTests(AbstractProxyTestBase,
unittest.TestCase):
- def _getTargetClass(self):
+ def _getTargetClass(self): # pragma: no cover
from zope.security.proxy import _Proxy
return _Proxy
@@ -1548,6 +1574,7 @@ class ProxyPyTests(AbstractProxyTestBase,
def test_access_checker_from_subclass(self):
target = object()
checker = DummyChecker()
+
class Sub(self._getTargetClass()):
def get_checker(self):
return self._checker
@@ -1568,6 +1595,7 @@ class ProxyPyTests(AbstractProxyTestBase,
target = object()
checker = object()
proxy = self._makeOne(target, checker)
+
def test():
del proxy._wrapped
self.assertRaises(AttributeError, test)
@@ -1576,6 +1604,7 @@ class ProxyPyTests(AbstractProxyTestBase,
target = object()
checker = object()
proxy = self._makeOne(target, checker)
+
def test():
del proxy._checker
self.assertRaises(AttributeError, test)
@@ -1616,7 +1645,8 @@ class ProxyPyTests(AbstractProxyTestBase,
orig_builtin_isinstance = zope.security.proxy._builtin_isinstance
zope.security.proxy._builtin_isinstance = None
try:
- self.assertRaises(TypeError, zope.security.proxy.getObjectPy, proxy)
+ self.assertRaises(
+ TypeError, zope.security.proxy.getObjectPy, proxy)
finally:
zope.security.proxy._builtin_isinstance = orig_builtin_isinstance
@@ -1646,17 +1676,21 @@ class ProxyPyTests(AbstractProxyTestBase,
proxy = self._makeOne(module, DummyChecker())
self.assertEqual(WithModule.__module__, proxy.__module__)
+
class DummyChecker(object):
_proxied = _checked = None
+
def __init__(self, raising=None, allowed=()):
self._raising = raising
self._allowed = allowed
+
def check(self, target, name):
self._checked = name
if name not in self._allowed:
if self._raising is not None:
raise self._raising(name)
check_getattr = check_setattr = check
+
def proxy(self, value):
self._proxied = value
return value
@@ -1703,6 +1737,7 @@ class Test_isinstance(unittest.TestCase):
def test_w_proxied_object(self):
from zope.security.checker import Checker
from zope.security.proxy import Proxy
+
class Foo(object):
pass
target = Foo()
@@ -1717,7 +1752,7 @@ class Checker(object):
ok = 1
- unproxied_types = {str,}
+ unproxied_types = {str, }
def check_getattr(self, _object, name):
if name not in ("foo", "next", "__class__", "__name__", "__module__"):
@@ -1741,32 +1776,45 @@ class Checker(object):
class Something:
def __init__(self):
self.foo = [1, 2, 3]
+
def __getitem__(self, key):
return self.foo[key]
+
def __setitem__(self, key, value):
self.foo[key] = value
+
def __delitem__(self, key):
del self.foo[key]
+
def __call__(self, arg):
return 42
+
def __eq__(self, other):
return self is other
+
def __hash__(self):
return 42
+
def __iter__(self):
return self
+
def __next__(self):
- return 42 # Infinite sequence
+ return 42 # Infinite sequence
next = __next__
+
def __len__(self):
return 42
- def __nonzero__(self):
- return 1
- def __getslice__(self, i, j):
- return [42]
- def __setslice__(self, i, j, value):
- if value != [42]:
+
+ def __nonzero__(self): # PY2
+ return 1 # pragma: no cover
+
+ def __getslice__(self, i, j): # PY2
+ return [42] # pragma: no cover
+
+ def __setslice__(self, i, j, value): # PY2
+ if value != [42]: # pragma: no cover
raise AssertionError("Value should be [42]")
+
def __contains__(self, x):
return x == 42
@@ -1800,7 +1848,7 @@ class ProxyFactoryTests(unittest.TestCase):
self.assertTrue(s.startswith(
"<security proxied %s.%s instance at"
% (x.__class__.__module__, x.__class__.__name__)),
- s)
+ s)
def testRepr(self):
from zope.security.proxy import ProxyFactory
@@ -1814,7 +1862,7 @@ class ProxyFactoryTests(unittest.TestCase):
self.assertTrue(s.startswith(
"<security proxied %s.%s instance at"
% (x.__class__.__module__, x.__class__.__name__)),
- s)
+ s)
def testGetAttrOK(self):
from zope.security.proxy import removeSecurityProxy
@@ -1867,8 +1915,8 @@ class ProxyFactoryTests(unittest.TestCase):
def testRichCompareOK(self):
self.assertTrue(self.p == self.x)
-## def testRichCompareFail(self):
-## self.shouldFail(lambda: self.p == self.x)
+# def testRichCompareFail(self):
+# self.shouldFail(lambda: self.p == self.x)
def testIterOK(self):
from zope.security.proxy import removeSecurityProxy
@@ -1884,23 +1932,23 @@ class ProxyFactoryTests(unittest.TestCase):
self.shouldFail(self.p.next)
@_skip_if_not_Py2
- def testCompareOK(self):
+ def testCompareOK(self): # pragma: no cover
self.assertEqual(cmp(self.p, self.x), 0)
-## def testCompareFail(self):
-## self.shouldFail(cmp, self.p, self.x)
+# def testCompareFail(self):
+# self.shouldFail(cmp, self.p, self.x)
def testHashOK(self):
self.assertEqual(hash(self.p), hash(self.x))
-## def testHashFail(self):
-## self.shouldFail(hash, self.p)
+# def testHashFail(self):
+# self.shouldFail(hash, self.p)
def testNonzeroOK(self):
self.assertEqual(not self.p, 0)
-## def testNonzeroFail(self):
-## self.shouldFail(lambda: not self.p)
+# def testNonzeroFail(self):
+# self.shouldFail(lambda: not self.p)
def testLenOK(self):
self.assertEqual(len(self.p), 42)
@@ -1909,7 +1957,7 @@ class ProxyFactoryTests(unittest.TestCase):
self.shouldFail(len, self.p)
@_skip_if_not_Py2
- def testSliceOK(self):
+ def testSliceOK(self): # pragma: no cover
from zope.security.proxy import removeSecurityProxy
self.assertEqual(removeSecurityProxy(self.p[:]), [42])
@@ -1938,9 +1986,9 @@ class ProxyFactoryTests(unittest.TestCase):
from zope.security.proxy import getChecker
self.assertEqual(self.c, getChecker(self.p))
-
def testProxiedClassicClassAsDictKey(self):
from zope.security.proxy import ProxyFactory
+
class C(object):
pass
d = {C: C()}
@@ -1949,6 +1997,7 @@ class ProxyFactoryTests(unittest.TestCase):
def testProxiedNewClassAsDictKey(self):
from zope.security.proxy import ProxyFactory
+
class C(object):
pass
d = {C: C()}
@@ -1957,7 +2006,7 @@ class ProxyFactoryTests(unittest.TestCase):
unops = ["-x", "+x", "abs(x)", "~x", "int(x)", "float(x)"]
if PYTHON2:
- unops.append("long(x)")
+ unops.append("long(x)") # pragma: no cover
def _make_eval(self, expr, locs):
def _eval(*args):
@@ -1973,7 +2022,7 @@ class ProxyFactoryTests(unittest.TestCase):
from zope.security.proxy import removeSecurityProxy
self.c.unproxied_types = {str, int, float}
if PYTHON2:
- self.c.unproxied_types.add(long)
+ self.c.unproxied_types.add(long) # pragma: no cover
for expr in self.unops:
x = 1
@@ -1986,7 +2035,7 @@ class ProxyFactoryTests(unittest.TestCase):
self.shouldFail(self._make_eval(expr, locals()), x)
@_skip_if_not_Py2
- def test_odd_unops(self):
+ def test_odd_unops(self): # pragma: no cover
# unops that don't return a proxy
P = self.c.proxy
for func in (
@@ -1999,7 +2048,7 @@ class ProxyFactoryTests(unittest.TestCase):
binops = [
"x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y",
"x<<y", "x>>y", "x&y", "x|y", "x^y",
- ]
+ ]
def test_binops(self):
from zope.security.proxy import removeSecurityProxy
@@ -2046,7 +2095,7 @@ class ProxyFactoryTests(unittest.TestCase):
self.shouldFail(doit2)
@_skip_if_not_Py2
- def test_coerce(self):
+ def test_coerce(self): # pragma: no cover
from zope.security.proxy import removeSecurityProxy
P = self.c.proxy
@@ -2203,8 +2252,8 @@ class LocationProxySecurityCheckerTests(unittest.TestCase):
import zope.security
try:
from importlib import reload as _reload
- except ImportError:
- _reload = reload # Python 2
+ except ImportError: # pragma: PY2
+ _reload = reload # noqa: F821 undefined name 'reload'
# This attribute is set when zope.security.decorator is imported, to
# show that it will be set too, if zope.security.proxy is imported
diff --git a/src/zope/security/tests/test_simplepolicies.py b/src/zope/security/tests/test_simplepolicies.py
index ce5c483..fcbc8de 100644
--- a/src/zope/security/tests/test_simplepolicies.py
+++ b/src/zope/security/tests/test_simplepolicies.py
@@ -35,7 +35,7 @@ class ConformsToIInteraction(object):
class ParanoidSecurityPolicyTests(unittest.TestCase,
ConformsToIInteraction,
- ):
+ ):
def _getTargetClass(self):
from zope.security.simplepolicies import ParanoidSecurityPolicy
@@ -87,6 +87,7 @@ class ParanoidSecurityPolicyTests(unittest.TestCase,
def test_checkPermission_w_non_public_only_system_user(self):
from zope.security._definitions import system_user
+
class Participation(object):
interaction = None
principal = system_user
@@ -111,6 +112,7 @@ class ParanoidSecurityPolicyTests(unittest.TestCase,
self.assertTrue(policy.checkPermission(None, None))
self.assertTrue(policy.checkPermission(self, self))
+
class PermissiveSecurityPolicyTests(unittest.TestCase,
ConformsToIInteraction):
diff --git a/src/zope/security/tests/test_testing.py b/src/zope/security/tests/test_testing.py
index 42eebd0..cc11037 100644
--- a/src/zope/security/tests/test_testing.py
+++ b/src/zope/security/tests/test_testing.py
@@ -18,6 +18,7 @@ from zope.testing.cleanup import CleanUp
from zope.security import testing
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public
+
class TestTestingFunctions(CleanUp,
unittest.TestCase):
@@ -50,6 +51,7 @@ class TestTestingFunctions(CleanUp,
def test_contextmanager_ends_interaction_on_exception(self):
from zope.security.management import queryInteraction
+
class MyError(Exception):
pass
@@ -59,7 +61,6 @@ class TestTestingFunctions(CleanUp,
self.assertFalse(queryInteraction())
-
def test_addCheckerPublic(self):
from zope import component
from zope.security.interfaces import IPermission
@@ -69,7 +70,5 @@ class TestTestingFunctions(CleanUp,
self.assertIs(perm, utility)
-
-
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
diff --git a/src/zope/security/tests/test_zcml.py b/src/zope/security/tests/test_zcml.py
index 9fb1cc4..2cdf62a 100644
--- a/src/zope/security/tests/test_zcml.py
+++ b/src/zope/security/tests/test_zcml.py
@@ -14,6 +14,7 @@
import unittest
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public
+
class ConformsToIFromUnicode(object):
def test_class_conforms_to_IFromUnicode(self):
@@ -29,7 +30,7 @@ class ConformsToIFromUnicode(object):
class PermissionTests(unittest.TestCase,
ConformsToIFromUnicode,
- ):
+ ):
def _getTargetClass(self):
from zope.security.zcml import Permission
@@ -147,38 +148,38 @@ class Test_redefinePermission(unittest.TestCase):
def test_wo_existing_mapping(self):
z_context = DummyZCMLContext()
+
class Context(object):
pass
context = z_context.context = Context()
after = object()
self._callFUT(z_context, 'before.permission', after)
- self.assertTrue(context.permission_mapping['before.permission']
- is after)
+ self.assertIs(context.permission_mapping['before.permission'], after)
def test_w_existing_mapping_wo_existing_key(self):
z_context = DummyZCMLContext()
+
class Context(object):
pass
context = z_context.context = Context()
mapping = context.permission_mapping = {}
after = object()
self._callFUT(z_context, 'before.permission', after)
- self.assertTrue(context.permission_mapping is mapping)
- self.assertTrue(context.permission_mapping['before.permission']
- is after)
+ self.assertIs(context.permission_mapping, mapping)
+ self.assertIs(context.permission_mapping['before.permission'], after)
def test_w_existing_mapping_w_existing_key(self):
z_context = DummyZCMLContext()
+
class Context(object):
pass
context = z_context.context = Context()
mapping = context.permission_mapping = {}
- before = mapping['before.permission'] = object()
+ mapping['before.permission'] = object()
after = object()
self._callFUT(z_context, 'before.permission', after)
- self.assertTrue(context.permission_mapping is mapping)
- self.assertTrue(context.permission_mapping['before.permission']
- is after)
+ self.assertIs(context.permission_mapping, mapping)
+ self.assertIs(context.permission_mapping['before.permission'], after)
class DummyZCMLContext(object):
diff --git a/src/zope/security/tests/test_zcml_functest.py b/src/zope/security/tests/test_zcml_functest.py
index b669847..2486af6 100644
--- a/src/zope/security/tests/test_zcml_functest.py
+++ b/src/zope/security/tests/test_zcml_functest.py
@@ -52,7 +52,6 @@ class TestClassDirective(unittest.TestCase):
import zope.security
XMLConfig('meta.zcml', zope.security)()
-
def testEmptyDirective(self):
from zope.configuration.xmlconfig import xmlconfig
self._meta()
@@ -62,7 +61,6 @@ class TestClassDirective(unittest.TestCase):
""")
xmlconfig(f)
-
def testImplements(self):
from zope.component.interface import queryInterface
from zope.configuration.xmlconfig import xmlconfig
@@ -83,7 +81,6 @@ class TestClassDirective(unittest.TestCase):
self.assertEqual(queryInterface(
"zope.security.tests.exampleclass.IExample"), IExample)
-
def testMulImplements(self):
from zope.component.interface import queryInterface
from zope.configuration.xmlconfig import xmlconfig
@@ -112,7 +109,7 @@ class TestClassDirective(unittest.TestCase):
"zope.security.tests.exampleclass.IExample"), IExample)
self.assertEqual(queryInterface(
"zope.security.tests.exampleclass.IExample2"),
- IExample2)
+ IExample2)
def testRequire(self):
from zope.configuration.xmlconfig import xmlconfig
@@ -162,7 +159,6 @@ class TestFactorySubdirective(unittest.TestCase):
import zope.security
XMLConfig('meta.zcml', zope.security)()
-
def testFactory(self):
from zope.component import getUtility
from zope.component.interfaces import IFactory
@@ -208,7 +204,6 @@ class TestFactorySubdirective(unittest.TestCase):
self.assertEqual(factory.title, "Example content")
self.assertEqual(factory.description, "Example description")
-
def testFactoryPublicPermission(self):
from zope.component import getUtility
from zope.component.interfaces import IFactory
@@ -251,7 +246,6 @@ class TestFactoryDirective(unittest.TestCase):
from zope.configuration.xmlconfig import XMLConfig
XMLConfig('meta.zcml', zope.security)()
-
def testFactory(self):
from zope.component import createObject
from zope.configuration.xmlconfig import xmlconfig
@@ -272,11 +266,11 @@ class TestFactoryDirective(unittest.TestCase):
self.assertTrue(proxy.isinstance(obj, exampleclass.ExampleClass))
-
def _pfx(name):
from zope.security.tests import module
return module.__name__ + '.' + name
+
def defineDirectives():
from zope.configuration.xmlconfig import XMLConfig
from zope.configuration.xmlconfig import xmlconfig
@@ -289,11 +283,13 @@ def defineDirectives():
<permission id="zope.Paltry" title="paltry" />
</configure>"""))
+
NOTSET = ()
P1 = "zope.Extravagant"
P2 = "zope.Paltry"
+
class TestRequireDirective(unittest.TestCase):
def setUp(self):
@@ -306,6 +302,7 @@ class TestRequireDirective(unittest.TestCase):
class B(object):
def m1(self):
raise AssertionError("Never called")
+
def m2(self):
raise AssertionError("Never called")
@@ -313,6 +310,7 @@ class TestRequireDirective(unittest.TestCase):
class C(B):
def m3(self):
raise AssertionError("Never called")
+
def m4(self):
raise AssertionError("Never called")
@@ -328,7 +326,7 @@ class TestRequireDirective(unittest.TestCase):
tearDown()
def assertState(self, m1P=NOTSET, m2P=NOTSET, m3P=NOTSET):
- #Verify that class, instance, and methods have expected permissions
+ # Verify that class, instance, and methods have expected permissions
from zope.security.checker import selectChecker
from zope.security.tests import module
checker = selectChecker(module.test_instance)
@@ -399,7 +397,6 @@ class TestRequireDirective(unittest.TestCase):
self.assertEqual(queryInterface(_pfx("S")), module.S)
-
checker = selectChecker(module.test_instance)
self.assertEqual(checker.setattr_permission_id('m1'), None)
self.assertEqual(checker.setattr_permission_id('m2'), None)
@@ -426,7 +423,6 @@ class TestRequireDirective(unittest.TestCase):
self.assertEqual(queryInterface(_pfx("S")), module.S)
self.assertEqual(queryInterface(_pfx("S2")), module.S2)
-
checker = selectChecker(module.test_instance)
self.assertEqual(checker.setattr_permission_id('m1'), None)
self.assertEqual(checker.setattr_permission_id('m2'), None)
@@ -454,7 +450,6 @@ class TestRequireDirective(unittest.TestCase):
# Make sure we know about the interfaces
self.assertEqual(queryInterface(_pfx("I")), module.I)
-
def testMultipleInterface(self):
from zope.component.interface import queryInterface
from zope.security.tests import module
@@ -478,7 +473,6 @@ class TestRequireDirective(unittest.TestCase):
# "testComposite*TopPerm" exercises tags with permission in containing tag.
# "testComposite*ElementPerm" exercises tags w/permission in children.
-
def testCompositeNoPerm(self):
# Establish rejection of declarations lacking a permission spec.
from zope.configuration.exceptions import ConfigurationError
@@ -490,7 +484,6 @@ class TestRequireDirective(unittest.TestCase):
with self.assertRaises(ConfigurationError):
self.assertDeclaration(declaration)
-
def testCompositeMethodsPluralElementPerm(self):
declaration = ('''<class class="%s">
<require
@@ -501,7 +494,6 @@ class TestRequireDirective(unittest.TestCase):
self.assertDeclaration(declaration,
m1P=P1, m3P=P1)
-
def testCompositeInterfaceTopPerm(self):
declaration = ('''<class class="%s">
<require
@@ -512,7 +504,6 @@ class TestRequireDirective(unittest.TestCase):
self.assertDeclaration(declaration,
m1P=P1, m2P=P1)
-
def testSubInterfaces(self):
declaration = ('''<class class="%s">
<require
@@ -523,7 +514,6 @@ class TestRequireDirective(unittest.TestCase):
# m1 and m2 are in the interface, so should be set, and m3 should not:
self.assertDeclaration(declaration, m1P=P1, m2P=P1)
-
def testMimicOnly(self):
declaration = ('''<class class="%s">
<require
@@ -534,12 +524,11 @@ class TestRequireDirective(unittest.TestCase):
<require like_class="%s" />
</class>
''' % (_pfx("test_base"), P1,
- _pfx("test_class"), _pfx("test_base")))
+ _pfx("test_class"), _pfx("test_base")))
# m1 and m2 are in the interface, so should be set, and m3 should not:
self.assertDeclaration(declaration,
m1P=P1, m2P=P1)
-
def testMimicAsDefault(self):
declaration = ('''<class class="%s">
<require
@@ -553,7 +542,7 @@ class TestRequireDirective(unittest.TestCase):
attributes="m2 m3"/>
</class>
''' % (_pfx("test_base"), P1,
- _pfx("test_class"), _pfx("test_base"), P2))
+ _pfx("test_class"), _pfx("test_base"), P2))
# m1 and m2 are in the interface, so should be set, and m3 should not:
self.assertDeclaration(declaration,
@@ -564,21 +553,22 @@ def apply_declaration(declaration):
'''Apply the xmlconfig machinery.'''
from zope.configuration.xmlconfig import xmlconfig
if isinstance(declaration, bytes):
- declaration = declaration.decode("utf-8")
+ declaration = declaration.decode("utf-8") # pragma: no cover PY2
return xmlconfig(io.StringIO(declaration))
-
def make_dummy():
from zope.interface import Interface
import zope.security.zcml
global IDummy
+
class IDummy(Interface):
perm = zope.security.zcml.Permission(title=u'')
perms = []
+
def dummy(context_, perm):
global perms
perms.append(perm)
diff --git a/src/zope/security/zcml.py b/src/zope/security/zcml.py
index 473c06e..4e3c17c 100644
--- a/src/zope/security/zcml.py
+++ b/src/zope/security/zcml.py
@@ -65,6 +65,7 @@ class ISecurityPolicyDirective(Interface):
description=u"Pointer to the object that will handle the security.",
required=True)
+
def securityPolicy(_context, component):
_context.action(
discriminator='defaultPolicy',
@@ -72,6 +73,7 @@ def securityPolicy(_context, component):
args=(component,)
)
+
class IPermissionDirective(Interface):
"""Define a new security object."""
@@ -90,6 +92,7 @@ class IPermissionDirective(Interface):
description=u"Provides a description for the object.",
required=False)
+
def permission(_context, id, title, description=u''):
from zope.security.interfaces import IPermission
from zope.security.permission import Permission
@@ -97,6 +100,7 @@ def permission(_context, id, title, description=u''):
permission = Permission(id, title, description)
utility(_context, IPermission, permission, name=id)
+
class IRedefinePermission(Interface):
"""Define a permission to replace another permission."""
@@ -110,6 +114,7 @@ class IRedefinePermission(Interface):
description=u"Substituted permission ID.",
required=True)
+
def redefinePermission(_context, from_, to):
_context = _context.context
diff --git a/tox.ini b/tox.ini
index 1a7a0ee..7c625bd 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,39 +1,68 @@
+# 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,pypy,jython,py33,coverage,docs
- py27,py27-watch,pypy,pypy3,py35,py36,py37-watch,py37-pure,py37,py38,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
+ py27-watch, py37-watch
[testenv]
+usedevelop = true
+deps =
+setenv =
+ pure: PURE_PYTHON=1
+ !pure-!pypy-!pypy3: PURE_PYTHON=0
+ ZOPE_INTERFACE_STRICT_IRO=1
+ watch: ZOPE_WATCH_CHECKERS = 1
commands =
- zope-testrunner --test-path=src []
- sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+ zope-testrunner --test-path=src {posargs:-vc}
+ !py27-!pypy: sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
extras =
test
docs
-deps =
-setenv =
- ZOPE_INTERFACE_STRICT_IRO = 1
- watch: ZOPE_WATCH_CHECKERS = 1
- pure: PURE_PYTHON = 1
[testenv:coverage]
-usedevelop = true
-basepython =
- python2.7
-commands =
- coverage run -m zope.testrunner --test-path=src []
- coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
- coverage html
- coverage report --fail-under=100
+basepython = python3
+allowlist_externals =
+ mkdir
deps =
- {[testenv]deps}
coverage
+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=99.5
+
+[testenv:lint]
+basepython = python3
+skip_install = true
+deps =
+ flake8
+ check-manifest
+ check-python-versions >= 0.19.1
+ wheel
+commands =
+ flake8 src setup.py
+ check-manifest
+ check-python-versions
[testenv:docs]
-basepython =
- python3.7
+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