Commit d29dda25 authored by Boxiang Sun's avatar Boxiang Sun
Browse files

Original implementation

parents
=======
CHANGES
=======
3.7.4 (2010-09-25)
------------------
- Added not declared, but needed test dependency on `zope.testing`.
3.7.3 (2010-04-30)
------------------
- Prefer the standard libraries doctest module to the one from zope.testing.
- Fixed directlyProvides IVocabularyFactory for PermissionIdsVocabulary in
Python code, even if it's unnecessary because IVocabularyFactory is provided
in zcml.
- Removed the dependency on the zope.exceptions package: zope.security.checker
now imports ``DuplicationError`` from zope.exceptions if available, otherwise
it defines a package-specific ``DuplicationError`` class which inherits from
Exception.
3.7.2 (2009-11-10)
------------------
- Added compatibility with Python 2.6 abstract base classes.
3.7.1 (2009-08-13)
------------------
- Fix for LP bug 181833 (from Gustavo Niemeyer). Before "visiting" a
sub-object, a check should be made to ensure the object is still valid.
Because garbage collection may involve loops, if you garbage collect an
object, it is possible that the actions done on this object may modify the
state of other objects. This may cause another round of garbage collection,
eventually generating a segfault (see LP bug). The Py_VISIT macro does the
necessary checks, so it is used instead of the previous code.
3.7.0 (2009-05-13)
------------------
- Made ``pytz`` a soft dependency: the checker for ``pytz.UTC`` is
created / tested only if the package is already present. Run
``bin/test_pytz`` to run the tests with ``pytz`` on the path.
3.6.3 (2009-03-23)
------------------
- Ensure that simple zope.schema's VocabularyRegistry is used for
PermissionVocabulary tests, because it's replaced implicitly in
environments with zope.app.schema installed that makes that tests
fail.
- Fixed a bug in DecoratedSecurityCheckerDescriptor which made
security-wrapping location proxied exception instances throw
exceptions on Python 2.5.
See https://bugs.launchpad.net/zope3/+bug/251848
3.6.2 (2009-03-14)
------------------
- Add zope.i18nmessageid.Message to non-proxied basic types. It's okay, because
messages are immutable. It was done by zope.app.security before.
- Add "__name__" and "__parent__" attributes to list of available by default.
This was also done by zope.app.security package before.
- Added PermissionsVocabulary and PermissionIdsVocabulary vocabularies
to the ``zope.security.permission`` module. They were moved from
the ``zope.app.security`` package.
- Add zcml permission definitions for most common and useful permissions,
like "zope.View" and "zope.ManageContent", as well as for the special
"zope.Public" permission. They are placed in a separate "permissions.zcml"
file, so it can be easily excluded/redefined. They are selected part of
permissions moved from ``zope.app.security`` and used by many zope.*
packages.
- Add `addCheckerPublic` helper function in ``zope.security.testing`` module
that registers the "zope.Public" permission as an IPermission utility.
- Add security declarations for the ``zope.security.permisson.Permission`` class.
- Improve test coverage.
3.6.1 (2009-03-10)
------------------
- Use ``from`` imports instead of ``zope.deferred`` to avoid circular
import problems, thus drop dependency on ``zope.deferredimport``.
- Raise NoInteraction when zope.security.checkPermission is called
without interaction being active (LP #301565).
- Don't define security checkers for deprecated set types from the
"sets" module on Python 2.6. It's discouraged to use them and
`set` and `frozenset` built-in types should be used instead.
- Change package's mailng list address to zope-dev at zope.org as
zope3-dev at zope.org is now retired.
- Remove old zpkg-related files.
3.6.0 (2009-01-31)
------------------
- Install decorated security checker support on LocationProxy from the
outside.
- Added support to bootstrap on Jython.
- Moved the `protectclass` module from `zope.app.security` to this
package to reduce the number of dependencies on `zope.app.security`.
- Moved the <module> directive implementation from `zope.app.security`
to this package.
- Moved the <class> directive implementation from `zope.app.component`
to this package.
3.5.2 (2008-07-27)
------------------
- Made C code compatible with Python 2.5 on 64bit architectures.
3.5.1 (2008-06-04)
------------------
- Add `frozenset`, `set`, `reversed`, and `sorted` to the list of safe
builtins.
3.5.0 (2008-03-05)
------------------
- Changed title for ``zope.security.management.system_user`` to be more
presentable.
3.4.0 (2007-10-02)
------------------
- Updated meta-data.
3.4.0b5 (2007-08-15)
--------------------
- Bug: Fixed a circular import in the C implementation.
3.4.0b4 (2007-08-14)
--------------------
- Bug: ``zope.security.management.system_user`` had an ugly/brittle id.
3.4.0b3 (2007-08-14)
--------------------
- ``zope.security`` now works on Python 2.5
- Bug: ``zope.security.management.system_user`` wasn't a valid principal
(didn't provide IPrincipal).
- Bug: Fixed inclusion of doctest to use the doctest module from
``zope.testing``. Now tests can be run multiple times without
breaking. (#98250)
3.4.0b2 (2007-06-15)
--------------------
- Bug: Removed stack extraction in newInteraction. When using eggs this is an
extremly expensive function. The publisher is now more than 10 times faster
when using eggs and about twice as fast with a zope trunk checkout.
3.4.0b1
-------
- Temporarily fixed the hidden (and accidental) dependency on zope.testing to
become optional.
Note: The releases between 3.2.0 and 3.4.0b1 where not tracked as an
individual package and have been documented in the Zope 3 changelog.
3.2.0 (2006-01-05)
------------------
- Corresponds to the verison of the zope.security package shipped as part of
the Zope 3.2.0 release.
- Removed deprecated helper functions, 'proxy.trustedRemoveSecurityProxy' and
'proxy.getProxiedObject'.
- Made handling of 'management.{end,restore}Interaction' more careful w.r.t.
edge cases.
- Made behavior of 'canWrite' consistent with 'canAccess': if 'canAccess'
does not raise 'ForbiddenAttribute', then neither will 'canWrite'. See:
http://www.zope.org/Collectors/Zope3-dev/506
- Code style / documentation / test fixes.
3.1.0 (2005-10-03)
------------------
- Added support for use of the new Python 2.4 datatypes, 'set' and
'frozenset', within checked code.
- C security proxy acquired a dependency on the 'proxy.h' header from the
'zope.proxy' package.
- XXX: the spelling of the '#include' is bizarre! It seems to be related to
'zpkg'-based builds, and should likely be revisited. For the moment, I have
linked in the 'zope.proxy' package into our own 'include' directory. See
the subversion checkin: http://svn.zope.org/Zope3/?rev=37882&view=rev
- Updated checker to avoid re-proxying objects which have and explicit
'__Security_checker__' assigned.
- Corresponds to the verison of the zope.security package shipped as part of
the Zope 3.1.0 release.
- Clarified contract of 'IChecker' to indicate that its 'check*' methods may
raise only 'Forbidden' or 'Unauthorized' exceptions.
- Added interfaces, ('IPrincipal', 'IGroupAwarePrincipal', 'IGroup', and
'IPermission') specifying contracts of components in the security framework.
- Code style / documentation / test fixes.
3.0.0 (2004-11-07)
------------------
- Corresponds to the version of the zope.security package shipped as part of
the Zope X3.0.0 release.
This diff is collapsed.
The Security framework provides a generic mechanism to implement security
policies on Python objects.
##############################################################################
#
# 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.
$Id: bootstrap.py 111760 2010-04-30 21:52:18Z hannosch $
"""
import os, shutil, sys, tempfile, urllib2
from optparse import OptionParser
tmpeggs = tempfile.mkdtemp()
is_jython = sys.platform.startswith('java')
# parsing arguments
parser = OptionParser()
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="distribute", default=False,
help="Use Disribute rather than Setuptools.")
parser.add_option("-c", None, action="store", dest="config_file",
help=("Specify the path to the buildout configuration "
"file to be used."))
options, args = parser.parse_args()
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args += ['-c', options.config_file]
if options.version is not None:
VERSION = '==%s' % options.version
else:
VERSION = ''
USE_DISTRIBUTE = options.distribute
args = args + ['bootstrap']
to_reload = False
try:
import pkg_resources
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
raise ImportError
except ImportError:
ez = {}
if USE_DISTRIBUTE:
exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
).read() in ez
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
else:
exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
).read() in ez
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
if to_reload:
reload(pkg_resources)
else:
import pkg_resources
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
def quote (c):
return c
cmd = 'from setuptools.command.easy_install import main; main()'
ws = pkg_resources.working_set
if USE_DISTRIBUTE:
requirement = 'distribute'
else:
requirement = 'setuptools'
if is_jython:
import subprocess
assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
quote(tmpeggs), 'zc.buildout' + VERSION],
env=dict(os.environ,
PYTHONPATH=
ws.find(pkg_resources.Requirement.parse(requirement)).location
),
).wait() == 0
else:
assert os.spawnle(
os.P_WAIT, sys.executable, quote (sys.executable),
'-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION,
dict(os.environ,
PYTHONPATH=
ws.find(pkg_resources.Requirement.parse(requirement)).location
),
) == 0
ws.add_entry(tmpeggs)
ws.require('zc.buildout' + VERSION)
import zc.buildout.buildout
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)
[buildout]
develop = .
parts = test test_pytz python coverage-test coverage-report
[test]
recipe = zc.recipe.testrunner
eggs = zope.security [test]
[test_pytz]
recipe = zc.recipe.testrunner
eggs = zope.security [test,pytz]
[python]
recipe = zc.recipe.egg
eggs = zope.security [untrustedpython]
interpreter = python
[coverage-test]
recipe = zc.recipe.testrunner
eggs = zope.security [test]
defaults = ['--coverage', '../../coverage']
[coverage-report]
recipe = zc.recipe.egg
eggs = z3c.coverage
scripts = coverage=coverage-report
arguments = ('coverage', 'coverage/report')
##############################################################################
#
# 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.
"""
from zope.interface import moduleProvides
from zope.proxy.interfaces import IProxyIntrospection
from zope.proxy._zope_proxy_proxy import *
from zope.proxy._zope_proxy_proxy import _CAPI
moduleProvides(IProxyIntrospection)
__all__ = tuple(IProxyIntrospection)
def ProxyIterator(p):
yield p
while isProxy(p):
p = getProxiedObject(p)
yield p
def non_overridable(func):
return property(lambda self: func.__get__(self))
This diff is collapsed.
##############################################################################
#
# 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
>>> from zope.interface import *
>>> class I1(Interface):
... pass
>>> class I2(Interface):
... pass
>>> class I3(Interface):
... pass
>>> class I4(Interface):
... pass
>>> class D1(SpecificationDecoratorBase):
... implements(I1)
>>> class D2(SpecificationDecoratorBase):
... implements(I2)
>>> class X(object):
... implements(I3)
>>> x = X()
>>> directlyProvides(x, I4)
Interfaces of X are ordered with the directly-provided interfaces first
>>> [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.
>>> [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:
>>> class X:
... implements(I3)
>>> 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']
"""
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()
##############################################################################
#
# 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.
"""
#ifndef _proxy_H_
#define _proxy_H_ 1
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
typedef int Py_ssize_t;
#define PY_SSIZE_T_MAX INT_MAX
#define PY_SSIZE_T_MIN INT_MIN
typedef Py_ssize_t (*lenfunc)(PyObject *);
typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t);
typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *);
typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
#endif
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 (PyCObject_Check(tmp))
_proxy_api = (ProxyInterface *)
PyCObject_AsVoidPtr(tmp);
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_ */
#
# This file is necessary to make this directory a package.
##############################################################################
#
# 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
"""
from doctest import DocTestSuite
def test_suite():
suite = DocTestSuite()
suite.addTest(DocTestSuite('zope.proxy.decorator'))
return suite
##############################################################################
#
# 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.
"""
from doctest import DocTestSuite
import pickle
import sys
import unittest
from zope.proxy import ProxyBase
import zope.proxy
class Thing:
"""This class is expected to be a classic class."""
class Comparable(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
if hasattr(other, "value"):
other = other.value
return self.value == other
def __ne__(self, other):
return not self.__eq__(other)
def __lt__(self, other):
if hasattr(other, "value"):
other = other.value
return self.value < other
def __ge__(self, other):
return not self.__lt__(other)
def __le__(self, other):
if hasattr(other, "value"):
other = other.value
return self.value <= other
def __gt__(self, other):
return not self.__le__(other)
def __repr__(self):
return "<Comparable: %r>" % self.value
class ProxyTestCase(unittest.TestCase):
proxy_class = ProxyBase
def setUp(self):
self.x = Thing()
self.p = self.new_proxy(self.x)
def new_proxy(self, o):
return self.proxy_class(o)
def test_constructor(self):
o = object()
self.assertRaises(TypeError, self.proxy_class, o, o)
self.assertRaises(TypeError, self.proxy_class, o, key='value')
self.assertRaises(TypeError, self.proxy_class, key='value')
def test_subclass_constructor(self):
class MyProxy(self.proxy_class):
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.assertEquals(o1, o[0])
self.assertEquals(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.proxy_class):
def __new__(cls, *args, **kwds):
return super(MyProxy2, cls).__new__(cls, 'value')
p = MyProxy2('splat!')
self.assertEquals(list(p), 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')
p = MyProxy3('notused')
self.assertEquals(list(p), list('another'))
def test_proxy_attributes(self):
o = Thing()
o.foo = 1
w = self.new_proxy(o)
self.assert_(w.foo == 1)
def test___class__(self):
o = object()
w = self.new_proxy(o)
self.assert_(w.__class__ is o.__class__)
def test_pickle_prevention(self):
w = self.new_proxy(Thing())
self.assertRaises(pickle.PicklingError,
pickle.dumps, w)
def test_proxy_equality(self):
w = self.new_proxy('foo')
self.assertEquals(w, 'foo')
o1 = Comparable(1)
o2 = Comparable(1.0)
o3 = Comparable("splat!")
w1 = self.new_proxy(o1)
w2 = self.new_proxy(o2)
w3 = self.new_proxy(o3)
self.assertEquals(o1, w1)
self.assertEquals(o1, w2)
self.assertEquals(o2, w1)
self.assertEquals(w1, o2)
self.assertEquals(w2, o1)
self.assertNotEquals(o3, w1)
self.assertNotEquals(w1, o3)
self.assertNotEquals(w3, o1)
self.assertNotEquals(o1, w3)
def test_proxy_ordering_lt(self):
o1 = Comparable(1)
o2 = Comparable(2.0)
w1 = self.new_proxy(o1)
w2 = self.new_proxy(o2)
self.assert_(w1 < w2)
self.assert_(w1 <= w2)
self.assert_(o1 < w2)
self.assert_(o1 <= w2)
self.assert_(w1 < o2)
self.assert_(w2 <= o2)
def test_proxy_callable(self):
w = self.new_proxy({}.get)
self.assert_(callable(w))
def test_proxy_item_protocol(self):
w = self.new_proxy({})
self.assertRaises(KeyError, lambda: w[1])
w[1] = 'a'
self.assertEquals(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_wrapped_iterable(self):
a = [1, 2, 3]
b = []
for x in self.new_proxy(a):
b.append(x)
self.assertEquals(a, b)
def test_iteration_over_proxy(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.new_proxy(iter(a)):
b.append(x)
self.assertEquals(a, b)
t = tuple(self.new_proxy(iter(a)))
self.assertEquals(t, (1, 2, 3))
def test_iteration_using_proxy(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.new_proxy(iter(self.data))
a = [1, 2, 3]
b = []
for x in Iterable(self, a):
b.append(x)
self.assertEquals(a, b)
def test_bool_wrapped_None(self):
w = self.new_proxy(None)
self.assertEquals(not w, 1)
# Numeric ops.
unops = [
"-x", "+x", "abs(x)", "~x",
"int(x)", "long(x)", "float(x)",
]
def test_unops(self):
P = self.new_proxy
for expr in self.unops:
x = 1
y = eval(expr)
x = P(1)
z = eval(expr)
self.assertEqual(z, y,
"x=%r; expr=%r" % (x, expr))
def test_odd_unops(self):
# unops that don't return a proxy
P = self.new_proxy
for func in hex, oct, lambda x: not x:
self.assertEqual(func(P(100)), func(100))
binops = [
"x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y",
"x<<y", "x>>y", "x&y", "x|y", "x^y",
]
def test_binops(self):
P = self.new_proxy
for expr in self.binops:
first = 1
for x in [1, P(1)]:
for y in [2, P(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_inplace(self):
# TODO: should test all inplace operators...
P = self.new_proxy
pa = P(1)
pa += 2
self.assertEqual(pa, 3)
a = [1, 2, 3]
pa = qa = P(a)
pa += [4, 5, 6]
self.failUnless(pa is qa)
self.assertEqual(a, [1, 2, 3, 4, 5, 6])
pa = P(2)
pa **= 2
self.assertEqual(pa, 4)
def test_coerce(self):
P = self.new_proxy
# Before 2.3, coerce() of two proxies returns them unchanged
fixed_coerce = sys.version_info >= (2, 3, 0)
x = P(1)
y = P(2)
a, b = coerce(x, y)
self.failUnless(a is x and b is y)
x = P(1)
y = P(2.1)
a, b = coerce(x, y)
self.failUnless(a == 1.0)
self.failUnless(b is y)
if fixed_coerce:
self.failUnless(a.__class__ is float, a.__class__)
x = P(1.1)
y = P(2)
a, b = coerce(x, y)
self.failUnless(a is x)
self.failUnless(b == 2.0)
if fixed_coerce:
self.failUnless(b.__class__ is float, b.__class__)
x = P(1)
y = 2
a, b = coerce(x, y)
self.failUnless(a is x)
self.failUnless(b is y)
x = P(1)
y = 2.1
a, b = coerce(x, y)
self.failUnless(a.__class__ is float, a.__class__)
self.failUnless(b is y)
x = P(1.1)
y = 2
a, b = coerce(x, y)
self.failUnless(a is x)
self.failUnless(b.__class__ is float, b.__class__)
x = 1
y = P(2)
a, b = coerce(x, y)
self.failUnless(a is x)
self.failUnless(b is y)
x = 1.1
y = P(2)
a, b = coerce(x, y)
self.failUnless(a is x)
self.failUnless(b.__class__ is float, b.__class__)
x = 1
y = P(2.1)
a, b = coerce(x, y)
self.failUnless(a.__class__ is float, a.__class__)
self.failUnless(b is y)
def test_getslice(self):
# Lists have special slicing bahvior.
pList = self.new_proxy([1, 2])
self.assertEqual(pList[-1:], [2])
self.assertEqual(pList[-2:], [1, 2])
self.assertEqual(pList[-3:], [1, 2])
# Tuples also have special slicing behavior.
pTuple = self.new_proxy((1, 2))
self.assertEqual(pTuple[-1:], (2,))
self.assertEqual(pTuple[-2:], (1, 2))
self.assertEqual(pTuple[-3:], (1, 2))
# 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.new_proxy(DerivedList([1, 2]))
self.assertEqual(pList[-1:], [2])
self.assertEqual(pList[-2:], [1, 2])
self.assertEqual(pList[-3:], [1, 2])
# Another sort of sequence has a different slicing interpretation.
class Slicer(object):
def __len__(self):
return 2
def __getslice__(self, start, end, step=None):
return (start, end, step)
pSlicer = self.new_proxy(Slicer())
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(self):
# Lists have special slicing bahvior for assignment as well.
pList = self.new_proxy([1, 2])
pList[-1:] = [3, 4]
self.assertEqual(pList, [1, 3, 4])
pList = self.new_proxy([1, 2])
pList[-2:] = [3, 4]
self.assertEqual(pList, [3, 4])
pList = self.new_proxy([1, 2])
pList[-3:] = [3, 4]
self.assertEqual(pList, [3, 4])
# This behavior should be true for all list-derived classes.
class DerivedList(list):
pass
pList = self.new_proxy(DerivedList([1, 2]))
pList[-1:] = [3, 4]
self.assertEqual(pList, [1, 3, 4])
pList = self.new_proxy(DerivedList([1, 2]))
pList[-2:] = [3, 4]
self.assertEqual(pList, [3, 4])
pList = self.new_proxy(DerivedList([1, 2]))
pList[-3:] = [3, 4]
self.assertEqual(pList, [3, 4])
def test_isProxy():
"""
>>> from zope.proxy import ProxyBase, isProxy
>>> class P1(ProxyBase):
... pass
>>> class P2(ProxyBase):
... pass
>>> class C(object):
... pass
>>> c = C()
>>> int(isProxy(c))
0
>>> p = P1(c)
>>> int(isProxy(p))
1
>>> int(isProxy(p, P1))
1
>>> int(isProxy(p, P2))
0
>>> p = P2(p)
>>> int(isProxy(p, P1))
1
>>> int(isProxy(p, P2))
1
"""
def test_getProxiedObject():
"""
>>> from zope.proxy import ProxyBase, getProxiedObject
>>> class C(object):
... pass
>>> c = C()
>>> int(getProxiedObject(c) is c)
1
>>> p = ProxyBase(c)
>>> int(getProxiedObject(p) is c)
1
>>> p2 = ProxyBase(p)
>>> int(getProxiedObject(p2) is p)
1
"""
def test_ProxyIterator():
"""
>>> from zope.proxy import ProxyBase, ProxyIterator
>>> class C(object):
... pass
>>> c = C()
>>> p1 = ProxyBase(c)
>>> class P(ProxyBase):
... pass
>>> p2 = P(p1)
>>> p3 = ProxyBase(p2)
>>> list(ProxyIterator(p3)) == [p3, p2, p1, c]
1
"""
def test_removeAllProxies():
"""
>>> from zope.proxy import ProxyBase, removeAllProxies
>>> class C(object):
... pass
>>> c = C()
>>> int(removeAllProxies(c) is c)
1
>>> p = ProxyBase(c)
>>> int(removeAllProxies(p) is c)
1
>>> p2 = ProxyBase(p)
>>> int(removeAllProxies(p2) is c)
1
"""
def test_queryProxy():
"""
>>> from zope.proxy import ProxyBase, queryProxy
>>> class P1(ProxyBase):
... pass
>>> class P2(ProxyBase):
... pass
>>> class C(object):
... pass
>>> c = C()
>>> queryProxy(c, P1)
>>> queryProxy(c, P1, 42)
42
>>> p1 = P1(c)
>>> int(queryProxy(p1, P1) is p1)
1
>>> queryProxy(c, P2)
>>> queryProxy(c, P2, 42)
42
>>> p2 = P2(p1)
>>> int(queryProxy(p2, P1) is p1)
1
>>> int(queryProxy(p2, P2) is p2)
1
>>> int(queryProxy(p2, ProxyBase) is p2)
1
"""
def test_queryInnerProxy():
"""
>>> from zope.proxy import ProxyBase, queryProxy, queryInnerProxy
>>> class P1(ProxyBase):
... pass
>>> class P2(ProxyBase):
... pass
>>> class C(object):
... pass
>>> c = C()
>>> queryInnerProxy(c, P1)
>>> queryInnerProxy(c, P1, 42)
42
>>> p1 = P1(c)
>>> int(queryProxy(p1, P1) is p1)
1
>>> queryInnerProxy(c, P2)
>>> queryInnerProxy(c, P2, 42)
42
>>> p2 = P2(p1)
>>> int(queryInnerProxy(p2, P1) is p1)
1
>>> int(queryInnerProxy(p2, P2) is p2)
1
>>> int(queryInnerProxy(p2, ProxyBase) is p1)
1
>>> p3 = P1(p2)
>>> int(queryProxy(p3, P1) is p3)
1
>>> int(queryInnerProxy(p3, P1) is p1)
1
>>> int(queryInnerProxy(p3, P2) is p2)
1
"""
def test_sameProxiedObjects():
"""
>>> from zope.proxy import ProxyBase, sameProxiedObjects
>>> class C(object):
... pass
>>> c1 = C()
>>> c2 = C()
>>> int(sameProxiedObjects(c1, c1))
1
>>> int(sameProxiedObjects(ProxyBase(c1), c1))
1
>>> int(sameProxiedObjects(ProxyBase(c1), ProxyBase(c1)))
1
>>> int(sameProxiedObjects(ProxyBase(ProxyBase(c1)), c1))
1
>>> int(sameProxiedObjects(c1, ProxyBase(c1)))
1
>>> int(sameProxiedObjects(c1, ProxyBase(ProxyBase(c1))))
1
>>> int(sameProxiedObjects(c1, c2))
0
>>> int(sameProxiedObjects(ProxyBase(c1), c2))
0
>>> int(sameProxiedObjects(ProxyBase(c1), ProxyBase(c2)))
0
>>> int(sameProxiedObjects(ProxyBase(ProxyBase(c1)), c2))
0
>>> int(sameProxiedObjects(c1, ProxyBase(c2)))
0
>>> int(sameProxiedObjects(c1, ProxyBase(ProxyBase(c2))))
0
"""
def test_subclassing_proxies():
"""You can subclass 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.
>>> class MyProxy(ProxyBase):
... __slots__ = 'x', 'y'
...
... def f(self):
... return self.x
>>> l = [1, 2, 3]
>>> p = MyProxy(l)
I can use attributes defined by the class, including slots:
>>> p.x = 'x'
>>> p.x
'x'
>>> p.f()
'x'
I can also use attributes of the proxied object:
>>> p
[1, 2, 3]
>>> p.pop()
3
>>> p
[1, 2]
"""
def test_get_descriptors_in_proxy_class():
"""
A non-data descriptor in a proxy class doesn't hide an attribute on
a proxied object or prevent writing the attribute.
>>> class ReadDescr(object):
... def __get__(self, i, c):
... return 'read'
>>> 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)
"""
def test_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.
>>> class MyProxy(ProxyBase):
... __slots__ = ()
...
... @zope.proxy.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'
"""
def test_setProxiedObject():
"""
>>> 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:
>>> 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:
>>> try:
... setProxiedObject(c1, None)
... except TypeError:
... print "TypeError raised"
... else:
... print "Expected TypeError not raised"
TypeError raised
"""
def test_suite():
suite = unittest.makeSuite(ProxyTestCase)
suite.addTest(DocTestSuite())
return suite
if __name__ == "__main__":
runner = unittest.TextTestRunner(sys.stdout)
result = runner.run(test_suite())
newerrs = len(result.errors) + len(result.failures)
sys.exit(newerrs and 1 or 0)
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
##############################################################################
#
# Copyright (c) 2006 Zope Corporation 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.security package
$Id: setup.py 116839 2010-09-25 11:20:03Z icemac $
"""
import os
from setuptools import setup, find_packages, Extension
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
setup(name='zope.security',
version='3.7.4',
author='Zope Corporation and Contributors',
author_email='zope-dev@zope.org',
description='Zope Security Framework',
long_description=(
read('README.txt')
+ '\n.. contents::\n\n' +
read('src', 'zope', 'security', 'README.txt')
+ '\n\n' +
read('src', 'zope', 'security', 'untrustedinterpreter.txt')
+ '\n\n' +
read('CHANGES.txt')
),
keywords = "zope security policy principal permission",
classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Programming Language :: Python',
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
'Framework :: Zope3'],
url='http://pypi.python.org/pypi/zope.security',
license='ZPL 2.1',
packages=find_packages('src'),
package_dir = {'': 'src'},
namespace_packages=['zope'],
ext_modules=[Extension("zope.security._proxy",
[os.path.join('src', 'zope', 'security',
"_proxy.c")
], include_dirs=['include']),
Extension("zope.security._zope_security_checker",
[os.path.join('src', 'zope', 'security',
"_zope_security_checker.c")
]),
],
install_requires=['setuptools',
'zope.component',
'zope.configuration',
'zope.i18nmessageid',
'zope.interface',
'zope.location',
'zope.proxy >= 3.4.2',
'zope.schema',
],
extras_require = dict(
untrustedpython=["RestrictedPython"],
test=[
"RestrictedPython",
"zope.testing",
],
pytz=["pytz"],
),
include_package_data = True,
zip_safe = False,
)
This diff is collapsed.
CHANGES.txt
README.txt
bootstrap.py
buildout.cfg
setup.py
include/zope.proxy/__init__.py
include/zope.proxy/_zope_proxy_proxy.c
include/zope.proxy/decorator.py
include/zope.proxy/interfaces.py
include/zope.proxy/proxy.h
include/zope.proxy/tests/__init__.py
include/zope.proxy/tests/test_decorator.py
include/zope.proxy/tests/test_proxy.py
src/zope/__init__.py
src/zope.security.egg-info/PKG-INFO
src/zope.security.egg-info/SOURCES.txt
src/zope.security.egg-info/dependency_links.txt
src/zope.security.egg-info/namespace_packages.txt
src/zope.security.egg-info/not-zip-safe
src/zope.security.egg-info/requires.txt
src/zope.security.egg-info/top_level.txt
src/zope/security/README.txt
src/zope/security/__init__.py
src/zope/security/_definitions.py
src/zope/security/_proxy.c
src/zope/security/_zope_security_checker.c
src/zope/security/adapter.py
src/zope/security/checker.py
src/zope/security/configure.zcml
src/zope/security/decorator.py
src/zope/security/i18n.py
src/zope/security/interfaces.py
src/zope/security/management.py
src/zope/security/meta.zcml
src/zope/security/metaconfigure.py
src/zope/security/metadirectives.py
src/zope/security/permission.py
src/zope/security/permissions.zcml
src/zope/security/protectclass.py
src/zope/security/proxy.py
src/zope/security/setup.py
src/zope/security/simplepolicies.py
src/zope/security/testing.py
src/zope/security/untrustedinterpreter.txt
src/zope/security/zcml.py
src/zope/security/examples/sandbox.py
src/zope/security/examples/sandbox_security.py
src/zope/security/tests/__init__.py
src/zope/security/tests/adapter.py
src/zope/security/tests/components.py
src/zope/security/tests/emptymodule.py
src/zope/security/tests/exampleclass.py
src/zope/security/tests/module.py
src/zope/security/tests/modulehookup.py
src/zope/security/tests/redefineperms.zcml
src/zope/security/tests/test_adapter.py
src/zope/security/tests/test_checker.py
src/zope/security/tests/test_contentdirective.py
src/zope/security/tests/test_decorator.py
src/zope/security/tests/test_directives.py
src/zope/security/tests/test_location.py
src/zope/security/tests/test_management.py
src/zope/security/tests/test_module_directives.py
src/zope/security/tests/test_permission.py
src/zope/security/tests/test_protectclass.py
src/zope/security/tests/test_protectsubclass.py
src/zope/security/tests/test_proxy.py
src/zope/security/tests/test_set_checkers.py
src/zope/security/tests/test_simpleinteraction.py
src/zope/security/tests/test_standard_checkers.py
src/zope/security/untrustedpython/__init__.py
src/zope/security/untrustedpython/builtins.py
src/zope/security/untrustedpython/builtins.txt
src/zope/security/untrustedpython/interpreter.py
src/zope/security/untrustedpython/interpreter.txt
src/zope/security/untrustedpython/rcompile.py
src/zope/security/untrustedpython/rcompile.txt
src/zope/security/untrustedpython/tests.py
\ No newline at end of file
zope
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment