Commit 3a5ac55b authored by Julien Muchembled's avatar Julien Muchembled

Add helper to easily monkey-patch many attributes of an object

Use it on PythonScript & ExternalMethod.
parent b9c41350
......@@ -14,9 +14,11 @@
from inspect import getargs
from Products.ExternalMethod.ExternalMethod import *
from Products.ERP5Type.Globals import InitializeClass
from . import PatchClass
from .PythonScript import addGuard
if 1:
class _(PatchClass(ExternalMethod)):
def getFunction(self, reload=False, f=None):
"""
Patch to get ZODB Component Extension function if available, otherwise
......@@ -43,8 +45,6 @@ if 1:
return f
ExternalMethod.getFunction = getFunction
ExternalMethod_reloadIfChanged = ExternalMethod.reloadIfChanged
def reloadIfChanged(self):
try:
......@@ -55,8 +55,6 @@ if 1:
except ImportError:
return ExternalMethod_reloadIfChanged(self)
ExternalMethod.reloadIfChanged = reloadIfChanged
def __call__(self, *args, **kw):
"""Call an ExternalMethod
......@@ -137,10 +135,8 @@ if 1:
raise TypeError, v, tb
finally: tb=None
ExternalMethod.__call__ = __call__
ExternalMethod.security = ClassSecurityInfo()
security = ClassSecurityInfo()
addGuard(ExternalMethod, change_external_methods)
addGuard(ExternalMethod, change_external_methods)
InitializeClass(ExternalMethod)
InitializeClass(ExternalMethod)
......@@ -14,6 +14,7 @@ from Products.DCWorkflow.Guard import Guard
from Products.PythonScripts.PythonScript import PythonScript
from App.special_dtml import DTMLFile
from .. import _dtmldir
from . import PatchClass
from AccessControl import ClassSecurityInfo, getSecurityManager
from AccessControl.class_init import InitializeClass
from AccessControl.PermissionRole import rolesForPermissionOn
......@@ -22,46 +23,6 @@ from App.ImageFile import ImageFile
from Acquisition import aq_base, aq_parent
from zExceptions import Forbidden
security = ClassSecurityInfo()
PythonScript.security = security
def haveProxyRole(self):
"""if a script has proxy role, return True"""
return bool(self._proxy_roles)
def om_icons(self):
"""Return a list of icon URLs to be displayed by an ObjectManager"""
icons = ({'path': 'misc_/PythonScripts/pyscript.gif',
'alt': self.meta_type, 'title': self.meta_type},)
if self.haveProxyRole():
icons = ({'path': 'p_/PythonScript_ProxyRole_icon',
'alt': 'Proxy Roled Python Script',
'title': 'This script has proxy role.'},)
return icons
pyscript_proxyrole = ImageFile('pyscript_proxyrole.gif', globals())
#
# Add proxy role icon in ZMI
#
security.declarePrivate('haveProxyRole')
PythonScript.haveProxyRole = haveProxyRole
PythonScript.om_icons = om_icons
p_.PythonScript_ProxyRole_icon = pyscript_proxyrole
# Patch for displaying textearea in full window instead of
# remembering a quantity of lines to display in a cookie
manage_editForm = DTMLFile("pyScriptEdit", _dtmldir)
manage_editForm._setName('manage_editForm')
PythonScript.ZPythonScriptHTML_editForm = manage_editForm
PythonScript.manage_editForm = manage_editForm
PythonScript.manage = manage_editForm
PythonScript.manage_main = manage_editForm
PythonScript.manage_editDocument = manage_editForm
PythonScript.manage_editForm = manage_editForm
### Guards
_guard_manage_options = (
......@@ -184,15 +145,42 @@ def addGuard(cls, set_permission):
security.declareProtected(set_permission, 'manage_setGuard')
cls.manage_setGuard = manage_setGuard
###
addGuard(PythonScript, 'Change Python Scripts')
class _(PatchClass(PythonScript)):
security = ClassSecurityInfo()
# Add proxy role icon in ZMI
def om_icons(self):
"""Return a list of icon URLs to be displayed by an ObjectManager"""
if self._proxy_roles:
return {'path': 'p_/PythonScript_ProxyRole_icon',
'alt': 'Proxy Roled Python Script',
'title': 'This script has proxy role.'},
return {'path': 'misc_/PythonScripts/pyscript.gif',
'alt': self.meta_type, 'title': self.meta_type},
def __call__(self, *args, **kw):
'''Calls the script.'''
self.checkGuard(True) # patch
return self._bindAndExec(args, kw, None)
p_.PythonScript_ProxyRole_icon = \
ImageFile('pyscript_proxyrole.gif', globals())
security.declarePublic("render")
PythonScript.__call__ = PythonScript.render = __call__
# Patch for displaying textearea in full window instead of
# remembering a quantity of lines to display in a cookie
manage = manage_editDocument = manage_main = ZPythonScriptHTML_editForm = \
manage_editForm = DTMLFile("pyScriptEdit", _dtmldir)
manage_editForm._setName('manage_editForm')
# Guards
def __call__(self, *args, **kw):
'''Calls the script.'''
self.checkGuard(True) # patch
return self._bindAndExec(args, kw, None)
security.declarePublic("render")
render = __call__
addGuard(PythonScript, 'Change Python Scripts')
InitializeClass(PythonScript)
class PatchClass(tuple):
"""Helper to easily monkey-patch many attributes of an object
>>> class Foo(object):
... def f(self):
... return 1
...
>>> class _(PatchClass(Foo)):
... _f = Foo.f
... def f(self):
... return - self._f()
...
>>> Foo().f()
-1
"""
def __new__(cls, *args):
if len(args) == 1:
return tuple.__new__(cls, args)
_, ((cls,),), d = args
for k, v in d.iteritems():
k == "__module__" or setattr(cls, k, v.im_func
if getattr(v, "im_class", None) is cls and v.im_self is None
else v)
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