zope.proxy-4.2.0/ 0000775 0001750 0001750 00000000000 12712651560 015025 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/setup.cfg 0000664 0001750 0001750 00000000375 12712651560 016653 0 ustar tseaver tseaver 0000000 0000000 [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
tag_svn_revision = 0
zope.proxy-4.2.0/buildout.cfg 0000664 0001750 0001750 00000000134 12450532143 017325 0 ustar tseaver tseaver 0000000 0000000 [buildout]
parts = test
develop = .
[test]
recipe = zc.recipe.testrunner
eggs = zope.proxy
zope.proxy-4.2.0/PKG-INFO 0000664 0001750 0001750 00000020656 12712651560 016133 0 ustar tseaver tseaver 0000000 0000000 Metadata-Version: 1.1
Name: zope.proxy
Version: 4.2.0
Summary: Generic Transparent Proxies
Home-page: http://pypi.python.org/pypi/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.png?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__`).
Changes
=======
4.2.0 (2016-05-05)
------------------
- Correctly strip ``zope.security`` proxies in ``removeAllProxies``.
- 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.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Framework :: Zope3
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
zope.proxy-4.2.0/tox.ini 0000664 0001750 0001750 00000002324 12704100346 016331 0 ustar tseaver tseaver 0000000 0000000 [tox]
envlist =
# Jython support pending 2.7 support, due 2012-07-15 or so. See:
# http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
# py27,jython,pypy,coverage
py27,py27-pure,py33,py33-pure,py34,py35,pypy,coverage,docs
[testenv]
commands =
python setup.py -q test -q
[testenv:py27-pure]
basepython =
python2.7
setenv =
PURE_PYTHON = 1
PIP_CACHE_DIR = {envdir}/.cache
[testenv:py33-pure]
basepython =
python3.3
setenv =
PURE_PYTHON = 1
PIP_CACHE_DIR = {envdir}/.cache
[testenv:jython]
commands =
jython setup.py test -q
[testenv:coverage]
basepython =
python2.7
commands =
# The installed version messes up nose's test discovery / coverage reporting
# So, we uninstall that from the environment, and then install the editable
# version, before running nosetests.
pip uninstall -y zope.proxy
pip install -e .
nosetests --with-xunit --with-xcoverage
deps =
nose
coverage
nosexcover
[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 =
Sphinx
repoze.sphinx.autointerface
zope.proxy-4.2.0/.gitignore 0000664 0001750 0001750 00000000211 12450532143 017001 0 ustar tseaver tseaver 0000000 0000000 *.pyc
*.so
__pycache__
build
*.egg-info
docs/_build
.installed.cfg
bin
develop-eggs
eggs
parts
.tox
.coverage
nosetests.xml
coverage.xml
zope.proxy-4.2.0/setup.py 0000664 0001750 0001750 00000006701 12712651522 016541 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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
"""
import os
import platform
from setuptools import setup, Extension, Feature
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).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")
],
extra_compile_args=['-g']),
],
)
# PyPy won't build the extension.
py_impl = getattr(platform, 'python_implementation', lambda: None)
is_pypy = py_impl() == 'PyPy'
is_pure = os.environ.get('PURE_PYTHON')
if is_pypy or is_pure:
features = {}
else:
features = {'Cwrapper': Cwrapper}
setup(name='zope.proxy',
version='4.2.0',
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://pypi.python.org/pypi/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.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
"Framework :: Zope3",
'Natural Language :: English',
'Operating System :: OS Independent'],
keywords='proxy generic transparent',
packages=['zope', 'zope.proxy'],
package_dir = {'': 'src'},
namespace_packages=['zope',],
features=features,
test_suite = 'zope.proxy',
install_requires=[
'zope.interface',
'setuptools'],
include_package_data = True,
zip_safe = False,
extras_require = {
'testing': ['nose', 'coverage', 'zope.security'],
'docs': ['Sphinx', 'repoze.sphinx.autointerface'],
},
)
zope.proxy-4.2.0/bootstrap.py 0000664 0001750 0001750 00000016442 12705677060 017430 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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.2.0/.travis.yml 0000664 0001750 0001750 00000000333 12712651272 017135 0 ustar tseaver tseaver 0000000 0000000 language: python
sudo: false
python:
- 2.7
- 3.3
- 3.4
- 3.5
- pypy
install:
- pip install .
- pip install zope.security
script:
- python setup.py test -q
notifications:
email: false
zope.proxy-4.2.0/src/ 0000775 0001750 0001750 00000000000 12712651560 015614 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/src/zope.proxy.egg-info/ 0000775 0001750 0001750 00000000000 12712651560 021443 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/src/zope.proxy.egg-info/top_level.txt 0000664 0001750 0001750 00000000005 12712651552 024171 0 ustar tseaver tseaver 0000000 0000000 zope
zope.proxy-4.2.0/src/zope.proxy.egg-info/SOURCES.txt 0000664 0001750 0001750 00000005001 12712651560 023323 0 ustar tseaver tseaver 0000000 0000000 .gitignore
.travis.yml
CHANGES.rst
COPYRIGHT.txt
LICENSE.txt
MANIFEST.in
README.rst
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/_build/doctest/output.txt
docs/_build/doctrees/api.doctree
docs/_build/doctrees/environment.pickle
docs/_build/doctrees/hacking.doctree
docs/_build/doctrees/index.doctree
docs/_build/doctrees/narr.doctree
docs/_build/html/.buildinfo
docs/_build/html/api.html
docs/_build/html/genindex.html
docs/_build/html/hacking.html
docs/_build/html/index.html
docs/_build/html/narr.html
docs/_build/html/objects.inv
docs/_build/html/py-modindex.html
docs/_build/html/search.html
docs/_build/html/searchindex.js
docs/_build/html/_modules/index.html
docs/_build/html/_modules/zope/proxy.html
docs/_build/html/_modules/zope/proxy/decorator.html
docs/_build/html/_modules/zope/proxy/interfaces.html
docs/_build/html/_sources/api.txt
docs/_build/html/_sources/hacking.txt
docs/_build/html/_sources/index.txt
docs/_build/html/_sources/narr.txt
docs/_build/html/_static/ajax-loader.gif
docs/_build/html/_static/basic.css
docs/_build/html/_static/classic.css
docs/_build/html/_static/comment-bright.png
docs/_build/html/_static/comment-close.png
docs/_build/html/_static/comment.png
docs/_build/html/_static/default.css
docs/_build/html/_static/doctools.js
docs/_build/html/_static/down-pressed.png
docs/_build/html/_static/down.png
docs/_build/html/_static/file.png
docs/_build/html/_static/jquery-1.11.1.js
docs/_build/html/_static/jquery.js
docs/_build/html/_static/minus.png
docs/_build/html/_static/plus.png
docs/_build/html/_static/pygments.css
docs/_build/html/_static/searchtools.js
docs/_build/html/_static/sidebar.js
docs/_build/html/_static/underscore-1.3.1.js
docs/_build/html/_static/underscore.js
docs/_build/html/_static/up-pressed.png
docs/_build/html/_static/up.png
docs/_build/html/_static/websupport.js
docs/_static/.gitignore
src/coverage.xml
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.py zope.proxy-4.2.0/src/zope.proxy.egg-info/PKG-INFO 0000664 0001750 0001750 00000020656 12712651552 022552 0 ustar tseaver tseaver 0000000 0000000 Metadata-Version: 1.1
Name: zope.proxy
Version: 4.2.0
Summary: Generic Transparent Proxies
Home-page: http://pypi.python.org/pypi/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.png?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__`).
Changes
=======
4.2.0 (2016-05-05)
------------------
- Correctly strip ``zope.security`` proxies in ``removeAllProxies``.
- 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.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Framework :: Zope3
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
zope.proxy-4.2.0/src/zope.proxy.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12712651552 025512 0 ustar tseaver tseaver 0000000 0000000
zope.proxy-4.2.0/src/zope.proxy.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12450532253 023665 0 ustar tseaver tseaver 0000000 0000000
zope.proxy-4.2.0/src/zope.proxy.egg-info/namespace_packages.txt 0000664 0001750 0001750 00000000005 12712651552 025772 0 ustar tseaver tseaver 0000000 0000000 zope
zope.proxy-4.2.0/src/zope.proxy.egg-info/requires.txt 0000664 0001750 0001750 00000000154 12712651552 024044 0 ustar tseaver tseaver 0000000 0000000 zope.interface
setuptools
[docs]
Sphinx
repoze.sphinx.autointerface
[testing]
nose
coverage
zope.security
zope.proxy-4.2.0/src/coverage.xml 0000664 0001750 0001750 00000030731 12526704240 020132 0 ustar tseaver tseaver 0000000 0000000
zope.proxy-4.2.0/src/zope/ 0000775 0001750 0001750 00000000000 12712651560 016571 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/src/zope/proxy/ 0000775 0001750 0001750 00000000000 12712651560 017752 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/src/zope/proxy/_compat.py 0000664 0001750 0001750 00000000247 12526704623 021753 0 ustar tseaver tseaver 0000000 0000000 import sys
PY3 = sys.version_info[0] >= 3
if PY3: # pragma NO COVER
def _u(s):
return s
else:
def _u(s):
return unicode(s, 'unicode_escape')
zope.proxy-4.2.0/src/zope/proxy/__init__.py 0000664 0001750 0001750 00000037725 12712651272 022101 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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 __getitem__(self, key):
if isinstance(key, slice):
if isinstance(self._wrapped, (list, tuple)):
return self._wrapped[key]
start, stop = key.start, key.stop
if start is None:
start = 0
if start < 0:
start += len(self._wrapped)
if stop is None:
stop = sys.maxint
if stop < 0:
stop += len(self._wrapped)
return operator.getslice(self._wrapped, start, stop)
return self._wrapped[key]
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 = lhs._wrapped
while isinstance(rhs, PyProxyBase):
rhs = rhs._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.2.0/src/zope/proxy/decorator.py 0000664 0001750 0001750 00000003541 12450532143 022303 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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.2.0/src/zope/proxy/interfaces.py 0000664 0001750 0001750 00000004143 12450532143 022443 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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.2.0/src/zope/proxy/tests/ 0000775 0001750 0001750 00000000000 12712651560 021114 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/src/zope/proxy/tests/test_decorator.py 0000664 0001750 0001750 00000012520 12526704040 024502 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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.2.0/src/zope/proxy/tests/__init__.py 0000664 0001750 0001750 00000000075 12450532143 023221 0 ustar tseaver tseaver 0000000 0000000 #
# This file is necessary to make this directory a package.
zope.proxy-4.2.0/src/zope/proxy/tests/test_proxy.py 0000664 0001750 0001750 00000126164 12712651272 023720 0 ustar tseaver tseaver 0000000 0000000 ##############################################################################
#
# 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
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):
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_string_to_int(self):
# Strings don't have the tp_number.tp_int pointer
proxy = self._makeOne("14")
self.assertEqual(14, int(proxy))
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))
def test___unicode__of_unicode(self):
from zope.proxy._compat import PY3, _u
if PY3: # Gone in Python 3:
return
s = _u('Hello, \u2603')
proxy = self._makeOne(s)
self.assertEqual(unicode(proxy), s)
def test___unicode__of_custom_class(self):
from zope.proxy._compat import PY3, _u
if PY3: # Gone in Python 3:
return
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'))
def test___unicode__of_custom_class_no_unicode(self):
# The default behaviour should be preserved
from zope.proxy._compat import PY3, _u
if PY3: # Gone in Python 3:
return
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')
def test_callable(self):
from zope.proxy._compat import PY3
if not PY3: # Gone in Python 3:
w = self._makeOne({}.get)
self.assertTrue(callable(w))
def test___repr__(self):
def _foo():
return 'FOO'
proxy = self._makeOne(_foo)
self.assertEqual(repr(proxy), repr(_foo))
def test___str__(self):
def _foo():
return 'FOO'
proxy = self._makeOne(_foo)
self.assertEqual(str(proxy), str(_foo))
def test___unicode__(self):
from zope.proxy._compat import PY3
if PY3: # Gone in Python 3:
return
def _foo():
return 'FOO'
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):
return 'PROXY'
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):
# This behavior should be true for all list- and tuple-derived classes.
class DerivedList(list):
def __getslice__(self, start, end, step=None):
return (start, end, step)
pList = self._makeOne(DerivedList([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_class_w_custom___getslice__(self):
# moot under Python 3, where __getslice__ isn't supported.
from zope.proxy._compat import PY3
if not PY3:
class Slicer(object):
def __len__(self):
return 2
def __getslice__(self, start, end, step=None):
return (start, end, step)
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)
# Note that for non-lists and non-tuples the slice is computed
# differently
self.assertEqual(pSlicer[-3:][0], 1)
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___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):
return 42
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):
from zope.proxy._compat import PY3
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):
from zope.proxy._compat import PY3
# 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)
def test_coerce(self):
from zope.proxy._compat import PY3
if PY3: # No coercion in Python 3
return
# 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))
# XXX: PyPy 2.5.0 has a bug where proxys around types
# aren't correctly hashable, which breaks this part of the
# test. This is fixed in 2.5.1, but as of 2015-05-28,
# TravisCI still uses 2.5.0.
proxy_type = proxy_class(builtin_type)
from zope.interface.declarations import BuiltinImplementationSpecifications
if proxy_type in BuiltinImplementationSpecifications \
and BuiltinImplementationSpecifications.get(proxy_type, self) is not self:
provided_type = implementedBy(proxy_type)
self.assertTrue(IFoo in list(provided_type))
else:
import sys
self.assertEqual((2,5,0), sys.pypy_version_info[:3])
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__'):
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):
# XXX Implementation difference: This works in the
# Pure-Python version, but fails in CPython.
# See https://github.com/zopefoundation/zope.proxy/issues/4
proxy = self._makeOne("14")
try:
self.assertEqual(14, int(proxy))
except TypeError:
from zope.proxy import PyProxyBase
self.assertNotEqual(self._getTargetClass(), PyProxyBase)
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 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))))
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)
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(unittest.TestCase):
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)
def test_security_proxy(self):
class C(object):
pass
c = C()
proxy = self._makeSecurityProxy(c)
self.assertTrue(self._callFUT(proxy) is c)
class Test_removeAllProxies(unittest.TestCase):
def _callFUT(self, *args):
from zope.proxy import removeAllProxies
return removeAllProxies(*args)
def _makeProxy(self, obj):
from zope.proxy import ProxyBase
return ProxyBase(obj)
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):
return 'PROXY'
@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 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):
return "" % self.value
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ModuleConformanceCase),
unittest.makeSuite(PyProxyBaseTestCase),
unittest.makeSuite(ProxyBaseTestCase),
unittest.makeSuite(Test_py_getProxiedObject),
unittest.makeSuite(Test_getProxiedObject),
unittest.makeSuite(Test_py_setProxiedObject),
unittest.makeSuite(Test_setProxiedObject),
unittest.makeSuite(Test_py_isProxy),
unittest.makeSuite(Test_isProxy),
unittest.makeSuite(Test_py_sameProxiedObjects),
unittest.makeSuite(Test_sameProxiedObjects),
unittest.makeSuite(Test_py_queryProxy),
unittest.makeSuite(Test_queryProxy),
unittest.makeSuite(Test_py_queryInnerProxy),
unittest.makeSuite(Test_queryInnerProxy),
unittest.makeSuite(Test_py_removeAllProxies),
unittest.makeSuite(Test_removeAllProxies),
unittest.makeSuite(Test_ProxyIterator),
unittest.makeSuite(Test_nonOverridable),
unittest.makeSuite(Test_py__module),
unittest.makeSuite(Test__module),
unittest.makeSuite(Test_py_subclass__module),
unittest.makeSuite(Test_subclass__module),
))
zope.proxy-4.2.0/src/zope/proxy/proxy.h 0000664 0001750 0001750 00000003157 12450532143 021304 0 ustar tseaver tseaver 0000000 0000000 #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.2.0/src/zope/proxy/_zope_proxy_proxy.c 0000664 0001750 0001750 00000101634 12533354637 023747 0 ustar tseaver tseaver 0000000 0000000 /*############################################################################
#
# 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 IS_STRING PyString_Check
#define MAKE_STRING(name) PyString_AS_STRING(name)
#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 IS_STRING PyUnicode_Check
#define MAKE_STRING(name) PyBytes_AS_STRING( \
PyUnicode_AsUTF8String(name))
#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)
{
(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 && defined(Py_USING_UNICODE)
/* The Unicode to string conversion is done here because the
existing tp_setattro slots expect a string object as name
(except under Python 3) and we wouldn't want to break those. */
if (PyUnicode_Check(name)) {
name = PyUnicode_AsEncodedString(name, NULL, NULL);
if (name == NULL)
return NULL;
}
else
#endif
if (!IS_STRING(name)){
PyErr_SetString(PyExc_TypeError, "attribute name must be string");
return NULL;
}
else
Py_INCREF(name);
name_as_string = MAKE_STRING(name);
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:
Py_DECREF(name);
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 && defined(Py_USING_UNICODE)
/* The Unicode to string conversion is done here because the
existing tp_setattro slots expect a string object as name
(except under Python 3) and we wouldn't want to break those. */
if (PyUnicode_Check(name)) {
name = PyUnicode_AsEncodedString(name, NULL, NULL);
if (name == NULL)
return -1;
}
else
#endif
if (!IS_STRING(name)){
PyErr_SetString(PyExc_TypeError, "attribute name must be string");
return -1;
}
else
Py_INCREF(name);
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;
}
name_as_string = MAKE_STRING(name);
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:
Py_DECREF(name);
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)
{
PyObject *obj = Proxy_GET_OBJECT(self);
if (PyList_Check(obj)) {
return PyList_GetSlice(obj, start, end);
}
else if (PyTuple_Check(obj)) {
return PyTuple_GetSlice(obj, start, end);
}
else {
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.2.0/src/zope/__init__.py 0000664 0001750 0001750 00000000070 12450532143 020671 0 ustar tseaver tseaver 0000000 0000000 __import__('pkg_resources').declare_namespace(__name__)
zope.proxy-4.2.0/COPYRIGHT.txt 0000664 0001750 0001750 00000000040 12450532143 017122 0 ustar tseaver tseaver 0000000 0000000 Zope Foundation and Contributors zope.proxy-4.2.0/CHANGES.rst 0000664 0001750 0001750 00000011430 12712651507 016627 0 ustar tseaver tseaver 0000000 0000000 Changes
=======
4.2.0 (2016-05-05)
------------------
- Correctly strip ``zope.security`` proxies in ``removeAllProxies``.
- 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.2.0/LICENSE.txt 0000664 0001750 0001750 00000004026 12450532143 016644 0 ustar tseaver tseaver 0000000 0000000 Zope 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.2.0/README.rst 0000664 0001750 0001750 00000002024 12661101454 016505 0 ustar tseaver tseaver 0000000 0000000 ``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.png?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__`).
zope.proxy-4.2.0/docs/ 0000775 0001750 0001750 00000000000 12712651560 015755 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/docs/api.rst 0000664 0001750 0001750 00000004477 12450532143 017266 0 ustar tseaver tseaver 0000000 0000000 :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.2.0/docs/make.bat 0000664 0001750 0001750 00000011756 12450532143 017366 0 ustar tseaver tseaver 0000000 0000000 @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.2.0/docs/Makefile 0000664 0001750 0001750 00000012710 12450532143 017410 0 ustar tseaver tseaver 0000000 0000000 # 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.2.0/docs/_static/ 0000775 0001750 0001750 00000000000 12712651560 017403 5 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/docs/_static/.gitignore 0000664 0001750 0001750 00000000000 12460222640 021352 0 ustar tseaver tseaver 0000000 0000000 zope.proxy-4.2.0/docs/conf.py 0000664 0001750 0001750 00000017450 12450532143 017255 0 ustar tseaver tseaver 0000000 0000000 # -*- 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.2.0/docs/index.rst 0000664 0001750 0001750 00000000306 12457464662 017630 0 ustar tseaver tseaver 0000000 0000000 :mod:`zope.proxy`
=================
Contents:
.. toctree::
:maxdepth: 2
narr
api
hacking
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
zope.proxy-4.2.0/docs/narr.rst 0000664 0001750 0001750 00000006151 12450532143 017446 0 ustar tseaver tseaver 0000000 0000000 :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.2.0/docs/hacking.rst 0000664 0001750 0001750 00000021121 12460223710 020100 0 ustar tseaver tseaver 0000000 0000000 Hacking 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.2.0/MANIFEST.in 0000664 0001750 0001750 00000000242 12450532143 016553 0 ustar tseaver tseaver 0000000 0000000 include *.rst
include *.txt
recursive-include docs *
recursive-include src *
global-exclude *.dll
global-exclude *.pyc
global-exclude *.pyo
global-exclude *.so
zope.proxy-4.2.0/rtd.txt 0000664 0001750 0001750 00000000034 12462241706 016353 0 ustar tseaver tseaver 0000000 0000000 repoze.sphinx.autointerface