[Zope-dev] ZopeSecurityPolicy global manipulation
Martin Aspeli
optilude+lists at gmail.com
Thu Dec 29 20:35:12 UTC 2011
Hi,
AccessControl.ZopeSecurityPolicy contains this code:
from types import MethodType
# AccessControl.Implementation inserts:
# ZopeSecurityPolicy, getRoles, rolesForPermissionOn
from AccessControl.SimpleObjectPolicies import _noroles
rolesForPermissionOn = None # XXX: avoid import loop
tuple_or_list = tuple, list
def getRoles(container, name, value, default):
global rolesForPermissionOn # XXX: avoid import loop
if rolesForPermissionOn is None:
from PermissionRole import rolesForPermissionOn
roles = getattr(value, '__roles__', _noroles)
if roles is _noroles:
if not name or not isinstance(name, basestring):
return default
if type(value) is MethodType:
container = value.im_self
cls = getattr(container, '__class__', None)
if cls is None:
return default
roles = getattr(cls, name+'__roles__', _noroles)
if roles is _noroles:
return default
value = container
if roles is None or isinstance(roles, tuple_or_list):
return roles
rolesForPermissionOn = getattr(roles, 'rolesForPermissionOn', None)
if rolesForPermissionOn is not None:
roles = rolesForPermissionOn(value)
return roles
Look carefully at how ``rolesForPermissionOn`` is used both at the
top, to lazily set a global to avoid an import loop, and the bottom,
as an attribute of the ``roles`` object.
I'm pretty sure this is wrong™ on many levels, but most importantly,
it seems the global is being overwritten each time execution gets down
to that last block. I know this module gets munged by Implementation,
but I'm pretty sure ImplPython doesn't define getRoles() at least, and
I'm not even sure the C implementation does either.
To prove it to myself, I made a frivolous equivalent that used
'datetime.date' as the importable. It's a bit ugly, but you get the
idea:
>>> date = None
>>> class C(object):
... def __init__(self, d):
... self.date = d
...
>>> c1 = C(lambda: 'x')
>>> c2 = C(lambda: 'y')
>>> def get(c):
... global date
... if date is None:
... from datetime import date
... date = getattr(c, 'date', None)
... if date is not None:
... print date()
...
>>> date is None
True
>>> get(c1)
x
>>> date
<function <lambda> at 0x10dac8140>
>>> get(c2)
y
>>> date
<function <lambda> at 0x10dac8cf8>
>>>
Surely, this is all evil volatile? Maybe the global bit just needs to
go away? It doesn't seem to be used in that function, and I'm pretty
sure the implementation ends up overwriting the global anyway.
Cheers,
Martin
More information about the Zope-Dev
mailing list