diff --git a/product/ERP5Type/Cache.py b/product/ERP5Type/Cache.py index b1471012af02f0c190229a0d29439ca1cf0805af..2b9f571712c566ca9d9fceec3b8be5d839fd8ef3 100644 --- a/product/ERP5Type/Cache.py +++ b/product/ERP5Type/Cache.py @@ -33,6 +33,7 @@ from AccessControl.SecurityInfo import allow_class from CachePlugins.BaseCache import CachedMethodError from zLOG import LOG, WARNING from Products.ERP5Type.TransactionalVariable import getTransactionalVariable +from Products.ERP5Type.Utils import simple_decorator from warnings import warn DEFAULT_CACHE_SCOPE = 'GLOBAL' @@ -281,6 +282,7 @@ def generateCacheIdWithoutFirstArg(method_id, *args, **kwd): def caching_instance_method(*args, **kw): kw.setdefault('cache_id_generator', generateCacheIdWithoutFirstArg) + @simple_decorator def wrapped(method): # The speed of returned function must be fast # so we instanciate CachingMethod now. @@ -293,6 +295,7 @@ def caching_instance_method(*args, **kw): return wrapped def transactional_cached(key_method=lambda *args: args): + @simple_decorator def decorator(function): key = repr(function) def wrapper(*args, **kw): @@ -303,7 +306,5 @@ def transactional_cached(key_method=lambda *args: args): except KeyError: cache[subkey] = result = function(*args, **kw) return result - wrapper.__doc__ = function.__doc__ - wrapper.__name__ = function.__name__ return wrapper return decorator diff --git a/product/ERP5Type/UnrestrictedMethod.py b/product/ERP5Type/UnrestrictedMethod.py index 85ff8a88f57c011284d6ec5cd3d2e584bcb97962..733458c5967a457dcb3557e496907fe80120011c 100644 --- a/product/ERP5Type/UnrestrictedMethod.py +++ b/product/ERP5Type/UnrestrictedMethod.py @@ -34,6 +34,7 @@ try: from Zope2 import app except ImportError: from Zope import app +from Products.ERP5Type.Utils import simple_decorator class PrivilegedUser(UnrestrictedUser): """User that bypasses all security checks, but retains an original @@ -48,6 +49,7 @@ class PrivilegedUser(UnrestrictedUser): """Get the ID of the user. This is disabled in UnrestrictedUser.""" return self.getUserName() +@simple_decorator def UnrestrictedMethod(function): """Decorator to bypass all security checks. @@ -66,10 +68,7 @@ def UnrestrictedMethod(function): This method is dangerous. Enough said. Be careful. """ - wrapper = lambda *args, **kw: unrestricted_apply(function, args, kw) - wrapper.__doc__ = function.__doc__ - wrapper.__name__ = function.__name__ - return wrapper + return lambda *args, **kw: unrestricted_apply(function, args, kw) def unrestricted_apply(function, args=(), kw={}): """Function to bypass all security checks diff --git a/product/ERP5Type/Utils.py b/product/ERP5Type/Utils.py index db55b57acf074678e979ae6a875099967fc46a9c..91ada44ab11917a60a59229c0d28fa6046a9adbf 100644 --- a/product/ERP5Type/Utils.py +++ b/product/ERP5Type/Utils.py @@ -65,6 +65,27 @@ from Products.PageTemplates.Expressions import getEngine from Products.PageTemplates.Expressions import SecureModuleImporter from Products.ZCatalog.Lazy import LazyMap +def simple_decorator(decorator): + """Decorator to turn simple function into well-behaved decorator + + See also http://wiki.python.org/moin/PythonDecoratorLibrary + + XXX We should use http://pypi.python.org/pypi/decorator/ instead, + to make decorators ZPublisher-friendly. + """ + def new_decorator(f): + g = decorator(f) + g.__name__ = f.__name__ + g.__doc__ = f.__doc__ + g.__dict__.update(f.__dict__) + return g + # Now a few lines needed to make simple_decorator itself + # be a well-behaved decorator. + new_decorator.__name__ = decorator.__name__ + new_decorator.__doc__ = decorator.__doc__ + new_decorator.__dict__.update(decorator.__dict__) + return new_decorator + from Products.ERP5Type import Permissions from Products.ERP5Type.Accessor.Constant import PropertyGetter as \ @@ -194,6 +215,7 @@ def _showwarning(message, category, filename, lineno, file=None, line=None): file.write(warnings.formatwarning(message, category, filename, lineno)) warnings.showwarning = _showwarning +@simple_decorator def deprecated(wrapped): message = "Use of '%s' function (%s, line %s) is deprecated." % ( wrapped.__name__, wrapped.__module__, wrapped.func_code.co_firstlineno)