zope.proxy-4.3.3/0000755000175000017500000000000013562322312012705 5ustar mgmg00000000000000zope.proxy-4.3.3/.coveragerc0000644000175000017500000000023713562322312015030 0ustar mgmg00000000000000[run] source = zope.proxy [report] exclude_lines = pragma: no cover if __name__ == '__main__': raise NotImplementedError raise AssertionError zope.proxy-4.3.3/.travis.yml0000644000175000017500000000651713562322312015027 0ustar mgmg00000000000000language: python env: global: TWINE_USERNAME: zope.wheelbuilder TWINE_PASSWORD: secure: "BWyhZtoO9jM3vatjfwdloThv7RY2p8AaN3D8T/8nEIupcgT5E6QKfLlIDibtlMNds2UU0q/HOJiSM/CwBsm5nzMke55m8OhfxfyHG+5TuBafwHtEkMyXe1VQtxnyB7Rlya2ylI9f4/3qXYqyLinBr3F+osE1g2nQmqQL2tpNmRA=" python: - 2.7 - 3.5 - 3.6 - 3.7 - 3.8 - pypy - pypy3 jobs: include: - name: "Python: 2.7, pure (no C extensions)" python: "2.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.0' - name: Python 3.7 wheels for MacOS os: osx language: generic env: TERRYFY_PYTHON='macpython 3.7.0' before_install: - | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then git clone https://github.com/MacPython/terryfy source terryfy/travis_tools.sh get_python_environment $TERRYFY_PYTHON venv fi install: - pip install -U pip - pip install -U setuptools - pip install -U coverage coveralls # NB: let's install . (zope.proxy) first separately, because we have a nasty # dependency loop: .[test] wants zope.security that setup_requires zope.proxy # (and setup_requires is broken on Mac OS Python 3.5 due to TLS version # compatibility issues that pip knows how to work around, but setuptools # don't). - pip install -e . - pip install -e .[test,docs] script: - python --version - coverage run -m zope.testrunner --test-path=src - sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html - coverage run -a -m sphinx -b doctest -d docs/_build/doctrees docs docs/_build/doctest - python setup.py bdist_wheel after_success: - coveralls - | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then # macpython 3.5 doesn't support recent TLS protocols which causes twine # upload to fail, so we use the system Python to run twine /usr/bin/python -m ensurepip --user /usr/bin/python -m pip install --user -U pip /usr/bin/python -m pip install --user -U -I twine /usr/bin/python -m twine check dist/* if [[ $TRAVIS_TAG ]]; then /usr/bin/python -m twine upload --skip-existing dist/* fi fi - | if [[ -n "$DOCKER_IMAGE" ]]; then pip install twine twine check wheelhouse/* if [[ $TRAVIS_TAG ]]; then twine upload --skip-existing wheelhouse/* fi fi notifications: email: false cache: pip before_cache: - rm -f $HOME/.cache/pip/log/debug.log zope.proxy-4.3.3/CHANGES.rst0000644000175000017500000001512313562322312014511 0ustar mgmg00000000000000Changes ======= 4.3.3 (2019-11-11) ------------------ - Add support for Python 3.8. - Drop support for Python 3.4. 4.3.2 (2019-07-12) ------------------ - Fix error handling in ``ProxyBase.__setattr__``: any the exception raised by ``PyString_AsString``/``PyUnicode_AsUTF8`` would be silently swallowed up and ignored. See `issue 31 `_. 4.3.1 (2018-08-09) ------------------ - Simplify the internal C handling of attribute names in ``__getattribute__`` and ``__setattr__``. - Make building the C extension optional. We still attempt to build it on supported platforms, but we allow it to fail in case of a missing compiler or headers. See `issue 26 `_. - Test the PURE_PYTHON environment and PyPy3 on Travis CI. - Add support for Python 3.7. 4.3.0 (2017-09-13) ------------------ - Fix a potential rare crash when deallocating proxies. See `issue 20 `_. - Drop support for Python 3.3. - Drop support for "python setup.py test". - 100% test coverage. - Fix indexing pure-Python proxies with slices under Python 3, and restore the use of ``__getslice__`` (if implemented by the target's type) under Python 2. Previously, pure-Python proxies would fail with an AttributeError when given a slice on Python 3, and on Python 2, a custom ``__getslice__`` was ignored. See `issue 21 `_. 4.2.1 (2017-04-23) ------------------ - Make the pure-Python implementation of ``sameProxiedObjects`` handle ``zope.security`` proxies. See `issue 15 `_. - Add support for Python 3.6. 4.2.0 (2016-05-05) ------------------ - Correctly strip ``zope.security`` proxies in ``removeAllProxies``. See `issue 13 `_. - Avoid poisoning the user's global wheel cache when testing ``PURE_PYTHON`` environments under ``tox``, - Drop support for Python 2.6 and 3.2. - Add support for Python 3.5. 4.1.6 (2015-06-02) ------------------ - Make subclasses of ProxyBase properly delegate ``__module__`` to the wrapped object. This fixes some ``zope.interface`` lookups under PyPy. - Make the pure-Python implementation of ProxyBase properly report the ``zope.interface`` interfaces implemented by builtin types like ``list``. This fixes some ``zope.interface`` lookups under PyPy. 4.1.5 (2015-05-19) ------------------ - Make the C implementation proxy ``__unicode__`` correctly. - Make the C implementation use the standard methods to proxy ``int`` and ``float``. - Make the pure Python implementation handle descriptors defined in subclasses like the C version. See https://github.com/zopefoundation/zope.proxy/issues/5. 4.1.4 (2014-03-19) ------------------ - Add support for Python 3.4. - Update ``bootstrap.py`` to version 2.2. 4.1.3 (2013-03-12) ------------------ - Fix interface object introspection in PyPy. For some reason PyPy makes attributes available despite the restrictive ``__slots__`` declaration. - Add a bunch of tests surrounding interface lookup and adaptation. 4.1.2 (2013-03-11) ------------------ - Make ``PyProxyBase.__iter__()`` return the result of ``PyProxyBase._wrapped.__iter__`` if available, otherwise falling back to Python internals. The previous implementation always created a generator. - In ``PyProxyBase.__setattr__()``, allow setting of properties on the proxy itself. This is needed to properly allow proxy extensions as was evidenced int he ``zope.security.decorator`` module. 4.1.1 (2012-12-31) ------------------ - Fleshed out PyPI Trove classifiers. 4.1.0 (2012-12-19) ------------------ - Enable compilation of dependent modules under Py3k. - Replace use of ``PyCObject`` APIs with equivalent ``PyCapsule`` APIs, except under Python 2.6. N.B. This change is an ABI incompatibility under Python 2.7: extensions built under Python 2.7 against 4.0.x versions of ``zope.proxy`` must be rebuilt. 4.0.1 (2012-11-21) ------------------ - Add support for Python 3.3. 4.0.0 (2012-06-06) ------------------ - Add support for PyPy. N.B.: the C extension is *not* built under PyPy. - Add a pure-Python reference / fallback implementations of ``zope.proxy.ProxyBase`` and the proxy module API functions. N.B.: the pure-Python proxy implements all regular features of ``ProxyBase``; however, it does not exclude access to the wrapped object in the same way that the C version does. If you need that information hiding (e.g., to implement security sandboxing), you still need to use the C version. - Add support for continuous integration using ``tox`` and ``jenkins``. - 100% unit test coverage. - Add Sphinx documentation: moved doctest examples to API reference. - Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies). - Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs ``nose`` and ``coverage``). - Replace deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Drop support for Python 2.4 and 2.5. - Add Python 3.2 support. 3.6.1 (2010-07-06) ------------------ - Make tests compatible with Python 2.7. 3.6.0 (2010-04-30) ------------------ - Remove test extra and the remaining dependency on zope.testing. - Remove use of 'zope.testing.doctestunit' in favor of stdlib's 'doctest. 3.5.0 (2009/01/31) ------------------ - Add support to bootstrap on Jython. - Use ``zope.container`` instead of ``zope.app.container``. 3.4.2 (2008/07/27) ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.4.1 (2008/06/24) ------------------ - Bug: Update ``setup.py`` script to conform to common layout. Also updated some of the fields. - Bug: Honor pre-cooked indices for tuples and lists in the ``__getslice__()`` and ``__setslice__()`` methods. See http://docs.python.org/ref/sequence-methods.html. 3.4.0 (2007/07/12) ------------------ - Feature: Add a ``decorator`` module that supports declaring interfaces on proxies that get blended with the interfaces of the things they proxy. 3.3.0 (2006/12/20) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope 3.3.0 release. 3.2.0 (2006/01/05) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope 3.2.0 release. 3.0.0 (2004/11/07) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope X3.0.0 release. zope.proxy-4.3.3/COPYRIGHT.txt0000644000175000017500000000004013562322312015010 0ustar mgmg00000000000000Zope Foundation and Contributorszope.proxy-4.3.3/LICENSE.txt0000644000175000017500000000402613562322312014532 0ustar mgmg00000000000000Zope Public License (ZPL) Version 2.1 A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zope.proxy-4.3.3/MANIFEST.in0000644000175000017500000000045013562322312014442 0ustar mgmg00000000000000include *.rst include *.txt include *.py include tox.ini include buildout.cfg include .travis.yml include .coveragerc recursive-include docs * recursive-include src * global-exclude *.dll global-exclude *.pyc global-exclude *.pyo global-exclude *.so # added by check_manifest.py include *.yml zope.proxy-4.3.3/PKG-INFO0000644000175000017500000002560313562322312014010 0ustar mgmg00000000000000Metadata-Version: 2.1 Name: zope.proxy Version: 4.3.3 Summary: Generic Transparent Proxies Home-page: http://github.com/zopefoundation/zope.proxy Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ``zope.proxy`` ============== .. image:: https://img.shields.io/pypi/v/zope.proxy.svg :target: https://pypi.python.org/pypi/zope.proxy/ :alt: Latest Version .. image:: https://travis-ci.org/zopefoundation/zope.proxy.svg?branch=master :target: https://travis-ci.org/zopefoundation/zope.proxy .. image:: https://readthedocs.org/projects/zopeproxy/badge/?version=latest :target: http://zopeproxy.readthedocs.org/en/latest/ :alt: Documentation Status Proxies are special objects which serve as mostly-transparent wrappers around another object, intervening in the apparent behavior of the wrapped object only when necessary to apply the policy (e.g., access checking, location brokering, etc.) for which the proxy is responsible. zope.proxy is implemented via a C extension module, which lets it do things like lie about its own ``__class__`` that are difficult in pure Python (and were completely impossible before metaclasses). It also proxies all the internal slots (such as ``__int__``/``__str__``/``__add__``). Complete documentation is at https://zopeproxy.readthedocs.io Changes ======= 4.3.3 (2019-11-11) ------------------ - Add support for Python 3.8. - Drop support for Python 3.4. 4.3.2 (2019-07-12) ------------------ - Fix error handling in ``ProxyBase.__setattr__``: any the exception raised by ``PyString_AsString``/``PyUnicode_AsUTF8`` would be silently swallowed up and ignored. See `issue 31 `_. 4.3.1 (2018-08-09) ------------------ - Simplify the internal C handling of attribute names in ``__getattribute__`` and ``__setattr__``. - Make building the C extension optional. We still attempt to build it on supported platforms, but we allow it to fail in case of a missing compiler or headers. See `issue 26 `_. - Test the PURE_PYTHON environment and PyPy3 on Travis CI. - Add support for Python 3.7. 4.3.0 (2017-09-13) ------------------ - Fix a potential rare crash when deallocating proxies. See `issue 20 `_. - Drop support for Python 3.3. - Drop support for "python setup.py test". - 100% test coverage. - Fix indexing pure-Python proxies with slices under Python 3, and restore the use of ``__getslice__`` (if implemented by the target's type) under Python 2. Previously, pure-Python proxies would fail with an AttributeError when given a slice on Python 3, and on Python 2, a custom ``__getslice__`` was ignored. See `issue 21 `_. 4.2.1 (2017-04-23) ------------------ - Make the pure-Python implementation of ``sameProxiedObjects`` handle ``zope.security`` proxies. See `issue 15 `_. - Add support for Python 3.6. 4.2.0 (2016-05-05) ------------------ - Correctly strip ``zope.security`` proxies in ``removeAllProxies``. See `issue 13 `_. - Avoid poisoning the user's global wheel cache when testing ``PURE_PYTHON`` environments under ``tox``, - Drop support for Python 2.6 and 3.2. - Add support for Python 3.5. 4.1.6 (2015-06-02) ------------------ - Make subclasses of ProxyBase properly delegate ``__module__`` to the wrapped object. This fixes some ``zope.interface`` lookups under PyPy. - Make the pure-Python implementation of ProxyBase properly report the ``zope.interface`` interfaces implemented by builtin types like ``list``. This fixes some ``zope.interface`` lookups under PyPy. 4.1.5 (2015-05-19) ------------------ - Make the C implementation proxy ``__unicode__`` correctly. - Make the C implementation use the standard methods to proxy ``int`` and ``float``. - Make the pure Python implementation handle descriptors defined in subclasses like the C version. See https://github.com/zopefoundation/zope.proxy/issues/5. 4.1.4 (2014-03-19) ------------------ - Add support for Python 3.4. - Update ``bootstrap.py`` to version 2.2. 4.1.3 (2013-03-12) ------------------ - Fix interface object introspection in PyPy. For some reason PyPy makes attributes available despite the restrictive ``__slots__`` declaration. - Add a bunch of tests surrounding interface lookup and adaptation. 4.1.2 (2013-03-11) ------------------ - Make ``PyProxyBase.__iter__()`` return the result of ``PyProxyBase._wrapped.__iter__`` if available, otherwise falling back to Python internals. The previous implementation always created a generator. - In ``PyProxyBase.__setattr__()``, allow setting of properties on the proxy itself. This is needed to properly allow proxy extensions as was evidenced int he ``zope.security.decorator`` module. 4.1.1 (2012-12-31) ------------------ - Fleshed out PyPI Trove classifiers. 4.1.0 (2012-12-19) ------------------ - Enable compilation of dependent modules under Py3k. - Replace use of ``PyCObject`` APIs with equivalent ``PyCapsule`` APIs, except under Python 2.6. N.B. This change is an ABI incompatibility under Python 2.7: extensions built under Python 2.7 against 4.0.x versions of ``zope.proxy`` must be rebuilt. 4.0.1 (2012-11-21) ------------------ - Add support for Python 3.3. 4.0.0 (2012-06-06) ------------------ - Add support for PyPy. N.B.: the C extension is *not* built under PyPy. - Add a pure-Python reference / fallback implementations of ``zope.proxy.ProxyBase`` and the proxy module API functions. N.B.: the pure-Python proxy implements all regular features of ``ProxyBase``; however, it does not exclude access to the wrapped object in the same way that the C version does. If you need that information hiding (e.g., to implement security sandboxing), you still need to use the C version. - Add support for continuous integration using ``tox`` and ``jenkins``. - 100% unit test coverage. - Add Sphinx documentation: moved doctest examples to API reference. - Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies). - Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs ``nose`` and ``coverage``). - Replace deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Drop support for Python 2.4 and 2.5. - Add Python 3.2 support. 3.6.1 (2010-07-06) ------------------ - Make tests compatible with Python 2.7. 3.6.0 (2010-04-30) ------------------ - Remove test extra and the remaining dependency on zope.testing. - Remove use of 'zope.testing.doctestunit' in favor of stdlib's 'doctest. 3.5.0 (2009/01/31) ------------------ - Add support to bootstrap on Jython. - Use ``zope.container`` instead of ``zope.app.container``. 3.4.2 (2008/07/27) ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.4.1 (2008/06/24) ------------------ - Bug: Update ``setup.py`` script to conform to common layout. Also updated some of the fields. - Bug: Honor pre-cooked indices for tuples and lists in the ``__getslice__()`` and ``__setslice__()`` methods. See http://docs.python.org/ref/sequence-methods.html. 3.4.0 (2007/07/12) ------------------ - Feature: Add a ``decorator`` module that supports declaring interfaces on proxies that get blended with the interfaces of the things they proxy. 3.3.0 (2006/12/20) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope 3.3.0 release. 3.2.0 (2006/01/05) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope 3.2.0 release. 3.0.0 (2004/11/07) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope X3.0.0 release. Keywords: proxy generic transparent Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Framework :: Zope :: 3 Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Provides-Extra: docs Provides-Extra: test zope.proxy-4.3.3/README.rst0000644000175000017500000000213113562322312014371 0ustar mgmg00000000000000``zope.proxy`` ============== .. image:: https://img.shields.io/pypi/v/zope.proxy.svg :target: https://pypi.python.org/pypi/zope.proxy/ :alt: Latest Version .. image:: https://travis-ci.org/zopefoundation/zope.proxy.svg?branch=master :target: https://travis-ci.org/zopefoundation/zope.proxy .. image:: https://readthedocs.org/projects/zopeproxy/badge/?version=latest :target: http://zopeproxy.readthedocs.org/en/latest/ :alt: Documentation Status Proxies are special objects which serve as mostly-transparent wrappers around another object, intervening in the apparent behavior of the wrapped object only when necessary to apply the policy (e.g., access checking, location brokering, etc.) for which the proxy is responsible. zope.proxy is implemented via a C extension module, which lets it do things like lie about its own ``__class__`` that are difficult in pure Python (and were completely impossible before metaclasses). It also proxies all the internal slots (such as ``__int__``/``__str__``/``__add__``). Complete documentation is at https://zopeproxy.readthedocs.io zope.proxy-4.3.3/appveyor.yml0000644000175000017500000000233513562322312015300 0ustar mgmg00000000000000environment: global: TWINE_USERNAME: zope.wheelbuilder TWINE_PASSWORD: secure: UcdTh6W78cRLVGfKRFoa5A== matrix: - python: 27 - python: 27-x64 - python: 35 - python: 35-x64 - python: 36 - python: 36-x64 - python: 37 - python: 37-x64 - python: 38 - python: 38-x64 install: - "SET PATH=C:\\Python%PYTHON%;c:\\Python%PYTHON%\\scripts;%PATH%" - ps: | $env:PYTHON = "C:\\Python${env:PYTHON}" if (-not (Test-Path $env:PYTHON)) { curl -o install_python.ps1 https://raw.githubusercontent.com/matthew-brett/multibuild/11a389d78892cf90addac8f69433d5e22bfa422a/install_python.ps1 .\install_python.ps1 } - ps: if (-not (Test-Path $env:PYTHON)) { throw "No $env:PYTHON" } - echo "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 > "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64\vcvars64.bat" - pip install -e . build_script: - pip install wheel - python -W ignore setup.py -q bdist_wheel test_script: - python setup.py test -q artifacts: - path: 'dist\*.whl' name: wheel deploy_script: - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE) { pip install twine; twine upload --skip-existing dist/* } deploy: on zope.proxy-4.3.3/bootstrap.py0000644000175000017500000001644213562322312015303 0ustar mgmg00000000000000############################################################################## # # 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) zope.proxy-4.3.3/buildout.cfg0000644000175000017500000000032413562322312015214 0ustar mgmg00000000000000[buildout] parts = test test-wo-zope-security develop = . [test] recipe = zc.recipe.testrunner eggs = zope.proxy[testing] [test-wo-zope-security] recipe = zc.recipe.testrunner eggs = zope.proxy zope.proxy-4.3.3/docs/0000755000175000017500000000000013562322312013635 5ustar mgmg00000000000000zope.proxy-4.3.3/docs/Makefile0000644000175000017500000001271013562322312015276 0ustar mgmg00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/zopeproxy.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zopeproxy.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/zopeproxy" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zopeproxy" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." zope.proxy-4.3.3/docs/_static/0000755000175000017500000000000013562322312015263 5ustar mgmg00000000000000zope.proxy-4.3.3/docs/_static/.gitignore0000644000175000017500000000000013562322312017241 0ustar mgmg00000000000000zope.proxy-4.3.3/docs/api.rst0000644000175000017500000000447713562322312015154 0ustar mgmg00000000000000:mod:`zope.proxy` API ===================== :mod:`zope.proxy.interfaces` ---------------------------- .. automodule:: zope.proxy.interfaces .. autointerface:: IProxyIntrospection :members: :member-order: bysource :mod:`zope.proxy` ----------------- .. automodule:: zope.proxy :members: :mod:`zope.proxy.decorator` --------------------------- .. automodule:: zope.proxy.decorator .. doctest:: >>> from zope.interface import Interface >>> from zope.interface import directlyProvides >>> from zope.interface import implementer >>> class I1(Interface): ... pass >>> class I2(Interface): ... pass >>> class I3(Interface): ... pass >>> class I4(Interface): ... pass >>> from zope.proxy.decorator import SpecificationDecoratorBase >>> @implementer(I1) ... class D1(SpecificationDecoratorBase): ... pass >>> @implementer(I2) ... class D2(SpecificationDecoratorBase): ... pass >>> @implementer(I3) ... class X(object): ... pass >>> x = X() >>> directlyProvides(x, I4) Interfaces of X are ordered with the directly-provided interfaces first. .. doctest:: >>> from zope.interface import providedBy >>> [interface.getName() for interface in list(providedBy(x))] ['I4', 'I3'] When we decorate objects, what order should the interfaces come in? One could argue that decorators are less specific, so they should come last. .. doctest:: >>> [interface.getName() for interface in list(providedBy(D1(x)))] ['I4', 'I3', 'I1'] >>> [interface.getName() for interface in list(providedBy(D2(D1(x))))] ['I4', 'I3', 'I1', 'I2'] SpecificationDecorators also work with old-style classes: .. doctest:: >>> @implementer(I3) ... class X: ... pass >>> x = X() >>> directlyProvides(x, I4) >>> [interface.getName() for interface in list(providedBy(x))] ['I4', 'I3'] >>> [interface.getName() for interface in list(providedBy(D1(x)))] ['I4', 'I3', 'I1'] >>> [interface.getName() for interface in list(providedBy(D2(D1(x))))] ['I4', 'I3', 'I1', 'I2'] .. autoclass:: DecoratorSpecificationDescriptor :members: .. autoclass:: SpecificationDecoratorBase zope.proxy-4.3.3/docs/conf.py0000644000175000017500000001745013562322312015143 0ustar mgmg00000000000000# -*- coding: utf-8 -*- # # zope.proxy documentation build configuration file, created by # sphinx-quickstart on Mon Jun 4 15:12:17 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', 'repoze.sphinx.autointerface', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'zope.proxy' copyright = u'2012, Zope Foundation Contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '4.0' # The full version, including alpha/beta/rc tags. release = '4.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'zopeproxydoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'zopeproxy.tex', u'zope.proxy Documentation', u'Zope Foundation Contributors', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'zopeproxy', u'zope.proxy Documentation', [u'Zope Foundation Contributors'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'zopeproxy', u'zope.proxy Documentation', u'Zope Foundation Contributors', 'zopeproxy', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' zope.proxy-4.3.3/docs/hacking.rst0000644000175000017500000002112113562322312015770 0ustar mgmg00000000000000Hacking on :mod:`zope.proxy` ============================ Getting the Code ################ The main repository for :mod:`zope.proxy` is in the Zope Foundation Github repository: https://github.com/zopefoundation/zope.proxy You can get a read-only checkout from there: .. code-block:: sh $ git clone https://github.com/zopefoundation/zope.proxy.git or fork it and get a writeable checkout of your fork: .. code-block:: sh $ git clone git@github.com/jrandom/zope.proxy.git The project also mirrors the trunk from the Github repository as a Bazaar branch on Launchpad: https://code.launchpad.net/zope.proxy You can branch the trunk from there using Bazaar: .. code-block:: sh $ bzr branch lp:zope.proxy Working in a ``virtualenv`` ########################### Installing ---------- If you use the ``virtualenv`` package to create lightweight Python development environments, you can run the tests using nothing more than the ``python`` binary in a virtualenv. First, create a scratch environment: .. code-block:: sh $ /path/to/virtualenv --no-site-packages /tmp/hack-zope.proxy Next, get this package registered as a "development egg" in the environment: .. code-block:: sh $ /tmp/hack-zope.proxy/bin/python setup.py develop Running the tests ----------------- Then, you canrun the tests using the build-in ``setuptools`` testrunner: .. code-block:: sh $ /tmp/hack-zope.proxy/bin/python setup.py test -q ................................................................................................................................................... ---------------------------------------------------------------------- Ran 147 tests in 0.010s OK If you have the :mod:`nose` package installed in the virtualenv, you can use its testrunner too: .. code-block:: sh $ /tmp/hack-zope.proxy/bin/easy_install nose ... $ /tmp/hack-zope.proxy/bin/nosetests ..................................................................................................................................................... ---------------------------------------------------------------------- Ran 149 tests in 0.107s OK If you have the :mod:`coverage` pacakge installed in the virtualenv, you can see how well the tests cover the code: .. code-block:: sh $ /tmp/hack-zope.proxy/bin/easy_install nose coverage ... $ /tmp/hack-zope.proxy/bin/nosetests --with coverage ..................................................................................................................................................... Name Stmts Miss Cover Missing ----------------------------------------------------- zope.proxy 271 0 100% zope.proxy._compat 2 0 100% zope.proxy.decorator 18 0 100% zope.proxy.interfaces 10 0 100% ----------------------------------------------------- TOTAL 301 0 100% ---------------------------------------------------------------------- Ran 149 tests in 0.148s OK Building the documentation -------------------------- :mod:`zope.proxy` uses the nifty :mod:`Sphinx` documentation system for building its docs. Using the same virtualenv you set up to run the tests, you can build the docs: .. code-block:: sh $ /tmp/hack-zope.proxy/bin/easy_install Sphinx ... $ cd docs $ /tmp/hack-zope.proxy/bin/sphinx-build \ -b html -d _build/doctrees . _build/html ... build succeeded. You can also test the code snippets in the documentation: .. code-block:: sh $ /tmp/hack-zope.proxy/bin/sphinx-build \ -b doctest -d _build/doctrees . _build/doctest ... running tests... Document: api ------------- 1 items passed all tests: 23 tests in default 23 tests in 1 items. 23 passed and 0 failed. Test passed. Document: narr -------------- 1 items passed all tests: 37 tests in default 37 tests in 1 items. 37 passed and 0 failed. Test passed. Doctest summary =============== 60 tests 0 failures in tests 0 failures in setup code 0 failures in cleanup code build succeeded. Using :mod:`zc.buildout` ######################## Setting up the buildout ----------------------- :mod:`zope.proxy` ships with its own :file:`buildout.cfg` file and :file:`bootstrap.py` for setting up a development buildout: .. code-block:: sh $ /path/to/python2.6 bootstrap.py ... Generated script '.../bin/buildout' $ bin/buildout Develop: '/home/jrandom/projects/Zope/BTK/event/.' ... Generated script '.../bin/test'. Running the tests ----------------- You can now run the tests: .. code-block:: sh $ bin/test --all Running zope.testing.testrunner.layer.UnitTests tests: Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds. Ran 147 tests with 0 failures and 0 errors in 0.000 seconds. Tearing down left over layers: Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds. Using :mod:`tox` ################ Running Tests on Multiple Python Versions ----------------------------------------- `tox `_ is a Python-based test automation tool designed to run tests against multiple Python versions. It creates a ``virtualenv`` for each configured version, installs the current package and configured dependencies into each ``virtualenv``, and then runs the configured commands. :mod:`zope.proxy` configures the following :mod:`tox` environments via its ``tox.ini`` file: - The ``py26``, ``py27``, ``py33``, ``py34``, and ``pypy`` environments builds a ``virtualenv`` with ``pypy``, installs :mod:`zope.proxy` and dependencies, and runs the tests via ``python setup.py test -q``. - The ``coverage`` environment builds a ``virtualenv`` with ``python2.6``, installs :mod:`zope.proxy`, installs :mod:`nose` and :mod:`coverage`, and runs ``nosetests`` with statement coverage. - The ``docs`` environment builds a virtualenv with ``python2.6``, installs :mod:`zope.proxy`, installs ``Sphinx`` and dependencies, and then builds the docs and exercises the doctest snippets. This example requires that you have a working ``python2.6`` on your path, as well as installing ``tox``: .. code-block:: sh $ tox -e py26 GLOB sdist-make: .../zope.proxy/setup.py py26 sdist-reinst: .../zope.proxy/.tox/dist/zope.proxy-4.0.2dev.zip py26 runtests: commands[0] ... ---------------------------------------------------------------------- Ran 147 tests in 0.000s OK ___________________________________ summary ____________________________________ py26: commands succeeded congratulations :) Running ``tox`` with no arguments runs all the configured environments, including building the docs and testing their snippets: .. code-block:: sh $ tox GLOB sdist-make: .../zope.proxy/setup.py py26 sdist-reinst: .../zope.proxy/.tox/dist/zope.proxy-4.0.2dev.zip py26 runtests: commands[0] ... Doctest summary =============== 60 tests 0 failures in tests 0 failures in setup code 0 failures in cleanup code build succeeded. ___________________________________ summary ____________________________________ py26: commands succeeded py27: commands succeeded py32: commands succeeded pypy: commands succeeded coverage: commands succeeded docs: commands succeeded congratulations :) Contributing to :mod:`zope.proxy` ################################# Submitting a Bug Report ----------------------- :mod:`zope.proxy` tracks its bugs on Github: https://github.com/zopefoundation/zope.proxy/issues Please submit bug reports and feature requests there. Sharing Your Changes -------------------- .. note:: Please ensure that all tests are passing before you submit your code. If possible, your submission should include new tests for new features or bug fixes, although it is possible that you may have tested your new code by updating existing tests. If have made a change you would like to share, the best route is to fork the Githb repository, check out your fork, make your changes on a branch in your fork, and push it. You can then submit a pull request from your branch: https://github.com/zopefoundation/zope.proxy/pulls If you branched the code from Launchpad using Bazaar, you have another option: you can "push" your branch to Launchpad: .. code-block:: sh $ bzr push lp:~jrandom/zope.proxy/cool_feature After pushing your branch, you can link it to a bug report on Github, or request that the maintainers merge your branch using the Launchpad "merge request" feature. zope.proxy-4.3.3/docs/index.rst0000644000175000017500000000030613562322312015475 0ustar mgmg00000000000000:mod:`zope.proxy` ================= Contents: .. toctree:: :maxdepth: 2 narr api hacking Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` zope.proxy-4.3.3/docs/make.bat0000644000175000017500000001175613562322312015254 0ustar mgmg00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\zopeproxy.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\zopeproxy.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end zope.proxy-4.3.3/docs/narr.rst0000644000175000017500000000615313562322312015336 0ustar mgmg00000000000000:mod:`zope.proxy` Narrative Documentation ========================================= Subclassing :class:`ProxyBase` ------------------------------ If you subclass a proxy, instances of the subclass have access to data defined in the class, including descriptors. Your subclass instances don't get instance dictionaries, but they can have slots. .. doctest:: >>> from zope.proxy import ProxyBase >>> class MyProxy(ProxyBase): ... __slots__ = 'x', 'y' ... ... def f(self): ... return self.x >>> l = [1, 2, 3] >>> p = MyProxy(l) You can use attributes defined by the class, including slots: .. doctest:: >>> p.x = 'x' >>> p.x 'x' >>> p.f() 'x' You can also use attributes of the proxied object: .. doctest:: >>> p [1, 2, 3] >>> p.pop() 3 >>> p [1, 2] Using get descriptors in proxy classes -------------------------------------- A non-data descriptor in a proxy class doesn't hide an attribute on a proxied object or prevent writing the attribute. .. doctest:: >>> class ReadDescr(object): ... def __get__(self, i, c): ... return 'read' >>> from zope.proxy import ProxyBase >>> class MyProxy(ProxyBase): ... __slots__ = () ... ... z = ReadDescr() ... q = ReadDescr() >>> class MyOb: ... q = 1 >>> o = MyOb() >>> p = MyProxy(o) >>> p.q 1 >>> p.z 'read' >>> p.z = 1 >>> o.z, p.z (1, 1) Marking proxy attributes as non-overridable ------------------------------------------- Normally, methods defined in proxies are overridden by methods of proxied objects. This applies to all non-data descriptors. The non_overridable function can be used to convert a non-data descriptor to a data descriptor that disallows writes. This function can be used as a decorator to make functions defined in proxy classes take precedence over functions defined in proxied objects. .. doctest:: >>> from zope.proxy import ProxyBase >>> from zope.proxy import non_overridable >>> class MyProxy(ProxyBase): ... __slots__ = () ... ... @non_overridable ... def foo(self): ... return 'MyProxy foo' >>> class MyOb: ... def foo(self): ... return 'MyOb foo' >>> o = MyOb() >>> p = MyProxy(o) >>> p.foo() 'MyProxy foo' Changing the proxied object --------------------------- .. doctest:: >>> from zope.proxy import ProxyBase >>> from zope.proxy import setProxiedObject, getProxiedObject >>> class C(object): ... pass >>> c1 = C() >>> c2 = C() >>> p = ProxyBase(c1) `setProxiedObject()` allows us to change the object a proxy refers to, returning the previous referent: .. doctest:: >>> old = setProxiedObject(p, c2) >>> old is c1 True >>> getProxiedObject(p) is c2 True The first argument to `setProxiedObject()` must be a proxy; other objects cause it to raise an exception: .. doctest:: >>> try: ... setProxiedObject(c1, None) ... except TypeError: ... print("TypeError raised") ... else: ... print("Expected TypeError not raised") TypeError raised zope.proxy-4.3.3/rtd.txt0000644000175000017500000000003413562322312014234 0ustar mgmg00000000000000repoze.sphinx.autointerface zope.proxy-4.3.3/setup.cfg0000644000175000017500000000035013562322312014524 0ustar mgmg00000000000000[nosetests] nocapture = 1 cover-package = zope.proxy cover-erase = 1 with-doctest = 0 where = src [aliases] dev = develop easy_install zope.proxy[testing] docs = easy_install zope.proxy[docs] [egg_info] tag_build = tag_date = 0 zope.proxy-4.3.3/setup.py0000644000175000017500000001076013562322312014423 0ustar mgmg00000000000000############################################################################## # # Copyright (c) 2006-2008 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. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.proxy package """ from __future__ import print_function import os import platform from distutils.errors import CCompilerError from distutils.errors import DistutilsExecError from distutils.errors import DistutilsPlatformError from setuptools import Extension from setuptools.command.build_ext import build_ext from setuptools import setup from setuptools import Feature 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) except DistutilsPlatformError as e: self._unavailable(e) def build_extension(self, ext): try: build_ext.build_extension(self, ext) except (CCompilerError, DistutilsExecError, OSError) as e: self._unavailable(e) def _unavailable(self, e): print('*' * 80) print("""WARNING: An optional code optimization (C extension) could not be compiled. Optimizations for this package will not be available!""") print() print(e) print('*' * 80) def read(*rnames): with open(os.path.join(os.path.dirname(__file__), *rnames)) as f: return f.read() Cwrapper = Feature( "C wrapper", standard=True, headers=[os.path.join('src', 'zope', 'proxy', 'proxy.h')], ext_modules=[ Extension( "zope.proxy._zope_proxy_proxy", [os.path.join('src', 'zope', 'proxy', "_zope_proxy_proxy.c")], ), ], ) # PyPy won't build the extension. is_pypy = platform.python_implementation() == 'PyPy' if is_pypy: features = {} else: features = {'Cwrapper': Cwrapper} setup(name='zope.proxy', version='4.3.3', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Generic Transparent Proxies', long_description=( read('README.rst') + '\n\n' + read('CHANGES.rst') ), url='http://github.com/zopefoundation/zope.proxy', license='ZPL 2.1', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Framework :: Zope :: 3', 'Natural Language :: English', 'Operating System :: OS Independent', ], keywords='proxy generic transparent', packages=['zope', 'zope.proxy'], package_dir={'': 'src'}, namespace_packages=['zope'], cmdclass={ 'build_ext': optional_build_ext, }, features=features, install_requires=[ 'zope.interface', 'setuptools', ], include_package_data=True, zip_safe=False, extras_require={ 'test': [ 'zope.security', # We have a circular dependency for testing 'zope.testrunner', ], 'docs': [ 'Sphinx', 'repoze.sphinx.autointerface', ], }, ) zope.proxy-4.3.3/src/0000755000175000017500000000000013562322312013474 5ustar mgmg00000000000000zope.proxy-4.3.3/src/zope/0000755000175000017500000000000013562322312014451 5ustar mgmg00000000000000zope.proxy-4.3.3/src/zope/__init__.py0000644000175000017500000000007013562322312016557 0ustar mgmg00000000000000__import__('pkg_resources').declare_namespace(__name__) zope.proxy-4.3.3/src/zope/proxy/0000755000175000017500000000000013562322312015632 5ustar mgmg00000000000000zope.proxy-4.3.3/src/zope/proxy/__init__.py0000644000175000017500000004012213562322312017742 0ustar mgmg00000000000000############################################################################## # # Copyright (c) 2003 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. # ############################################################################## """More convenience functions for dealing with proxies. """ import operator import os import pickle import sys from zope.interface import moduleProvides from zope.proxy.interfaces import IProxyIntrospection moduleProvides(IProxyIntrospection) __all__ = tuple(IProxyIntrospection) def ProxyIterator(p): yield p while isProxy(p): p = getProxiedObject(p) yield p _MARKER = object() def _WrapperType_Lookup(type_, name): """ Looks up information in class dictionaries in MRO order, ignoring the proxy type itself. Returns the first found object, or _MARKER """ for base in type_.mro(): if base is AbstractPyProxyBase: continue res = base.__dict__.get(name, _MARKER) if res is not _MARKER: return res return _MARKER def _get_wrapped(self): """ Helper method to access the wrapped object. """ return super(AbstractPyProxyBase, self).__getattribute__('_wrapped') class _EmptyInterfaceDescriptor(object): """A descriptor for the attributes used on the class by the Python implementation of `zope.interface`. When wrapping builtin types, these descriptors prevent the objects we find in the AbstractPyProxyBase from being used. """ def __get__(self, inst, klass): raise AttributeError() def __set__(self, inst, value): raise TypeError() def __delete__(self, inst): pass def __iter__(self): return self def __next__(self): raise StopIteration() next = __next__ class _ProxyMetaclass(type): # The metaclass is applied after the class definition # for Py2/Py3 compatibility. __implemented__ = _EmptyInterfaceDescriptor() class AbstractPyProxyBase(object): """ A reference implementation that cannot be instantiated. Most users will want to use :class:`PyProxyBase`. This type is intended to be used in multiple-inheritance scenarios, where another super class already has defined ``__slots__``. In order to subclass both that class and this class, you must include the ``_wrapped`` value in your own ``__slots__`` definition (or else you will get the infamous TypeError: "multiple bases have instance lay-out conflicts") """ __slots__ = () def __new__(cls, value=None): # Some subclasses (zope.security.proxy) fail to pass the object inst = super(AbstractPyProxyBase, cls).__new__(cls) inst._wrapped = value return inst def __init__(self, obj): self._wrapped = obj def __call__(self, *args, **kw): return self._wrapped(*args, **kw) def __repr__(self): return repr(self._wrapped) def __str__(self): return str(self._wrapped) def __unicode__(self): return unicode(self._wrapped) def __reduce__(self): # pragma: no cover (__reduce_ex__ prevents normal) raise pickle.PicklingError def __reduce_ex__(self, proto): raise pickle.PicklingError # Rich comparison protocol def __lt__(self, other): return self._wrapped < other def __le__(self, other): return self._wrapped <= other def __eq__(self, other): return self._wrapped == other def __ne__(self, other): return self._wrapped != other def __gt__(self, other): return self._wrapped > other def __ge__(self, other): return self._wrapped >= other def __nonzero__(self): return bool(self._wrapped) __bool__ = __nonzero__ # Python3 compat def __hash__(self): return hash(self._wrapped) # Attribute protocol def __getattribute__(self, name): # Try to avoid accessing the _wrapped value until we need to. # We don't know how subclasses may be storing it # (e.g., persistent subclasses) if name == '_wrapped': return _get_wrapped(self) if name in ('__class__', '__module__'): # __class__ and __module__ are special cased in the C # implementation, because we will always find them on the # type of this object if we are being subclassed return getattr(_get_wrapped(self), name) if name in ('__reduce__', '__reduce_ex__'): # These things we specifically override and no one # can stop us, not even a subclass return object.__getattribute__(self, name) # First, look for descriptors in this object's type type_self = type(self) descriptor = _WrapperType_Lookup(type_self, name) if descriptor is _MARKER: # Nothing in the class, go straight to the wrapped object return getattr(_get_wrapped(self), name) if hasattr(descriptor, '__get__'): if not hasattr(descriptor, '__set__'): # Non-data-descriptor: call through to the wrapped object # to see if it's there try: return getattr(_get_wrapped(self), name) except AttributeError: pass # Data-descriptor on this type. Call it return descriptor.__get__(self, type_self) return descriptor def __getattr__(self, name): return getattr(self._wrapped, name) def __setattr__(self, name, value): if name == '_wrapped': return super(AbstractPyProxyBase, self).__setattr__(name, value) # First, look for descriptors in this object's type type_self = type(self) descriptor = _WrapperType_Lookup(type_self, name) if descriptor is _MARKER or not hasattr(descriptor, '__set__'): # Nothing in the class that's a descriptor, # go straight to the wrapped object return setattr(self._wrapped, name, value) return object.__setattr__(self, name, value) def __delattr__(self, name): if name == '_wrapped': raise AttributeError() delattr(self._wrapped, name) # Container protocols def __len__(self): return len(self._wrapped) def __getslice__(self, start, stop): try: getslice = type(self._wrapped).__getslice__ except AttributeError: return self.__getitem__(slice(start, stop)) return getslice(self._wrapped, start, stop) def __getitem__(self, key): return self._wrapped[key] def __setslice__(self, start, stop, value): try: setslice = type(self._wrapped).__setslice__ except AttributeError: return self.__setitem__(slice(start, stop), value) return setslice(self._wrapped, start, stop, value) def __setitem__(self, key, value): self._wrapped[key] = value def __delitem__(self, key): del self._wrapped[key] def __iter__(self): # This handles a custom __iter__ and generator support at the same time. return iter(self._wrapped) def next(self): # Called when we wrap an iterator itself. return self._wrapped.next() def __next__(self): # pragma: no cover Python3 return self._wrapped.__next__() # Python 2.7 won't let the C wrapper support __reversed__ :( #def __reversed__(self): # return reversed(self._wrapped) def __contains__(self, item): return item in self._wrapped # Numeric protocol: unary operators def __neg__(self): return -self._wrapped def __pos__(self): return +self._wrapped def __abs__(self): return abs(self._wrapped) def __invert__(self): return ~self._wrapped # Numeric protocol: unary conversions def __complex__(self): return complex(self._wrapped) def __int__(self): return int(self._wrapped) def __long__(self): return long(self._wrapped) def __float__(self): return float(self._wrapped) def __oct__(self): return oct(self._wrapped) def __hex__(self): return hex(self._wrapped) def __index__(self): return operator.index(self._wrapped) # Numeric protocol: binary coercion def __coerce__(self, other): left, right = coerce(self._wrapped, other) if left == self._wrapped and type(left) is type(self._wrapped): left = self return left, right # Numeric protocol: binary arithmetic operators def __add__(self, other): return self._wrapped + other def __sub__(self, other): return self._wrapped - other def __mul__(self, other): return self._wrapped * other def __floordiv__(self, other): return self._wrapped // other def __truediv__(self, other): # pragma: no cover # Only one of __truediv__ and __div__ is meaningful at any one time. return self._wrapped / other def __div__(self, other): # pragma: no cover # Only one of __truediv__ and __div__ is meaningful at any one time. return self._wrapped / other def __mod__(self, other): return self._wrapped % other def __divmod__(self, other): return divmod(self._wrapped, other) def __pow__(self, other, modulus=None): if modulus is None: return pow(self._wrapped, other) return pow(self._wrapped, other, modulus) def __radd__(self, other): return other + self._wrapped def __rsub__(self, other): return other - self._wrapped def __rmul__(self, other): return other * self._wrapped def __rfloordiv__(self, other): return other // self._wrapped def __rtruediv__(self, other): # pragma: no cover # Only one of __rtruediv__ and __rdiv__ is meaningful at any one time. return other / self._wrapped def __rdiv__(self, other): # pragma: no cover # Only one of __rtruediv__ and __rdiv__ is meaningful at any one time. return other / self._wrapped def __rmod__(self, other): return other % self._wrapped def __rdivmod__(self, other): return divmod(other, self._wrapped) def __rpow__(self, other, modulus=None): if modulus is None: return pow(other, self._wrapped) # We can't actually get here, because we can't lie about our type() return pow(other, self._wrapped, modulus) # pragma: no cover # Numeric protocol: binary bitwise operators def __lshift__(self, other): return self._wrapped << other def __rshift__(self, other): return self._wrapped >> other def __and__(self, other): return self._wrapped & other def __xor__(self, other): return self._wrapped ^ other def __or__(self, other): return self._wrapped | other def __rlshift__(self, other): return other << self._wrapped def __rrshift__(self, other): return other >> self._wrapped def __rand__(self, other): return other & self._wrapped def __rxor__(self, other): return other ^ self._wrapped def __ror__(self, other): return other | self._wrapped # Numeric protocol: binary in-place operators def __iadd__(self, other): self._wrapped += other return self def __isub__(self, other): self._wrapped -= other return self def __imul__(self, other): self._wrapped *= other return self def __idiv__(self, other): # pragma: no cover # Only one of __itruediv__ and __idiv__ is meaningful at any one time. self._wrapped /= other return self def __itruediv__(self, other): # pragma: no cover # Only one of __itruediv__ and __idiv__ is meaningful at any one time. self._wrapped /= other return self def __ifloordiv__(self, other): self._wrapped //= other return self def __imod__(self, other): self._wrapped %= other return self def __ilshift__(self, other): self._wrapped <<= other return self def __irshift__(self, other): self._wrapped >>= other return self def __iand__(self, other): self._wrapped &= other return self def __ixor__(self, other): self._wrapped ^= other return self def __ior__(self, other): self._wrapped |= other return self def __ipow__(self, other, modulus=None): if modulus is None: self._wrapped **= other else: # pragma: no cover # There is no syntax which triggers in-place pow w/ modulus self._wrapped = pow(self._wrapped, other, modulus) return self AbstractPyProxyBase = _ProxyMetaclass(str('AbstractPyProxyBase'), (), dict(AbstractPyProxyBase.__dict__)) class PyProxyBase(AbstractPyProxyBase): """Reference implementation. """ __slots__ = ('_wrapped', ) def py_getProxiedObject(obj): if isinstance(obj, PyProxyBase): return obj._wrapped return obj def py_setProxiedObject(obj, new_value): if not isinstance(obj, PyProxyBase): raise TypeError('Not a proxy') old, obj._wrapped = obj._wrapped, new_value return old def py_isProxy(obj, klass=None): if klass is None: klass = PyProxyBase return isinstance(obj, klass) def py_sameProxiedObjects(lhs, rhs): while isinstance(lhs, PyProxyBase): lhs = super(PyProxyBase, lhs).__getattribute__('_wrapped') while isinstance(rhs, PyProxyBase): rhs = super(PyProxyBase, rhs).__getattribute__('_wrapped') return lhs is rhs def py_queryProxy(obj, klass=None, default=None): if klass is None: klass = PyProxyBase while obj is not None and not isinstance(obj, klass): obj = getattr(obj, '_wrapped', None) if obj is not None: return obj return default def py_queryInnerProxy(obj, klass=None, default=None): if klass is None: klass = PyProxyBase found = [] while obj is not None: if isinstance(obj, klass): found.append(obj) # stack obj = getattr(obj, '_wrapped', None) if found: return found[-1] return default def py_removeAllProxies(obj): while isinstance(obj, PyProxyBase): obj = super(PyProxyBase, obj).__getattribute__('_wrapped') return obj _c_available = False if 'PURE_PYTHON' not in os.environ: try: from zope.proxy._zope_proxy_proxy import ProxyBase as _c_available except ImportError: # pragma: no cover pass class PyNonOverridable(object): "Deprecated, only for BWC." def __init__(self, method_desc): # pragma: no cover PyPy self.desc = method_desc if _c_available: # Python API: not used in this module from zope.proxy._zope_proxy_proxy import ProxyBase from zope.proxy._zope_proxy_proxy import getProxiedObject from zope.proxy._zope_proxy_proxy import setProxiedObject from zope.proxy._zope_proxy_proxy import isProxy from zope.proxy._zope_proxy_proxy import sameProxiedObjects from zope.proxy._zope_proxy_proxy import queryProxy from zope.proxy._zope_proxy_proxy import queryInnerProxy from zope.proxy._zope_proxy_proxy import removeAllProxies # API for proxy-using C extensions. from zope.proxy._zope_proxy_proxy import _CAPI else: # pragma: no cover # no C extension available, fall back ProxyBase = PyProxyBase getProxiedObject = py_getProxiedObject setProxiedObject = py_setProxiedObject isProxy = py_isProxy sameProxiedObjects = py_sameProxiedObjects queryProxy = py_queryProxy queryInnerProxy = py_queryInnerProxy removeAllProxies = py_removeAllProxies def non_overridable(func): return property(lambda self: func.__get__(self)) zope.proxy-4.3.3/src/zope/proxy/_compat.py0000644000175000017500000000005313562322312017624 0ustar mgmg00000000000000import sys PY3 = sys.version_info[0] >= 3 zope.proxy-4.3.3/src/zope/proxy/_zope_proxy_proxy.c0000644000175000017500000010011413562322312021611 0ustar mgmg00000000000000/*############################################################################ # # Copyright (c) 2004 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. # ############################################################################*/ /* * This file is also used as a really extensive macro in * ../container/_zope_container_contained.c. If you need to * change this file, you need to "svn copy" it to ../container/. * * This approach is taken to allow the sources for the two packages * to be compilable when the relative locations of these aren't * related in the same way as they are in a checkout. * * This will be revisited in the future, but works for now. */ #include "Python.h" #include "modsupport.h" #define PROXY_MODULE #include "proxy.h" static PyTypeObject ProxyType; #define Proxy_Check(wrapper) (PyObject_TypeCheck((wrapper), &ProxyType)) static PyObject * empty_tuple = NULL; #if PY_VERSION_HEX < 0x02070000 #define PyCapsule_New(pointer, name, destr) \ PyCObject_FromVoidPtr(pointer, destr) #endif // Compatibility with Python 2 #if PY_MAJOR_VERSION < 3 #define MOD_ERROR_VAL #define MOD_SUCCESS_VAL(val) #define MOD_INIT(name) void init##name(void) #define MOD_DEF(ob, name, doc, methods) \ ob = Py_InitModule3(name, methods, doc); #else #define MOD_ERROR_VAL NULL #define MOD_SUCCESS_VAL(val) val #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define MOD_DEF(ob, name, doc, methods) \ static struct PyModuleDef moduledef = { \ PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ ob = PyModule_Create(&moduledef); #endif /* * Slot methods. */ static PyObject * wrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *result = NULL; PyObject *object; if (PyArg_UnpackTuple(args, "__new__", 1, 1, &object)) { if (kwds != NULL && PyDict_Size(kwds) != 0) { PyErr_SetString(PyExc_TypeError, "proxy.__new__ does not accept keyword args"); return NULL; } result = PyType_GenericNew(type, args, kwds); if (result != NULL) { ProxyObject *wrapper = (ProxyObject *) result; Py_INCREF(object); wrapper->proxy_object = object; } } return result; } static int wrap_init(PyObject *self, PyObject *args, PyObject *kwds) { int result = -1; PyObject *object; if (PyArg_UnpackTuple(args, "__init__", 1, 1, &object)) { ProxyObject *wrapper = (ProxyObject *)self; if (kwds != NULL && PyDict_Size(kwds) != 0) { PyErr_SetString(PyExc_TypeError, "proxy.__init__ does not accept keyword args"); return -1; } /* If the object in this proxy is not the one we * received in args, replace it with the new one. */ if (wrapper->proxy_object != object) { PyObject *temp = wrapper->proxy_object; Py_INCREF(object); wrapper->proxy_object = object; Py_DECREF(temp); } result = 0; } return result; } static int wrap_traverse(PyObject *self, visitproc visit, void *arg) { PyObject *ob = Proxy_GET_OBJECT(self); if (ob != NULL) return visit(ob, arg); else return 0; } static int wrap_clear(PyObject *self) { ProxyObject *proxy = (ProxyObject *)self; PyObject *temp = proxy->proxy_object; if (temp != NULL) { proxy->proxy_object = NULL; Py_DECREF(temp); } return 0; } static PyObject * wrap_richcompare(PyObject* self, PyObject* other, int op) { if (Proxy_Check(self)) { self = Proxy_GET_OBJECT(self); } else { other = Proxy_GET_OBJECT(other); } return PyObject_RichCompare(self, other, op); } static PyObject * wrap_iter(PyObject *self) { return PyObject_GetIter(Proxy_GET_OBJECT(self)); } static PyObject * wrap_iternext(PyObject *self) { return PyIter_Next(Proxy_GET_OBJECT(self)); } static void wrap_dealloc(PyObject *self) { PyObject_GC_UnTrack(self); (void) wrap_clear(self); self->ob_type->tp_free(self); } /* A variant of _PyType_Lookup that doesn't look in ProxyType. * * If argument search_wrappertype is nonzero, we can look in WrapperType. */ PyObject * WrapperType_Lookup(PyTypeObject *type, PyObject *name) { int i, n; PyObject *mro, *res, *base, *dict; /* Look in tp_dict of types in MRO */ mro = type->tp_mro; /* If mro is NULL, the type is either not yet initialized by PyType_Ready(), or already cleared by type_clear(). Either way the safest thing to do is to return NULL. */ if (mro == NULL) return NULL; assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro) - 1; /* We don't want to look at the last item, which is object. */ for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(mro, i); if (((PyTypeObject *)base) != &ProxyType) { #if PY_MAJOR_VERSION < 3 if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else #endif { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } assert(dict && PyDict_Check(dict)); res = PyDict_GetItem(dict, name); if (res != NULL) return res; } } return NULL; } static PyObject * wrap_getattro(PyObject *self, PyObject *name) { PyObject *wrapped; PyObject *descriptor; PyObject *res = NULL; const char *name_as_string; int maybe_special_name; #if PY_MAJOR_VERSION < 3 name_as_string = PyString_AsString(name); #else name_as_string = PyUnicode_AsUTF8(name); #endif if (name_as_string == NULL) { return NULL; } wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to get attribute '%s'", name_as_string); goto finally; } maybe_special_name = name_as_string[0] == '_' && name_as_string[1] == '_'; if (!(maybe_special_name && (strcmp(name_as_string, "__class__") == 0 || strcmp(name_as_string, "__module__") == 0))) { descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL) { if (descriptor->ob_type->tp_descr_get != NULL #if PY_MAJOR_VERSION < 3 // Always true in Python 3 && PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) #endif ){ if (descriptor->ob_type->tp_descr_set == NULL) { res = PyObject_GetAttr(wrapped, name); if (res != NULL) goto finally; if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); else goto finally; } res = descriptor->ob_type->tp_descr_get( descriptor, self, (PyObject *)self->ob_type); } else { Py_INCREF(descriptor); res = descriptor; } goto finally; } } res = PyObject_GetAttr(wrapped, name); finally: return res; } static int wrap_setattro(PyObject *self, PyObject *name, PyObject *value) { PyObject *wrapped; PyObject *descriptor; const char *name_as_string; int res = -1; #if PY_MAJOR_VERSION < 3 name_as_string = PyString_AsString(name); #else name_as_string = PyUnicode_AsUTF8(name); #endif if (name_as_string == NULL) { goto finally; } descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL #if PY_MAJOR_VERSION < 3 // This is always true in Python 3 (I think) && PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) #endif && descriptor->ob_type->tp_descr_set != NULL) { res = descriptor->ob_type->tp_descr_set(descriptor, self, value); goto finally; } wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to set attribute '%s'", name_as_string); goto finally; } res = PyObject_SetAttr(wrapped, name, value); finally: return res; } static int wrap_print(PyObject *wrapper, FILE *fp, int flags) { return PyObject_Print(Proxy_GET_OBJECT(wrapper), fp, flags); } static PyObject * wrap_str(PyObject *wrapper) { return PyObject_Str(Proxy_GET_OBJECT(wrapper)); } static PyObject * wrap_repr(PyObject *wrapper) { return PyObject_Repr(Proxy_GET_OBJECT(wrapper)); } #if PY_MAJOR_VERSION < 3 static int wrap_compare(PyObject *wrapper, PyObject *v) { return PyObject_Compare(Proxy_GET_OBJECT(wrapper), v); } #endif static long wrap_hash(PyObject *self) { return PyObject_Hash(Proxy_GET_OBJECT(self)); } static PyObject * wrap_call(PyObject *self, PyObject *args, PyObject *kw) { if (kw) return PyEval_CallObjectWithKeywords(Proxy_GET_OBJECT(self), args, kw); else return PyObject_CallObject(Proxy_GET_OBJECT(self), args); } /* * Number methods. */ static PyObject * call_int(PyObject *self) { #if PY_MAJOR_VERSION < 3 return PyNumber_Int(self); #else return PyNumber_Long(self); #endif } #if PY_MAJOR_VERSION < 3 // Python 3 has no long, oct or hex methods. static PyObject * call_long(PyObject *self) { return PyNumber_Long(self); } static PyObject * call_oct(PyObject *self) { PyNumberMethods *nb = self->ob_type->tp_as_number; if (nb == NULL || nb->nb_oct== NULL) { PyErr_SetString(PyExc_TypeError, "object can't be converted to oct"); return NULL; } return nb->nb_oct(self); } static PyObject * call_hex(PyObject *self) { PyNumberMethods *nb = self->ob_type->tp_as_number; if (nb == NULL || nb->nb_hex == NULL) { PyErr_SetString(PyExc_TypeError, "object can't be converted to hex"); return NULL; } return nb->nb_hex(self); } #endif static PyObject * call_index(PyObject *self) { return PyNumber_Index(self); } static PyObject * call_float(PyObject *self) { return PyNumber_Float(self); } static PyObject * call_ipow(PyObject *self, PyObject *other) { /* PyNumber_InPlacePower has three args. How silly. :-) */ return PyNumber_InPlacePower(self, other, Py_None); } #if PY_MAJOR_VERSION < 3 static PyObject * call_unicode(PyObject *self) { return PyObject_Unicode(self); } #endif typedef PyObject *(*function1)(PyObject *); static PyObject * check1(ProxyObject *self, char *opname, function1 operation) { PyObject *result = NULL; result = operation(Proxy_GET_OBJECT(self)); #if 0 if (result != NULL) /* ??? create proxy for result? */ ; #endif return result; } static PyObject * check2(PyObject *self, PyObject *other, char *opname, char *ropname, binaryfunc operation) { PyObject *result = NULL; PyObject *object; if (Proxy_Check(self)) { object = Proxy_GET_OBJECT(self); result = operation(object, other); } else if (Proxy_Check(other)) { object = Proxy_GET_OBJECT(other); result = operation(self, object); } else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } #if 0 if (result != NULL) /* ??? create proxy for result? */ ; #endif return result; } static PyObject * check2i(ProxyObject *self, PyObject *other, char *opname, binaryfunc operation) { PyObject *result = NULL; PyObject *object = Proxy_GET_OBJECT(self); result = operation(object, other); if (result == object) { /* If the operation was really carried out inplace, don't create a new proxy, but use the old one. */ Py_INCREF(self); Py_DECREF(object); result = (PyObject *)self; } #if 0 else if (result != NULL) /* ??? create proxy for result? */ ; #endif return result; } #define UNOP(NAME, CALL) \ static PyObject *wrap_##NAME(PyObject *self) \ { return check1((ProxyObject *)self, "__"#NAME"__", CALL); } #define BINOP(NAME, CALL) \ static PyObject *wrap_##NAME(PyObject *self, PyObject *other) \ { return check2(self, other, "__"#NAME"__", "__r"#NAME"__", CALL); } #define INPLACE(NAME, CALL) \ static PyObject *wrap_i##NAME(PyObject *self, PyObject *other) \ { return check2i((ProxyObject *)self, other, "__i"#NAME"__", CALL); } BINOP(add, PyNumber_Add) BINOP(sub, PyNumber_Subtract) BINOP(mul, PyNumber_Multiply) #if PY_MAJOR_VERSION < 3 // Python 3 doesn't support the old integer division BINOP(div, PyNumber_Divide) #endif BINOP(mod, PyNumber_Remainder) BINOP(divmod, PyNumber_Divmod) static PyObject * wrap_pow(PyObject *self, PyObject *other, PyObject *modulus) { PyObject *result = NULL; PyObject *object; if (Proxy_Check(self)) { object = Proxy_GET_OBJECT(self); result = PyNumber_Power(object, other, modulus); } else if (Proxy_Check(other)) { object = Proxy_GET_OBJECT(other); result = PyNumber_Power(self, object, modulus); } else if (modulus != NULL && Proxy_Check(modulus)) { object = Proxy_GET_OBJECT(modulus); result = PyNumber_Power(self, other, modulus); } else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return result; } BINOP(lshift, PyNumber_Lshift) BINOP(rshift, PyNumber_Rshift) BINOP(and, PyNumber_And) BINOP(xor, PyNumber_Xor) BINOP(or, PyNumber_Or) #if PY_MAJOR_VERSION < 3 // Coercion is gone in Python 3 static int wrap_coerce(PyObject **p_self, PyObject **p_other) { PyObject *self = *p_self; PyObject *other = *p_other; PyObject *object; PyObject *left; PyObject *right; int r; assert(Proxy_Check(self)); object = Proxy_GET_OBJECT(self); left = object; right = other; r = PyNumber_CoerceEx(&left, &right); if (r != 0) return r; /* Now left and right have been INCREF'ed. Any new value that comes out is proxied; any unchanged value is left unchanged. */ if (left == object) { /* Keep the old proxy */ Py_INCREF(self); Py_DECREF(left); left = self; } #if 0 else { /* ??? create proxy for left? */ } if (right != other) { /* ??? create proxy for right? */ } #endif *p_self = left; *p_other = right; return 0; } #endif UNOP(neg, PyNumber_Negative) UNOP(pos, PyNumber_Positive) UNOP(abs, PyNumber_Absolute) UNOP(invert, PyNumber_Invert) UNOP(int, call_int) UNOP(float, call_float) #if PY_MAJOR_VERSION < 3 // Python 3 has no long, oct or hex methods UNOP(long, call_long) UNOP(oct, call_oct) UNOP(hex, call_hex) #endif INPLACE(add, PyNumber_InPlaceAdd) INPLACE(sub, PyNumber_InPlaceSubtract) INPLACE(mul, PyNumber_InPlaceMultiply) #if PY_MAJOR_VERSION < 3 // The old integer division operator is gone in Python 3 INPLACE(div, PyNumber_InPlaceDivide) #endif INPLACE(mod, PyNumber_InPlaceRemainder) INPLACE(pow, call_ipow) INPLACE(lshift, PyNumber_InPlaceLshift) INPLACE(rshift, PyNumber_InPlaceRshift) INPLACE(and, PyNumber_InPlaceAnd) INPLACE(xor, PyNumber_InPlaceXor) INPLACE(or, PyNumber_InPlaceOr) BINOP(floordiv, PyNumber_FloorDivide) BINOP(truediv, PyNumber_TrueDivide) INPLACE(floordiv, PyNumber_InPlaceFloorDivide) INPLACE(truediv, PyNumber_InPlaceTrueDivide) UNOP(index, call_index) #if PY_MAJOR_VERSION < 3 // Python 3 has no __unicode__ method UNOP(unicode, call_unicode) #endif static int wrap_nonzero(PyObject *self) { return PyObject_IsTrue(Proxy_GET_OBJECT(self)); } /* * Sequence methods */ static Py_ssize_t wrap_length(PyObject *self) { return PyObject_Length(Proxy_GET_OBJECT(self)); } static PyObject * wrap_slice(PyObject *self, Py_ssize_t start, Py_ssize_t end) { /* * Note that we have arrived here through PySequence_GetSlice * once already, which on Python 2 adjusted indices. We can't call * PySequence_GetSlice again or they will be wrong. So we directly * call the slice method the type provides. */ PyObject *obj = Proxy_GET_OBJECT(self); #if PY_MAJOR_VERSION < 3 PySequenceMethods *m; m = obj->ob_type->tp_as_sequence; if (m && m->sq_slice) { return m->sq_slice(obj, start, end); } #endif return PySequence_GetSlice(obj, start, end); } static int wrap_ass_slice(PyObject *self, Py_ssize_t i, Py_ssize_t j, PyObject *value) { PyObject *obj = Proxy_GET_OBJECT(self); if (PyList_Check(obj)) { return PyList_SetSlice(obj, i, j, value); } else { return PySequence_SetSlice(obj, i, j, value); } } static int wrap_contains(PyObject *self, PyObject *value) { return PySequence_Contains(Proxy_GET_OBJECT(self), value); } /* * Mapping methods */ static PyObject * wrap_getitem(PyObject *wrapper, PyObject *v) { return PyObject_GetItem(Proxy_GET_OBJECT(wrapper), v); } static int wrap_setitem(PyObject *self, PyObject *key, PyObject *value) { if (value == NULL) return PyObject_DelItem(Proxy_GET_OBJECT(self), key); else return PyObject_SetItem(Proxy_GET_OBJECT(self), key, value); } /* * Normal methods */ static char reduce__doc__[] = "__reduce__()\n" "Raise an exception; this prevents proxies from being picklable by\n" "default, even if the underlying object is picklable."; static PyObject * wrap_reduce(PyObject *self) { PyObject *pickle_error = NULL; PyObject *pickle = PyImport_ImportModule("pickle"); if (pickle == NULL) PyErr_Clear(); else { pickle_error = PyObject_GetAttrString(pickle, "PicklingError"); if (pickle_error == NULL) PyErr_Clear(); } if (pickle_error == NULL) { pickle_error = PyExc_RuntimeError; Py_INCREF(pickle_error); } PyErr_SetString(pickle_error, "proxy instances cannot be pickled"); Py_DECREF(pickle_error); return NULL; } static PyNumberMethods wrap_as_number = { wrap_add, /* nb_add */ wrap_sub, /* nb_subtract */ wrap_mul, /* nb_multiply */ #if PY_MAJOR_VERSION < 3 wrap_div, /* nb_divide */ #endif wrap_mod, /* nb_remainder */ wrap_divmod, /* nb_divmod */ wrap_pow, /* nb_power */ wrap_neg, /* nb_negative */ wrap_pos, /* nb_positive */ wrap_abs, /* nb_absolute */ wrap_nonzero, /* nb_nonzero */ wrap_invert, /* nb_invert */ wrap_lshift, /* nb_lshift */ wrap_rshift, /* nb_rshift */ wrap_and, /* nb_and */ wrap_xor, /* nb_xor */ wrap_or, /* nb_or */ #if PY_MAJOR_VERSION < 3 wrap_coerce, /* nb_coerce */ #endif wrap_int, /* nb_int */ #if PY_MAJOR_VERSION < 3 wrap_long, /* nb_long */ #else 0, /* formerly known as nb_long */ #endif wrap_float, /* nb_float */ #if PY_MAJOR_VERSION < 3 wrap_oct, /* nb_oct */ wrap_hex, /* nb_hex */ #endif /* Added in release 2.0 */ /* These require the Py_TPFLAGS_HAVE_INPLACEOPS flag */ wrap_iadd, /* nb_inplace_add */ wrap_isub, /* nb_inplace_subtract */ wrap_imul, /* nb_inplace_multiply */ #if PY_MAJOR_VERSION < 3 wrap_idiv, /* nb_inplace_divide */ #endif wrap_imod, /* nb_inplace_remainder */ (ternaryfunc)wrap_ipow, /* nb_inplace_power */ wrap_ilshift, /* nb_inplace_lshift */ wrap_irshift, /* nb_inplace_rshift */ wrap_iand, /* nb_inplace_and */ wrap_ixor, /* nb_inplace_xor */ wrap_ior, /* nb_inplace_or */ /* Added in release 2.2 */ /* These require the Py_TPFLAGS_HAVE_CLASS flag */ wrap_floordiv, /* nb_floor_divide */ wrap_truediv, /* nb_true_divide */ wrap_ifloordiv, /* nb_inplace_floor_divide */ wrap_itruediv, /* nb_inplace_true_divide */ wrap_index, /* nb_index */ }; static PySequenceMethods wrap_as_sequence = { wrap_length, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ wrap_slice, /* sq_slice */ 0, /* sq_ass_item */ wrap_ass_slice, /* sq_ass_slice */ wrap_contains, /* sq_contains */ }; static PyMappingMethods wrap_as_mapping = { wrap_length, /* mp_length */ wrap_getitem, /* mp_subscript */ wrap_setitem, /* mp_ass_subscript */ }; static PyMethodDef wrap_methods[] = { {"__reduce__", (PyCFunction)wrap_reduce, METH_NOARGS, reduce__doc__}, #if PY_MAJOR_VERSION < 3 {"__unicode__", (PyCFunction)wrap_unicode, METH_NOARGS, "" }, #endif {NULL, NULL}, }; /* * Note that the numeric methods are not supported. This is primarily * because of the way coercion-less operations are performed with * new-style numbers; since we can't tell which side of the operation * is 'self', we can't ensure we'd unwrap the right thing to perform * the actual operation. We also can't afford to just unwrap both * sides the way weakrefs do, since we don't know what semantics will * be associated with the wrapper itself. */ static PyTypeObject ProxyType = { PyVarObject_HEAD_INIT(NULL, 0) "zope.proxy.ProxyBase", sizeof(ProxyObject), 0, wrap_dealloc, /* tp_dealloc */ wrap_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ #if PY_MAJOR_VERSION < 3 wrap_compare, /* tp_compare */ #else 0, /* tp_reserved */ #endif wrap_repr, /* tp_repr */ &wrap_as_number, /* tp_as_number */ &wrap_as_sequence, /* tp_as_sequence */ &wrap_as_mapping, /* tp_as_mapping */ wrap_hash, /* tp_hash */ wrap_call, /* tp_call */ wrap_str, /* tp_str */ wrap_getattro, /* tp_getattro */ wrap_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ #if PY_MAJOR_VERSION < 3 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE, /* tp_flags */ #else // Py_TPFLAGS_CHECKTYPES is always true in Python 3 and removed. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ #endif 0, /* tp_doc */ wrap_traverse, /* tp_traverse */ wrap_clear, /* tp_clear */ wrap_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ wrap_iter, /* tp_iter */ wrap_iternext, /* tp_iternext */ wrap_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ wrap_init, /* tp_init */ 0, /* tp_alloc */ wrap_new, /* tp_new */ 0, /*PyObject_GC_Del,*/ /* tp_free */ }; static PyObject * create_proxy(PyObject *object) { PyObject *result = NULL; PyObject *args; args = PyTuple_New(1); if (args != NULL) { Py_INCREF(object); PyTuple_SET_ITEM(args, 0, object); result = PyObject_CallObject((PyObject *)&ProxyType, args); Py_DECREF(args); } return result; } static int api_check(PyObject *obj) { return obj ? Proxy_Check(obj) : 0; } static PyObject * api_create(PyObject *object) { if (object == NULL) { PyErr_SetString(PyExc_ValueError, "cannot create proxy around NULL"); return NULL; } return create_proxy(object); } static PyObject * api_getobject(PyObject *proxy) { if (proxy == NULL) { PyErr_SetString(PyExc_RuntimeError, "cannot pass NULL to ProxyAPI.getobject()"); return NULL; } if (Proxy_Check(proxy)) return Proxy_GET_OBJECT(proxy); else { PyErr_Format(PyExc_TypeError, "expected proxy object, got %s", proxy->ob_type->tp_name); return NULL; } } static ProxyInterface wrapper_capi = { &ProxyType, api_check, api_create, api_getobject, }; static PyObject *api_object = NULL; static char getobject__doc__[] = "getProxiedObject(proxy) --> object\n" "\n" "Get the underlying object for proxy, or the object itself, if it is\n" "not a proxy."; static PyObject * wrapper_getobject(PyObject *unused, PyObject *obj) { if (Proxy_Check(obj)) obj = Proxy_GET_OBJECT(obj); if (obj == NULL) obj = Py_None; Py_INCREF(obj); return obj; } static char setobject__doc__[] = "setProxiedObject(proxy, object) --> object\n" "\n" "Set the underlying object for proxy, returning the old proxied object.\n" "Raises TypeError if proxy is not a proxy.\n"; static PyObject * wrapper_setobject(PyObject *unused, PyObject *args) { PyObject *proxy; PyObject *object; PyObject *result = NULL; if (PyArg_ParseTuple(args, "O!O:setProxiedObject", &ProxyType, &proxy, &object)) { result = Proxy_GET_OBJECT(proxy); Py_INCREF(object); ((ProxyObject *) proxy)->proxy_object = object; } return result; } static char isProxy__doc__[] = "Check whether the given object is a proxy\n" "\n" "If proxytype is not None, checkes whether the object is\n" "proxied by the given proxytype.\n" ; static PyObject * wrapper_isProxy(PyObject *unused, PyObject *args) { PyObject *obj, *result; PyTypeObject *proxytype=&ProxyType; if (! PyArg_ParseTuple(args, "O|O!:isProxy", &obj, &PyType_Type, &proxytype) ) return NULL; while (obj && Proxy_Check(obj)) { if (PyObject_TypeCheck(obj, proxytype)) { result = Py_True; Py_INCREF(result); return result; } obj = Proxy_GET_OBJECT(obj); } result = Py_False; Py_INCREF(result); return result; } static char removeAllProxies__doc__[] = "removeAllProxies(proxy) --> object\n" "\n" "Get the proxied object with no proxies\n" "\n" "If obj is not a proxied object, return obj.\n" "\n" "The returned object has no proxies.\n" ; static PyObject * wrapper_removeAllProxies(PyObject *unused, PyObject *obj) { while (obj && Proxy_Check(obj)) obj = Proxy_GET_OBJECT(obj); if (obj == NULL) obj = Py_None; Py_INCREF(obj); return obj; } static char sameProxiedObjects__doc__[] = "Check whether two objects are the same or proxies of the same object"; static PyObject * wrapper_sameProxiedObjects(PyObject *unused, PyObject *args) { PyObject *ob1, *ob2; if (! PyArg_ParseTuple(args, "OO:sameProxiedObjects", &ob1, &ob2)) return NULL; while (ob1 && Proxy_Check(ob1)) ob1 = Proxy_GET_OBJECT(ob1); while (ob2 && Proxy_Check(ob2)) ob2 = Proxy_GET_OBJECT(ob2); if (ob1 == ob2) ob1 = Py_True; else ob1 = Py_False; Py_INCREF(ob1); return ob1; } static char queryProxy__doc__[] = "Look for a proxy of the given type around the object\n" "\n" "If no such proxy can be found, return the default.\n" ; static PyObject * wrapper_queryProxy(PyObject *unused, PyObject *args) { PyObject *obj, *result=Py_None; PyTypeObject *proxytype=&ProxyType; if (! PyArg_ParseTuple(args, "O|O!O:queryProxy", &obj, &PyType_Type, &proxytype, &result) ) return NULL; while (obj && Proxy_Check(obj)) { if (PyObject_TypeCheck(obj, proxytype)) { Py_INCREF(obj); return obj; } obj = Proxy_GET_OBJECT(obj); } Py_INCREF(result); return result; } static char queryInnerProxy__doc__[] = "Look for the inner-most proxy of the given type around the object\n" "\n" "If no such proxy can be found, return the default.\n" "\n" "If there is such a proxy, return the inner-most one.\n" ; static PyObject * wrapper_queryInnerProxy(PyObject *unused, PyObject *args) { PyObject *obj, *result=Py_None; PyTypeObject *proxytype=&ProxyType; if (! PyArg_ParseTuple(args, "O|O!O:queryInnerProxy", &obj, &PyType_Type, &proxytype, &result) ) return NULL; while (obj && Proxy_Check(obj)) { if (PyObject_TypeCheck(obj, proxytype)) result = obj; obj = Proxy_GET_OBJECT(obj); } Py_INCREF(result); return result; } /* Module initialization */ static char module___doc__[] = "Association between an object, a context object, and a dictionary.\n\ \n\ The context object and dictionary give additional context information\n\ associated with a reference to the basic object. The wrapper objects\n\ act as proxies for the original object."; static PyMethodDef module_functions[] = { {"getProxiedObject", wrapper_getobject, METH_O, getobject__doc__}, {"setProxiedObject", wrapper_setobject, METH_VARARGS, setobject__doc__}, {"isProxy", wrapper_isProxy, METH_VARARGS, isProxy__doc__}, {"sameProxiedObjects", wrapper_sameProxiedObjects, METH_VARARGS, sameProxiedObjects__doc__}, {"queryProxy", wrapper_queryProxy, METH_VARARGS, queryProxy__doc__}, {"queryInnerProxy", wrapper_queryInnerProxy, METH_VARARGS, queryInnerProxy__doc__}, {"removeAllProxies", wrapper_removeAllProxies, METH_O, removeAllProxies__doc__}, {NULL} }; MOD_INIT(_zope_proxy_proxy) { PyObject *m; MOD_DEF(m, "_zope_proxy_proxy", module___doc__, module_functions) if (m == NULL) return MOD_ERROR_VAL; if (empty_tuple == NULL) empty_tuple = PyTuple_New(0); ProxyType.tp_free = PyObject_GC_Del; if (PyType_Ready(&ProxyType) < 0) return MOD_ERROR_VAL; Py_INCREF(&ProxyType); PyModule_AddObject(m, "ProxyBase", (PyObject *)&ProxyType); if (api_object == NULL) { api_object = PyCapsule_New(&wrapper_capi, NULL, NULL); if (api_object == NULL) return MOD_ERROR_VAL; } Py_INCREF(api_object); PyModule_AddObject(m, "_CAPI", api_object); return MOD_SUCCESS_VAL(m); } zope.proxy-4.3.3/src/zope/proxy/decorator.py0000644000175000017500000000354113562322312020171 0ustar mgmg00000000000000############################################################################## # # Copyright (c) 2003 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. # ############################################################################## """Decorator support Decorators are proxies that are mostly transparent but that may provide additional features. """ __docformat__ = "reStructuredText" from zope.proxy import getProxiedObject, ProxyBase from zope.interface.declarations import ObjectSpecificationDescriptor from zope.interface.declarations import getObjectSpecification from zope.interface.declarations import ObjectSpecification from zope.interface import providedBy class DecoratorSpecificationDescriptor(ObjectSpecificationDescriptor): """Support for interface declarations on decorators """ def __get__(self, inst, cls=None): if inst is None: return getObjectSpecification(cls) else: provided = providedBy(getProxiedObject(inst)) # Use type rather than __class__ because inst is a proxy and # will return the proxied object's class. cls = type(inst) return ObjectSpecification(provided, cls) def __set__(self, inst, value): raise TypeError("Can't set __providedBy__ on a decorated object") class SpecificationDecoratorBase(ProxyBase): """Base class for a proxy that provides additional interfaces.""" __providedBy__ = DecoratorSpecificationDescriptor() zope.proxy-4.3.3/src/zope/proxy/interfaces.py0000644000175000017500000000414313562322312020331 0ustar mgmg00000000000000############################################################################## # # Copyright (c) 2001, 2002 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 # ############################################################################## """Proxy-related interfaces. """ from zope.interface import Interface class IProxyIntrospection(Interface): """Provides methods for indentifying proxies and extracting proxied objects """ def isProxy(obj, proxytype=None): """Check whether the given object is a proxy If proxytype is not None, checkes whether the object is proxied by the given proxytype. """ def sameProxiedObjects(ob1, ob2): """Check whether ob1 and ob2 are the same or proxies of the same object """ def getProxiedObject(obj): """Get the proxied Object If the object isn't proxied, then just return the object. """ def setProxiedObject(ob1, ob2): """Set the underlying object for ob1 to ob2, returning the old object. Raises TypeError if ob1 is not a proxy. """ def removeAllProxies(obj): """Get the proxied object with no proxies If obj is not a proxied object, return obj. The returned object has no proxies. """ def queryProxy(obj, proxytype, default=None): """Look for a proxy of the given type around the object If no such proxy can be found, return the default. """ def queryInnerProxy(obj, proxytype, default=None): """Look for the inner-most proxy of the given type around the object If no such proxy can be found, return the default. If there is such a proxy, return the inner-most one. """ zope.proxy-4.3.3/src/zope/proxy/proxy.h0000644000175000017500000000315713562322312017172 0ustar mgmg00000000000000#ifndef _proxy_H_ #define _proxy_H_ 1 typedef struct { PyObject_HEAD PyObject *proxy_object; } ProxyObject; #define Proxy_GET_OBJECT(ob) (((ProxyObject *)(ob))->proxy_object) typedef struct { PyTypeObject *proxytype; int (*check)(PyObject *obj); PyObject *(*create)(PyObject *obj); PyObject *(*getobject)(PyObject *proxy); } ProxyInterface; #ifndef PROXY_MODULE /* These are only defined in the public interface, and are not * available within the module implementation. There we use the * classic Python/C API only. */ static ProxyInterface *_proxy_api = NULL; static int Proxy_Import(void) { if (_proxy_api == NULL) { PyObject *m = PyImport_ImportModule("zope.proxy"); if (m != NULL) { PyObject *tmp = PyObject_GetAttrString(m, "_CAPI"); if (tmp != NULL) { #if PY_VERSION_HEX < 0x02070000 if (PyCObject_Check(tmp)) _proxy_api = (ProxyInterface *) PyCObject_AsVoidPtr(tmp); #else if (PyCapsule_CheckExact(tmp)) _proxy_api = (ProxyInterface *) PyCapsule_GetPointer(tmp, NULL); #endif Py_DECREF(tmp); } } } return (_proxy_api == NULL) ? -1 : 0; } #define ProxyType (*_proxy_api->proxytype) #define Proxy_Check(obj) (_proxy_api->check((obj))) #define Proxy_CheckExact(obj) ((obj)->ob_type == ProxyType) #define Proxy_New(obj) (_proxy_api->create((obj))) #define Proxy_GetObject(proxy) (_proxy_api->getobject((proxy))) #endif /* PROXY_MODULE */ #endif /* _proxy_H_ */ zope.proxy-4.3.3/src/zope/proxy/tests/0000755000175000017500000000000013562322312016774 5ustar mgmg00000000000000zope.proxy-4.3.3/src/zope/proxy/tests/__init__.py0000644000175000017500000000007513562322312021107 0ustar mgmg00000000000000# # This file is necessary to make this directory a package. zope.proxy-4.3.3/src/zope/proxy/tests/test_decorator.py0000644000175000017500000001252013562322312022367 0ustar mgmg00000000000000############################################################################## # # Copyright (c) 2003 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. # ############################################################################## """Test Harness """ import unittest class DecoratorSpecificationDescriptorTests(unittest.TestCase): def _getTargetClass(self): from zope.proxy.decorator import DecoratorSpecificationDescriptor return DecoratorSpecificationDescriptor def _makeOne(self): return self._getTargetClass()() def test___get___w_class(self): from zope.interface import Interface from zope.interface import implementer from zope.interface import provider class IContextFactory(Interface): pass class IContext(Interface): pass @provider(IContextFactory) @implementer(IContext) class Context(object): pass dsd = self._makeOne() self.assertEqual(list(dsd.__get__(None, Context)), [IContextFactory]) def test___get___w_inst_no_proxy(self): from zope.interface import Interface from zope.interface import implementer from zope.interface import provider class IContextFactory(Interface): pass class IContext(Interface): pass @provider(IContextFactory) @implementer(IContext) class Context(object): pass dsd = self._makeOne() self.assertEqual(list(dsd.__get__(Context(), None)), [IContext]) def test___get___w_inst_w_proxy(self): from zope.interface import Interface from zope.interface import implementer from zope.interface import provider from zope.proxy import ProxyBase class IContextFactory(Interface): pass class IContext(Interface): pass @provider(IContextFactory) @implementer(IContext) class Context(object): pass context = Context() proxy = ProxyBase(context) dsd = self._makeOne() self.assertEqual(list(dsd.__get__(proxy, None)), [IContext]) def test___get___w_inst_w_derived_proxy(self): from zope.interface import Interface from zope.interface import implementer from zope.interface import provider from zope.proxy import ProxyBase class IContextFactory(Interface): pass class IContext(Interface): pass @provider(IContextFactory) @implementer(IContext) class Context(object): pass class IProxyFactory(Interface): pass class IProxy(Interface): pass @provider(IProxyFactory) @implementer(IProxy) class Proxy(ProxyBase): pass context = Context() proxy = Proxy(context) dsd = self._makeOne() self.assertEqual(list(dsd.__get__(proxy, None)), [IContext, IProxy]) def test___set___not_allowed(self): from zope.interface import Interface from zope.interface import implementer class IFoo(Interface): pass @implementer(IFoo) class Foo(object): pass foo = Foo() dsd = self._makeOne() self.assertRaises(TypeError, dsd.__set__, foo, object()) class SpecificationDecoratorBaseTests(unittest.TestCase): def _getTargetClass(self): from zope.proxy.decorator import SpecificationDecoratorBase return SpecificationDecoratorBase def _makeOne(self, wrapped): return self._getTargetClass()(wrapped) def test_wrapped_instance(self): from zope.interface import Interface from zope.interface import implementer from zope.interface import providedBy class IFoo(Interface): pass @implementer(IFoo) class Foo(object): pass foo = Foo() proxy = self._makeOne(foo) self.assertEqual(list(providedBy(proxy)), list(providedBy(foo))) def test_proxy_that_provides_interface_as_well_as_wrapped(self): # If both the wrapper and the wrapped object provide # interfaces, the wrapper provides the sum from zope.interface import Interface from zope.interface import implementer from zope.interface import providedBy class IFoo(Interface): pass @implementer(IFoo) class Foo(object): from_foo = 1 class IWrapper(Interface): pass @implementer(IWrapper) class Proxy(self._getTargetClass()): pass foo = Foo() proxy = Proxy(foo) self.assertEqual(proxy.from_foo, 1) self.assertEqual(list(providedBy(proxy)), [IFoo,IWrapper]) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(DecoratorSpecificationDescriptorTests), unittest.makeSuite(SpecificationDecoratorBaseTests), )) zope.proxy-4.3.3/src/zope/proxy/tests/test_proxy.py0000644000175000017500000013173513562322312021600 0ustar mgmg00000000000000############################################################################## # # Copyright (c) 2003 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. # ############################################################################## """Test base proxy class. """ import unittest try: import zope.security except ImportError: # pragma: no cover _HAVE_ZOPE_SECURITY = False else: _HAVE_ZOPE_SECURITY = True from zope.proxy._compat import PY3 class ModuleConformanceCase(unittest.TestCase): def test_module_conforms_to_IProxyIntrospection(self): from zope.interface.verify import verifyObject import zope.proxy from zope.proxy.interfaces import IProxyIntrospection verifyObject(IProxyIntrospection, zope.proxy) class PyProxyBaseTestCase(unittest.TestCase): # Names of special methods getslice = '__getitem__' if PY3 else '__getslice__' setslice = '__setitem__' if PY3 else '__setslice__' def _getTargetClass(self): from zope.proxy import PyProxyBase return PyProxyBase def _makeOne(self, o): return self._getTargetClass()(o) def test_constructor(self): o = object() self.assertRaises(TypeError, self._makeOne, o, o) self.assertRaises(TypeError, self._makeOne, o, key='value') self.assertRaises(TypeError, self._makeOne, key='value') def test_subclass_constructor(self): class MyProxy(self._getTargetClass()): def __new__(cls, *args, **kwds): return super(MyProxy, cls).__new__(cls, *args, **kwds) def __init__(self, *args, **kwds): super(MyProxy, self).__init__(*args, **kwds) o1 = object() o2 = object() o = MyProxy((o1, o2)) self.assertEqual(o1, o[0]) self.assertEqual(o2, o[1]) self.assertRaises(TypeError, MyProxy, o1, o2) self.assertRaises(TypeError, MyProxy, o1, key='value') self.assertRaises(TypeError, MyProxy, key='value') # Check that are passed to __init__() overrides what's passed # to __new__(). class MyProxy2(self._getTargetClass()): def __new__(cls, *args, **kwds): return super(MyProxy2, cls).__new__(cls, 'value') proxy = MyProxy2('splat!') self.assertEqual(list(proxy), list('splat!')) class MyProxy3(MyProxy2): def __init__(self, arg): if list(self) != list('value'): raise AssertionError("list(self) != list('value')") super(MyProxy3, self).__init__('another') proxy = MyProxy3('notused') self.assertEqual(list(proxy), list('another')) def test_custom_int_to_int(self): class CustomClass(object): def __int__(self): return 42 proxy = self._makeOne(CustomClass()) self.assertEqual(42, int(proxy)) def test_string_to_float(self): proxy = self._makeOne("14") self.assertEqual(float("14"), float(proxy)) def test_incorrect_string_to_int(self): proxy = self._makeOne("") self.assertRaises(ValueError, int, proxy) def test_incorrect_string_to_float(self): proxy = self._makeOne("") self.assertRaises(ValueError, float, proxy) def test_custom_float_to_float(self): class CustomClass(object): def __float__(self): return 42.0 proxy = self._makeOne(CustomClass()) self.assertEqual(42.0, float(proxy)) @unittest.skipIf(PY3, "Gone in Py3") def test___unicode__of_unicode(self): s = u'Hello, \u2603' proxy = self._makeOne(s) self.assertEqual(unicode(proxy), s) @unittest.skipIf(PY3, "Gone in Py3") def test___unicode__of_custom_class(self): class CustomClass(object): def __unicode__(self): return u'Hello, \u2603' cc = CustomClass() self.assertEqual(unicode(cc), u'Hello, \u2603') proxy = self._makeOne(cc) self.assertEqual(unicode(proxy), u'Hello, \u2603') @unittest.skipIf(PY3, "Gone in Py3") def test___unicode__of_custom_class_no_unicode(self): class CustomClass(object): pass cc = CustomClass() cc_unicode = unicode(cc) self.assertEqual(type(cc_unicode), unicode) proxy = self._makeOne(cc) self.assertEqual(unicode(proxy), cc_unicode) def test___call__(self): def _foo(): return 'FOO' proxy = self._makeOne(_foo) self.assertEqual(proxy(), 'FOO') @unittest.skipIf(PY3, "Gone in Py3") def test_callable(self): w = self._makeOne({}.get) self.assertTrue(callable(w)) def test___repr__(self): def _foo(): raise AssertionError("Not called") proxy = self._makeOne(_foo) self.assertEqual(repr(proxy), repr(_foo)) def test___str__(self): def _foo(): raise AssertionError("Not called") proxy = self._makeOne(_foo) self.assertEqual(str(proxy), str(_foo)) @unittest.skipIf(PY3, "Gone in Py3") def test___unicode__(self): def _foo(): raise AssertionError("Not called") proxy = self._makeOne(_foo) self.assertTrue(unicode(proxy).startswith(' w1) self.assertTrue(w2 >= w1) self.assertTrue(w2 > o1) self.assertTrue(w2 >= o1) self.assertTrue(o2 > w1) self.assertTrue(o2 >= w2) def test___nonzero__(self): w = self._makeOne(None) self.assertFalse(w) self.assertTrue(not w) def test___hash__(self): w1 = self._makeOne(1) self.assertEqual(hash(w1), hash(1)) def test___getattr__miss_both(self): class Foo(object): pass o = Foo() w = self._makeOne(o) def _try(): return w.nonesuch self.assertRaises(AttributeError, _try) def test___getattr__delegates_to_wrapped(self): class Foo(object): pass o = Foo() o.foo = 1 w = self._makeOne(o) self.assertEqual(w.foo, 1) def test___getattr__delegates_to_wrapped_when_conflict(self): class Proxy(self._getTargetClass()): def foo(self): raise AssertionError("Not called") class Foo(object): def foo(self): return 'FOO' o = Foo() w = Proxy(o) self.assertEqual(w.foo(), 'FOO') def test___setattr__delegates_to_wrapped(self): class Foo(object): pass o = Foo() w = self._makeOne(o) w.foo = 1 self.assertEqual(o.foo, 1) def test___setattr__sets_proxy_property(self): class Proxy(self._getTargetClass()): bar = property( lambda s: s.__dict__.get('_bar'), lambda s, v: s.__dict__.__setitem__('_bar', v) ) class Foo(object): pass o = Foo() w = Proxy(o) w.bar = 43 self.assertEqual(w.bar, 43) self.assertRaises(AttributeError, getattr, o, 'bar') def test___delattr___wrapped(self): class Foo(object): pass o = Foo() o.foo = 1 w = self._makeOne(o) def _try(): del w._wrapped self.assertRaises(AttributeError, _try) def test___delattr__delegates_to_wrapped(self): class Foo(object): pass o = Foo() o.foo = 1 w = self._makeOne(o) del w.foo self.assertFalse('foo' in o.__dict__) def test___len__(self): l = [] w = self._makeOne(l) self.assertEqual(len(w), 0) l.append(0) self.assertEqual(len(w), 1) def test___getitem_____setitem_____delitem__(self): w = self._makeOne({}) self.assertRaises(KeyError, lambda: w[1]) w[1] = 'a' self.assertEqual(w[1], 'a') del w[1] self.assertRaises(KeyError, lambda: w[1]) def del_w_1(): del w[1] self.assertRaises(KeyError, del_w_1) def test___getitem__w_slice_against_list(self): # Lists have special slicing behavior. pList = self._makeOne([1, 2]) self.assertEqual(pList[-1:], [2]) self.assertEqual(pList[-2:], [1, 2]) self.assertEqual(pList[-3:], [1, 2]) def test___getitem__w_slice_against_tuple(self): # Tuples also have special slicing behavior. pTuple = self._makeOne((1, 2)) self.assertEqual(pTuple[-1:], (2,)) self.assertEqual(pTuple[-2:], (1, 2)) self.assertEqual(pTuple[-3:], (1, 2)) def test___getitem__w_slice_against_derived_list(self): data = [1, 2] class DerivedList(list): def __getslice__(self, start, stop): return list.__getslice__(self, start, stop) pList = self._makeOne(DerivedList(data)) self.assertEqual(pList[-1:], data[-1:]) self.assertEqual(pList[-2:], data[-2:]) self.assertEqual(pList[-3:], data[-3:]) def test___getitem__w_slice_against_class_w_custom___getslice__(self): import sys test = self class Slicer(object): def __len__(self): return 2 def __getslice__(self, start, end): return (start, end) def __getitem__(self, a_slice): # pragma: no cover test.assertTrue(PY3) # On Python 3, we basically just return what the test expects. # Mostly that's the computed indices (yay!) but there are # a few special cases. indices = a_slice.indices(len(self)) return (indices[0] if a_slice.start != -3 else -1, indices[-1] if a_slice.stop is not None else sys.maxsize) pSlicer = self._makeOne(Slicer()) self.assertEqual(pSlicer[:1][0], 0) self.assertEqual(pSlicer[:1][1], 1) self.assertEqual(pSlicer[:-1][0], 0) self.assertEqual(pSlicer[:-1][1], 1) self.assertEqual(pSlicer[-1:][0], 1) self.assertEqual(pSlicer[-2:][0], 0) self.assertEqual(pSlicer[-3:], (-1, sys.maxsize)) def test___getslice___dne_uses_getitem(self): class Missing(Exception): pass class Get(object): def __getitem__(self, x): raise Missing('__getitem__') target = Get() proxy = self._makeOne(target) with self.assertRaisesRegexp(Missing, '__getitem__'): proxy[1:2] def test___getslice___error_propagates(self): test = self class Missing(Exception): pass class Get(object): def __getitem__(self, x): # pragma: no cover (only py3) test.assertTrue(PY3) raise Missing('__getitem__') def __getslice__(self, start, stop): raise Missing("__getslice__") target = Get() proxy = self._makeOne(target) with self.assertRaisesRegexp(Missing, self.getslice): proxy[1:2] def test___setslice___against_list(self): # Lists have special slicing bahvior for assignment as well. pList = self._makeOne([1, 2]) pList[-1:] = [3, 4] self.assertEqual(pList, [1, 3, 4]) pList = self._makeOne([1, 2]) pList[-2:] = [3, 4] self.assertEqual(pList, [3, 4]) pList = self._makeOne([1, 2]) pList[-3:] = [3, 4] self.assertEqual(pList, [3, 4]) def test___setslice___against_derived_list(self): # This behavior should be true for all list-derived classes. class DerivedList(list): pass pList = self._makeOne(DerivedList([1, 2])) pList[-1:] = [3, 4] self.assertEqual(pList, [1, 3, 4]) pList = self._makeOne(DerivedList([1, 2])) pList[-2:] = [3, 4] self.assertEqual(pList, [3, 4]) pList = self._makeOne(DerivedList([1, 2])) pList[-3:] = [3, 4] self.assertEqual(pList, [3, 4]) 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__") target = Set() proxy = self._makeOne(target) with self.assertRaisesRegexp(Missing, self.setslice): proxy[1:2] = 1 def test___setslice___dne_uses_setitem(self): class Missing(Exception): pass class Set(object): def __setitem__(self, k, v): raise Missing('__setitem__') target = Set() proxy = self._makeOne(target) with self.assertRaisesRegexp(Missing, '__setitem__'): proxy[1:2] = 1 def test___iter___w_wrapped_iterable(self): a = [1, 2, 3] b = [] for x in self._makeOne(a): b.append(x) self.assertEqual(a, b) def test___iter___w_wrapped_iterator(self): # Wrap an iterator before starting iteration. # PyObject_GetIter() will still be called on the proxy. a = [1, 2, 3] b = [] for x in self._makeOne(iter(a)): b.append(x) self.assertEqual(a, b) t = tuple(self._makeOne(iter(a))) self.assertEqual(t, (1, 2, 3)) def test___iter___returns_self_if_defined(self): # Return the wrapped object itself, if it is an iterator. class MyIter(object): def __iter__(self): return self def __next__(self): raise AssertionError("Not called") next = __next__ myIter = MyIter() p = self._makeOne(myIter) self.assertEqual(iter(p), p) self.assertTrue(isinstance(iter(p), MyIter)) def test___iter___next_when_returned_by_iterable(self): # Wrap an iterator within the iteration protocol, expecting it # still to work. PyObject_GetIter() will not be called on the # proxy, so the tp_iter slot won't unwrap it. class Iterable(object): def __init__(self, test, data): self.test = test self.data = data def __iter__(self): return self.test._makeOne(iter(self.data)) a = [1, 2, 3] b = [] for x in Iterable(self, a): b.append(x) self.assertEqual(a, b) # Python 2.7 won't let the C wrapper support __reversed__ :( #def test___reversed__(self): # w = self._makeOne([0, 1, 2, 3]) # self.assertEqual(list(reversed(w)), [3, 2, 1, 0]) def test___contains__(self): w = self._makeOne([0, 1, 2, 3]) self.assertTrue(1 in w) self.assertFalse(4 in w) def test___index__(self): import operator w = self._makeOne(42) self.assertEqual(operator.index(w), 42) # Numeric ops. @property def unops(self): ops = [ "-x", "+x", "abs(x)", "~x", "int(x)", "float(x)", "complex(x)", ] if not PY3: # long is gone in Python 3 ops.append("long(x)") return ops def test_unops(self): for expr in self.unops: x = 1 y = eval(expr) x = self._makeOne(1) z = eval(expr) self.assertEqual(z, y, "x=%r; expr=%r" % (x, expr)) def test_odd_unops(self): # unops that don't return a proxy funcs = (lambda x: not x,) if not PY3: funcs += (oct, hex) for func in funcs: self.assertEqual(func(self._makeOne(100)), func(100)) binops = [ "x+y", "x-y", "x*y", "x/y", "x//y", "x%y", "divmod(x, y)", "x**y", #"pow(x,y,3)" (RHS coercion not supported w/ modulus) "x<>y", "x&y", "x|y", "x^y", ] def test_binops(self): for expr in self.binops: first = 1 for x in [1, self._makeOne(1)]: for y in [2, self._makeOne(2)]: if first: z = eval(expr) first = 0 else: self.assertEqual(eval(expr), z, "x=%r; y=%r; expr=%r" % (x, y, expr)) def test_pow_w_modulus(self): x = self._makeOne(2) # Can't coerce 2nd / 3rd args in pure Python, because we can't # lie about our type self.assertEqual(pow(x, 3, 3), 2) def test_inplace(self): # TODO: should test all inplace operators... pa = self._makeOne(1) pa += 2 self.assertEqual(pa, 3) a = [1, 2, 3] pa = qa = self._makeOne(a) pa += [4, 5, 6] self.assertTrue(pa is qa) self.assertEqual(a, [1, 2, 3, 4, 5, 6]) pa = self._makeOne(2) pa -= 1 self.assertEqual(pa, 1) pa *= 4 self.assertEqual(pa, 4) pa /= 2 self.assertEqual(pa, 2) pa //= 2 self.assertEqual(pa, 1) pa += 2 self.assertEqual(pa, 3) pa %= 2 self.assertEqual(pa, 1) pa = self._makeOne(2) pa **= 2 self.assertEqual(pa, 4) pa <<= 1 self.assertEqual(pa, 8) pa >>= 2 self.assertEqual(pa, 2) pa = self._makeOne(7) pa &= 6 self.assertEqual(pa, 6) pa |= 16 self.assertEqual(pa, 22) pa ^= 2 self.assertEqual(pa, 20) @unittest.skipIf(PY3, "No coercion in Py3") def test_coerce(self): # Before 2.3, coerce() of two proxies returns them unchanged x = self._makeOne(1) y = self._makeOne(2) a, b = coerce(x, y) self.assertTrue(a is x and b is y) x = self._makeOne(1) y = self._makeOne(2.1) a, b = coerce(x, y) self.assertTrue(isinstance(a, float)) # a was coerced self.assertFalse(a is x) self.assertEqual(a, float(x)) self.assertTrue(b is y) x = self._makeOne(1.1) y = self._makeOne(2) a, b = coerce(x, y) self.assertTrue(a is x) self.assertTrue(isinstance(b, float)) # b was coerced self.assertFalse(b is y) self.assertEqual(b, float(y)) x = self._makeOne(1) y = 2 a, b = coerce(x, y) self.assertTrue(a is x) # neither was coerced self.assertTrue(b is y) x = self._makeOne(1) y = 2.1 a, b = coerce(x, y) self.assertTrue(isinstance(a, float)) # a was coerced self.assertFalse(a is x) self.assertEqual(a, float(x)) self.assertTrue(b is y) x = self._makeOne(1.1) y = 2 a, b = coerce(x, y) self.assertTrue(a is x) self.assertTrue(isinstance(b, float)) # b was coerced self.assertFalse(b is y) self.assertEqual(b,float(y)) x = 1 y = self._makeOne(2) a, b = coerce(x, y) self.assertTrue(a is x) # neither was coerced self.assertTrue(b is y) x = 1.1 y = self._makeOne(2) a, b = coerce(x, y) self.assertTrue(a is x) self.assertTrue(isinstance(b, float)) # b was coerced self.assertFalse(b is y) self.assertEqual(b, float(y)) x = 1 y = self._makeOne(2.1) a, b = coerce(x, y) self.assertTrue(isinstance(a, float)) # a was coerced self.assertFalse(a is x) self.assertEqual(a, float(x)) self.assertTrue(b is y) def test___class__(self): o = object() w = self._makeOne(o) self.assertTrue(w.__class__ is o.__class__) def test_descriptor__set___only_in_proxy_subclass(self): class Descriptor(object): value = None instance = None def __set__(self, instance, value): self.value = value self.instance = instance descriptor = Descriptor() class Proxy(self._getTargetClass()): attr = descriptor proxy = Proxy(object()) proxy.attr = 42 self.assertEqual(proxy.attr, descriptor) self.assertEqual(descriptor.value, 42) self.assertEqual(descriptor.instance, proxy) def test_descriptor__get___set___in_proxy_subclass(self): class Descriptor(object): value = None instance = None cls = None def __get__(self, instance, cls): self.cls = cls return self.value def __set__(self, instance, value): self.value = value self.instance = instance descriptor = Descriptor() descriptor.value = "descriptor value" class Proxy(self._getTargetClass()): attr = descriptor proxy = Proxy(object()) self.assertEqual(proxy.attr, "descriptor value") self.assertEqual(descriptor.cls, Proxy) proxy.attr = 42 self.assertEqual(descriptor.value, 42) self.assertEqual(descriptor.instance, proxy) def test_non_descriptor_in_proxy_subclass__dict__(self): # Non-descriptors in the class dict of the subclass # are always passed through to the wrapped instance class Proxy(self._getTargetClass()): attr = "constant value" proxy = Proxy(object()) self.assertEqual(proxy.attr, "constant value") self.assertRaises(AttributeError, setattr, proxy, 'attr', 42) self.assertEqual(proxy.attr, "constant value") def _check_wrapping_builtin_returns_correct_provided_by(self, proxy_class, builtin_type): # We get the __implemented__ (fallback) of the type, not our own from zope.interface import Interface from zope.interface import classImplements from zope.interface import classImplementsOnly from zope.interface import implementedBy from zope.interface import providedBy from zope.interface import implementedBy # Set up the builtin interface class IFoo(Interface): pass impl_before = list(implementedBy(builtin_type)) classImplements(builtin_type, IFoo) builtin = builtin_type() self.assertTrue(IFoo in list(providedBy(builtin))) self.assertTrue(IFoo in list(implementedBy(builtin_type))) try: # The asserts must be before we remove the interface # because there's a single object that gets mutated proxy_instance = proxy_class(builtin) provided_instance = providedBy(proxy_instance) self.assertTrue(IFoo in list(provided_instance)) proxy_type = proxy_class(builtin_type) from zope.interface.declarations import BuiltinImplementationSpecifications self.assertIn(proxy_type, BuiltinImplementationSpecifications) self.assertIsNot(BuiltinImplementationSpecifications.get(proxy_type, self), self) provided_type = implementedBy(proxy_type) self.assertTrue(IFoo in list(provided_type)) finally: classImplementsOnly(builtin_type, *impl_before) def test_wrapping_builtin_type_returns_correct_provided_by(self): self._check_wrapping_builtin_returns_correct_provided_by(self._getTargetClass(), list) def _check_wrapping_builtin_with_subclass_returns_correct_provided_by(self, builtin_type): class Proxy(self._getTargetClass()): pass self._check_wrapping_builtin_returns_correct_provided_by(Proxy, builtin_type) # Our new class did not gain an __implemented__ attribute, unless we're # the pure-python version if hasattr(Proxy, '__implemented__'): # pragma: no cover from zope.proxy import PyProxyBase self.assertTrue(self._getTargetClass() is PyProxyBase) def test_wrapping_builtin_with_subclass_returns_correct_provided_by(self): self._check_wrapping_builtin_with_subclass_returns_correct_provided_by(list) def test_method_in_proxy_subclass(self): class Proxy(self._getTargetClass()): def __getitem__(self, k): return k proxy = Proxy(object()) # Both when called by the interpreter, which bypasses # __getattribute__ self.assertEqual(proxy[42], 42) # And when asked for as an attribute self.assertNotEqual(getattr(proxy, '__getitem__'), self) def test_string_to_int(self): proxy = self._makeOne("14") self.assertEqual(14, int(proxy)) class ProxyBaseTestCase(PyProxyBaseTestCase): def _getTargetClass(self): from zope.proxy import ProxyBase return ProxyBase class Test_py__module(unittest.TestCase): # Historically, proxying __module__ has been troublesome, # especially when subclasses of the proxy class are involved; # there was also a discrepancy between the C and Python implementations # in that the C implementation only failed Test_subclass__module:test__module__in_instance, # whereas the Python version failed every test. # See https://github.com/zopefoundation/zopetoolkit/pull/2#issuecomment-106075153 # and https://github.com/zopefoundation/zope.proxy/pull/8 def _getTargetClass(self): from zope.proxy import PyProxyBase return PyProxyBase def _makeProxy(self, obj): from zope.proxy import PyProxyBase return self._getTargetClass()(obj) def _check_module(self, obj, expected): self.assertEqual(expected, obj.__module__) self.assertEqual(expected, self._makeProxy(obj).__module__) def test__module__in_instance(self): # We can find __module__ in an instance dict class Module(object): def __init__(self): self.__module__ = 'module' self._check_module(Module(), 'module') def test__module__in_class_instance(self): # We can find module in an instance of a class class Module(object): pass self._check_module(Module(), __name__) def test__module__in_class(self): # We can find module in a class itself class Module(object): pass self._check_module(Module, __name__) def test__module_in_eq_transitive(self): # An object that uses __module__ in its implementation # of __eq__ is transitively equal to a proxy of itself. # Seen with zope.interface.interface.Interface class Module(object): def __init__(self): self.__module__ = __name__ def __eq__(self, other): return self.__module__ == other.__module__ module = Module() # Sanity checks self.assertEqual(module, module) self.assertEqual(module.__module__, __name__) # transitive equal self.assertEqual(module, self._makeProxy(module)) self.assertEqual(self._makeProxy(module), module) class Test__module(Test_py__module): def _getTargetClass(self): from zope.proxy import ProxyBase return ProxyBase class Test_py_subclass__module(Test_py__module): def _getTargetClass(self): class ProxySubclass(super(Test_py_subclass__module, self)._getTargetClass()): pass return ProxySubclass class Test_subclass__module(Test__module): def _getTargetClass(self): class ProxySubclass(super(Test_subclass__module, self)._getTargetClass()): pass return ProxySubclass class Test_py_getProxiedObject(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_getProxiedObject return py_getProxiedObject(*args) def _makeProxy(self, obj): from zope.proxy import PyProxyBase return PyProxyBase(obj) def test_no_proxy(self): class C(object): pass c = C() self.assertTrue(self._callFUT(c) is c) def test_simple_proxy(self): class C(object): pass c = C() proxy = self._makeProxy(c) self.assertTrue(self._callFUT(proxy) is c) def test_nested_proxy(self): class C(object): pass c = C() proxy = self._makeProxy(c) proxy2 = self._makeProxy(proxy) self.assertTrue(self._callFUT(proxy2) is proxy) class Test_getProxiedObject(Test_py_getProxiedObject): def _callFUT(self, *args): from zope.proxy import getProxiedObject return getProxiedObject(*args) def _makeProxy(self, obj): from zope.proxy import ProxyBase return ProxyBase(obj) class Test_py_setProxiedObject(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_setProxiedObject return py_setProxiedObject(*args) def _makeProxy(self, obj): from zope.proxy import PyProxyBase return PyProxyBase(obj) def test_no_proxy(self): class C(object): pass c1 = C() c2 = C() self.assertRaises(TypeError, self._callFUT, c1, c2) def test_w_proxy(self): class C(object): def __init__(self, name): self.name = name c1 = C('c1') c2 = C('c2') proxy = self._makeProxy(c1) self.assertEqual(proxy.name, 'c1') old = self._callFUT(proxy, c2) self.assertTrue(old is c1) self.assertEqual(proxy.name, 'c2') def test_w_nested_proxy(self): class C(object): def __init__(self, name): self.name = name c1 = C('c1') c2 = C('c2') p1 = self._makeProxy(c1) proxy2 = self._makeProxy(c2) proxy = self._makeProxy(p1) self.assertEqual(proxy.name, 'c1') old = self._callFUT(proxy, proxy2) self.assertTrue(old is p1) self.assertEqual(proxy.name, 'c2') class Test_setProxiedObject(Test_py_setProxiedObject): def _callFUT(self, *args): from zope.proxy import setProxiedObject return setProxiedObject(*args) def _makeProxy(self, obj): from zope.proxy import ProxyBase return ProxyBase(obj) class Test_py_isProxy(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_isProxy return py_isProxy(*args) def _proxyClass(self): from zope.proxy import PyProxyBase return PyProxyBase def test_bare_instance(self): class C(object): pass c = C() self.assertFalse(self._callFUT(c)) def test_proxy_no_class(self): class P1(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1)) def test_proxy_w_same_class(self): class P1(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1, P1)) def test_proxy_w_other_class(self): class P1(self._proxyClass()): pass class P2(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertFalse(self._callFUT(p1, P2)) class Test_isProxy(Test_py_isProxy): def _callFUT(self, *args): from zope.proxy import isProxy return isProxy(*args) def _proxyClass(self): from zope.proxy import ProxyBase return ProxyBase class Test_py_sameProxiedObjects(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_sameProxiedObjects return py_sameProxiedObjects(*args) def _makeProxy(self, obj): from zope.proxy import PyProxyBase return PyProxyBase(obj) def _makeSecurityProxy(self, obj): from zope.security.proxy import ProxyPy from zope.security.checker import CheckerPy checker = CheckerPy({}) return ProxyPy(obj, checker) def test_bare_instance_identical(self): class C(object): pass c1 = C() self.assertTrue(self._callFUT(c1, c1)) def test_bare_instances_different(self): class C(object): pass c1 = C() c2 = C() self.assertFalse(self._callFUT(c1, c2)) self.assertFalse(self._callFUT(c2, c1)) def test_proxy_and_same_bare(self): class C(object): pass c1 = C() self.assertTrue(self._callFUT(self._makeProxy(c1), c1)) self.assertTrue(self._callFUT(c1, self._makeProxy(c1))) def test_proxy_and_other_bare(self): class C(object): pass c1 = C() c2 = C() self.assertFalse(self._callFUT(self._makeProxy(c1), c2)) self.assertFalse(self._callFUT(c2, self._makeProxy(c1))) def test_proxies_w_same_bare(self): _mP = self._makeProxy class C(object): pass c1 = C() self.assertTrue(self._callFUT(_mP(c1), _mP(c1))) def test_proxies_w_other_bare(self): _mP = self._makeProxy class C(object): pass c1 = C() c2 = C() self.assertFalse(self._callFUT(_mP(c1), _mP(c2))) self.assertFalse(self._callFUT(_mP(c2), _mP(c1))) def test_nested_proxy_and_same_bare(self): _mP = self._makeProxy class C(object): pass c1 = C() self.assertTrue(self._callFUT(_mP(_mP(c1)), c1)) self.assertTrue(self._callFUT(c1, _mP(_mP(c1)))) def test_nested_proxy_and_other_bare(self): _mP = self._makeProxy class C(object): pass c1 = C() c2 = C() self.assertFalse(self._callFUT(_mP(_mP(c1)), c2)) self.assertFalse(self._callFUT(c2, _mP(_mP(c1)))) @unittest.skipUnless(_HAVE_ZOPE_SECURITY, 'zope.security missing') def test_security_proxy(self): class C(object): pass c1 = C() proxy1 = self._makeSecurityProxy(c1) proxy1_2 = self._makeSecurityProxy(c1) self.assertTrue(self._callFUT(proxy1, proxy1)) self.assertTrue(self._callFUT(proxy1, proxy1_2)) c2 = C() proxy2 = self._makeSecurityProxy(c2) self.assertFalse(self._callFUT(proxy1, proxy2)) class Test_sameProxiedObjects(Test_py_sameProxiedObjects): def _callFUT(self, *args): from zope.proxy import sameProxiedObjects return sameProxiedObjects(*args) def _makeProxy(self, obj): from zope.proxy import ProxyBase return ProxyBase(obj) def _makeSecurityProxy(self, obj): from zope.security.proxy import Proxy from zope.security.checker import Checker checker = Checker({}) return Proxy(obj, checker) class Test_py_queryProxy(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_queryProxy return py_queryProxy(*args) def _proxyClass(self): from zope.proxy import PyProxyBase return PyProxyBase def test_bare_instance(self): class C(object): pass c = C() self.assertEqual(self._callFUT(c), None) def test_proxy_no_class(self): class P1(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1) is p1) def test_proxy_w_same_class(self): class P1(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1, P1) is p1) self.assertTrue(self._callFUT(p1, P1, 42) is p1) def test_proxy_w_other_class(self): class P1(self._proxyClass()): pass class P2(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertEqual(self._callFUT(p1, P2), None) self.assertEqual(self._callFUT(p1, P2, 42), 42) def test_proxy_w_base_class(self): class P1(self._proxyClass()): pass class P2(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1, self._proxyClass()) is p1) self.assertTrue(self._callFUT(p1, self._proxyClass(), 42) is p1) class Test_queryProxy(Test_py_queryProxy): def _callFUT(self, *args): from zope.proxy import queryProxy return queryProxy(*args) def _proxyClass(self): from zope.proxy import ProxyBase return ProxyBase class Test_py_queryInnerProxy(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_queryInnerProxy return py_queryInnerProxy(*args) def _proxyClass(self): from zope.proxy import PyProxyBase return PyProxyBase def test_bare_instance(self): class C(object): pass c = C() self.assertEqual(self._callFUT(c), None) def test_proxy_no_class(self): class P1(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1) is p1) def test_proxy_w_same_class(self): class P1(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) self.assertTrue(self._callFUT(p1, P1) is p1) self.assertTrue(self._callFUT(p1, P1, 42) is p1) def test_nested_proxy(self): class P1(self._proxyClass()): pass class P2(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) proxy2 = P2(p1) self.assertTrue(self._callFUT(proxy2, P1) is p1) self.assertTrue(self._callFUT(proxy2, P1, 42) is p1) self.assertTrue(self._callFUT(proxy2, P2) is proxy2) self.assertTrue(self._callFUT(proxy2, P2, 42) is proxy2) def test_re_nested_proxy(self): class P1(self._proxyClass()): pass class P2(self._proxyClass()): pass class C(object): pass c = C() p1 = P1(c) proxy2 = P2(p1) proxy3 = P1(proxy2) self.assertTrue(self._callFUT(proxy3, P1) is p1) self.assertTrue(self._callFUT(proxy3, P1, 42) is p1) self.assertTrue(self._callFUT(proxy3, P2) is proxy2) self.assertTrue(self._callFUT(proxy3, P2, 42) is proxy2) class Test_queryInnerProxy(Test_py_queryInnerProxy): def _callFUT(self, *args): from zope.proxy import queryInnerProxy return queryInnerProxy(*args) def _proxyClass(self): from zope.proxy import ProxyBase return ProxyBase class Test_py_removeAllProxies(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import py_removeAllProxies return py_removeAllProxies(*args) def _makeProxy(self, obj): from zope.proxy import PyProxyBase return PyProxyBase(obj) def _makeSecurityProxy(self, obj): from zope.security.proxy import ProxyPy checker = object() return ProxyPy(obj, checker) def test_no_proxy(self): class C(object): pass c = C() self.assertTrue(self._callFUT(c) is c) def test_simple_proxy(self): class C(object): pass c = C() proxy = self._makeProxy(c) self.assertTrue(self._callFUT(proxy) is c) def test_nested_proxy(self): class C(object): pass c = C() proxy = self._makeProxy(c) proxy2 = self._makeProxy(proxy) self.assertTrue(self._callFUT(proxy2) is c) @unittest.skipUnless(_HAVE_ZOPE_SECURITY, 'zope.security missing') def test_security_proxy(self): class C(object): pass c = C() proxy = self._makeSecurityProxy(c) self.assertIs(self._callFUT(proxy), c) class Test_removeAllProxies(Test_py_removeAllProxies): def _callFUT(self, *args): from zope.proxy import removeAllProxies return removeAllProxies(*args) def _makeProxy(self, obj): from zope.proxy import ProxyBase return ProxyBase(obj) def _makeSecurityProxy(self, obj): from zope.security.proxy import Proxy checker = object() return Proxy(obj, checker) class Test_ProxyIterator(unittest.TestCase): def _callFUT(self, *args): from zope.proxy import ProxyIterator return ProxyIterator(*args) def test_no_proxy(self): class C(object): pass c = C() self.assertEqual(list(self._callFUT(c)), [c]) def test_w_simple_proxy(self): from zope.proxy import ProxyBase class C(object): pass c = C() proxy = ProxyBase(c) self.assertEqual(list(self._callFUT(proxy)), [proxy, c]) def test_w_nested_proxies(self): from zope.proxy import ProxyBase class C(object): pass c = C() proxy = ProxyBase(c) proxy2 = ProxyBase(proxy) proxy3 = ProxyBase(proxy2) proxy4 = ProxyBase(proxy3) self.assertEqual(list(self._callFUT(proxy4)), [proxy4, proxy3, proxy2, proxy, c]) class Test_nonOverridable(unittest.TestCase): def test_it(self): from zope.proxy import ProxyBase from zope.proxy import non_overridable class Proxy(ProxyBase): def who(self): raise AssertionError("Not called") @non_overridable def what(self): return 'PROXY' class Foo(object): def who(self): return 'FOO' def what(self): return 'FOO' p0 = ProxyBase(Foo()) self.assertEqual(p0.who(), 'FOO') self.assertEqual(p0.what(), 'FOO') proxy = Proxy(Foo()) self.assertEqual(proxy.who(), 'FOO') self.assertEqual(proxy.what(), 'PROXY') class TestEmptyInterfaceDescriptor(unittest.TestCase): def _makeOne(self): from zope.proxy import _EmptyInterfaceDescriptor class It(object): feature = _EmptyInterfaceDescriptor() return It() def test_set(self): it = self._makeOne() with self.assertRaises(TypeError): it.feature = 42 def test_delete(self): it = self._makeOne() del it.feature with self.assertRaises(AttributeError): getattr(it, 'feature') def test_iter(self): it = type(self._makeOne()) feature = it.__dict__['feature'] self.assertEqual([], list(feature)) class Comparable(object): def __init__(self, value): self.value = value def __eq__(self, other): return self.value == getattr(other, 'value', other) def __ne__(self, other): return not self.__eq__(other) def __lt__(self, other): return self.value < getattr(other, 'value', other) def __ge__(self, other): return not self.__lt__(other) def __le__(self, other): return self.value <= getattr(other, 'value', other) def __gt__(self, other): return not self.__le__(other) def __repr__(self): # pragma: no cover return "" % self.value def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) zope.proxy-4.3.3/src/zope.proxy.egg-info/0000755000175000017500000000000013562322312017323 5ustar mgmg00000000000000zope.proxy-4.3.3/src/zope.proxy.egg-info/PKG-INFO0000644000175000017500000002560313562322312020426 0ustar mgmg00000000000000Metadata-Version: 2.1 Name: zope.proxy Version: 4.3.3 Summary: Generic Transparent Proxies Home-page: http://github.com/zopefoundation/zope.proxy Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ``zope.proxy`` ============== .. image:: https://img.shields.io/pypi/v/zope.proxy.svg :target: https://pypi.python.org/pypi/zope.proxy/ :alt: Latest Version .. image:: https://travis-ci.org/zopefoundation/zope.proxy.svg?branch=master :target: https://travis-ci.org/zopefoundation/zope.proxy .. image:: https://readthedocs.org/projects/zopeproxy/badge/?version=latest :target: http://zopeproxy.readthedocs.org/en/latest/ :alt: Documentation Status Proxies are special objects which serve as mostly-transparent wrappers around another object, intervening in the apparent behavior of the wrapped object only when necessary to apply the policy (e.g., access checking, location brokering, etc.) for which the proxy is responsible. zope.proxy is implemented via a C extension module, which lets it do things like lie about its own ``__class__`` that are difficult in pure Python (and were completely impossible before metaclasses). It also proxies all the internal slots (such as ``__int__``/``__str__``/``__add__``). Complete documentation is at https://zopeproxy.readthedocs.io Changes ======= 4.3.3 (2019-11-11) ------------------ - Add support for Python 3.8. - Drop support for Python 3.4. 4.3.2 (2019-07-12) ------------------ - Fix error handling in ``ProxyBase.__setattr__``: any the exception raised by ``PyString_AsString``/``PyUnicode_AsUTF8`` would be silently swallowed up and ignored. See `issue 31 `_. 4.3.1 (2018-08-09) ------------------ - Simplify the internal C handling of attribute names in ``__getattribute__`` and ``__setattr__``. - Make building the C extension optional. We still attempt to build it on supported platforms, but we allow it to fail in case of a missing compiler or headers. See `issue 26 `_. - Test the PURE_PYTHON environment and PyPy3 on Travis CI. - Add support for Python 3.7. 4.3.0 (2017-09-13) ------------------ - Fix a potential rare crash when deallocating proxies. See `issue 20 `_. - Drop support for Python 3.3. - Drop support for "python setup.py test". - 100% test coverage. - Fix indexing pure-Python proxies with slices under Python 3, and restore the use of ``__getslice__`` (if implemented by the target's type) under Python 2. Previously, pure-Python proxies would fail with an AttributeError when given a slice on Python 3, and on Python 2, a custom ``__getslice__`` was ignored. See `issue 21 `_. 4.2.1 (2017-04-23) ------------------ - Make the pure-Python implementation of ``sameProxiedObjects`` handle ``zope.security`` proxies. See `issue 15 `_. - Add support for Python 3.6. 4.2.0 (2016-05-05) ------------------ - Correctly strip ``zope.security`` proxies in ``removeAllProxies``. See `issue 13 `_. - Avoid poisoning the user's global wheel cache when testing ``PURE_PYTHON`` environments under ``tox``, - Drop support for Python 2.6 and 3.2. - Add support for Python 3.5. 4.1.6 (2015-06-02) ------------------ - Make subclasses of ProxyBase properly delegate ``__module__`` to the wrapped object. This fixes some ``zope.interface`` lookups under PyPy. - Make the pure-Python implementation of ProxyBase properly report the ``zope.interface`` interfaces implemented by builtin types like ``list``. This fixes some ``zope.interface`` lookups under PyPy. 4.1.5 (2015-05-19) ------------------ - Make the C implementation proxy ``__unicode__`` correctly. - Make the C implementation use the standard methods to proxy ``int`` and ``float``. - Make the pure Python implementation handle descriptors defined in subclasses like the C version. See https://github.com/zopefoundation/zope.proxy/issues/5. 4.1.4 (2014-03-19) ------------------ - Add support for Python 3.4. - Update ``bootstrap.py`` to version 2.2. 4.1.3 (2013-03-12) ------------------ - Fix interface object introspection in PyPy. For some reason PyPy makes attributes available despite the restrictive ``__slots__`` declaration. - Add a bunch of tests surrounding interface lookup and adaptation. 4.1.2 (2013-03-11) ------------------ - Make ``PyProxyBase.__iter__()`` return the result of ``PyProxyBase._wrapped.__iter__`` if available, otherwise falling back to Python internals. The previous implementation always created a generator. - In ``PyProxyBase.__setattr__()``, allow setting of properties on the proxy itself. This is needed to properly allow proxy extensions as was evidenced int he ``zope.security.decorator`` module. 4.1.1 (2012-12-31) ------------------ - Fleshed out PyPI Trove classifiers. 4.1.0 (2012-12-19) ------------------ - Enable compilation of dependent modules under Py3k. - Replace use of ``PyCObject`` APIs with equivalent ``PyCapsule`` APIs, except under Python 2.6. N.B. This change is an ABI incompatibility under Python 2.7: extensions built under Python 2.7 against 4.0.x versions of ``zope.proxy`` must be rebuilt. 4.0.1 (2012-11-21) ------------------ - Add support for Python 3.3. 4.0.0 (2012-06-06) ------------------ - Add support for PyPy. N.B.: the C extension is *not* built under PyPy. - Add a pure-Python reference / fallback implementations of ``zope.proxy.ProxyBase`` and the proxy module API functions. N.B.: the pure-Python proxy implements all regular features of ``ProxyBase``; however, it does not exclude access to the wrapped object in the same way that the C version does. If you need that information hiding (e.g., to implement security sandboxing), you still need to use the C version. - Add support for continuous integration using ``tox`` and ``jenkins``. - 100% unit test coverage. - Add Sphinx documentation: moved doctest examples to API reference. - Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies). - Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs ``nose`` and ``coverage``). - Replace deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Drop support for Python 2.4 and 2.5. - Add Python 3.2 support. 3.6.1 (2010-07-06) ------------------ - Make tests compatible with Python 2.7. 3.6.0 (2010-04-30) ------------------ - Remove test extra and the remaining dependency on zope.testing. - Remove use of 'zope.testing.doctestunit' in favor of stdlib's 'doctest. 3.5.0 (2009/01/31) ------------------ - Add support to bootstrap on Jython. - Use ``zope.container`` instead of ``zope.app.container``. 3.4.2 (2008/07/27) ------------------ - Make C code compatible with Python 2.5 on 64bit architectures. 3.4.1 (2008/06/24) ------------------ - Bug: Update ``setup.py`` script to conform to common layout. Also updated some of the fields. - Bug: Honor pre-cooked indices for tuples and lists in the ``__getslice__()`` and ``__setslice__()`` methods. See http://docs.python.org/ref/sequence-methods.html. 3.4.0 (2007/07/12) ------------------ - Feature: Add a ``decorator`` module that supports declaring interfaces on proxies that get blended with the interfaces of the things they proxy. 3.3.0 (2006/12/20) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope 3.3.0 release. 3.2.0 (2006/01/05) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope 3.2.0 release. 3.0.0 (2004/11/07) ------------------ - Corresponds to the verison of the ``zope.proxy`` package shipped as part of the Zope X3.0.0 release. Keywords: proxy generic transparent Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Framework :: Zope :: 3 Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Provides-Extra: docs Provides-Extra: test zope.proxy-4.3.3/src/zope.proxy.egg-info/SOURCES.txt0000644000175000017500000000152313562322312021210 0ustar mgmg00000000000000.coveragerc .travis.yml CHANGES.rst COPYRIGHT.txt LICENSE.txt MANIFEST.in README.rst appveyor.yml bootstrap.py buildout.cfg rtd.txt setup.cfg setup.py tox.ini docs/Makefile docs/api.rst docs/conf.py docs/hacking.rst docs/index.rst docs/make.bat docs/narr.rst docs/_static/.gitignore src/zope/__init__.py src/zope.proxy.egg-info/PKG-INFO src/zope.proxy.egg-info/SOURCES.txt src/zope.proxy.egg-info/dependency_links.txt src/zope.proxy.egg-info/namespace_packages.txt src/zope.proxy.egg-info/not-zip-safe src/zope.proxy.egg-info/requires.txt src/zope.proxy.egg-info/top_level.txt src/zope/proxy/__init__.py src/zope/proxy/_compat.py src/zope/proxy/_zope_proxy_proxy.c src/zope/proxy/decorator.py src/zope/proxy/interfaces.py src/zope/proxy/proxy.h src/zope/proxy/tests/__init__.py src/zope/proxy/tests/test_decorator.py src/zope/proxy/tests/test_proxy.pyzope.proxy-4.3.3/src/zope.proxy.egg-info/dependency_links.txt0000644000175000017500000000000113562322312023371 0ustar mgmg00000000000000 zope.proxy-4.3.3/src/zope.proxy.egg-info/namespace_packages.txt0000644000175000017500000000000513562322312023651 0ustar mgmg00000000000000zope zope.proxy-4.3.3/src/zope.proxy.egg-info/not-zip-safe0000644000175000017500000000000113562322312021551 0ustar mgmg00000000000000 zope.proxy-4.3.3/src/zope.proxy.egg-info/requires.txt0000644000175000017500000000015313562322312021722 0ustar mgmg00000000000000setuptools zope.interface [docs] Sphinx repoze.sphinx.autointerface [test] zope.security zope.testrunner zope.proxy-4.3.3/src/zope.proxy.egg-info/top_level.txt0000644000175000017500000000000513562322312022050 0ustar mgmg00000000000000zope zope.proxy-4.3.3/tox.ini0000644000175000017500000000163313562322312014223 0ustar mgmg00000000000000[tox] envlist = py27,py27-pure,py35,py36,py36-pure,py37,py38,pypy,coverage,docs [testenv] deps = .[test,docs] commands = zope-testrunner --test-path=src sphinx-build -b doctest -d {envdir}/doctrees docs {envdir}/doctest [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 report --fail-under=100 deps = {[testenv]deps} coverage [testenv:docs] basepython = python2.7 commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest deps = .[test,docs] [testenv:py27-pure] basepython = python2.7 setenv = PURE_PYTHON = 1 [testenv:py36-pure] basepython = python3.6 setenv = PURE_PYTHON = 1