From 5e35e6d4c0467d97363313386c4cc7a18484032d Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine <arnaud.fontaine@nexedi.com> Date: Wed, 20 Apr 2022 10:55:43 +0200 Subject: [PATCH] py3: No more unbound methods in python3. --- product/CMFActivity/tests/testCMFActivity.py | 21 ++++++++++++++----- product/ERP5/ERP5Site.py | 6 +++++- product/ERP5/Interaction.py | 6 +++++- product/ERP5/InteractionWorkflow.py | 8 ++++--- product/ERP5/mixin/timer_service.py | 20 ++++++++++++------ .../ERP5Type/dynamic/persistent_migration.py | 8 ++++++- product/ERP5Type/patches/ExternalMethod.py | 5 ++++- product/ERP5Type/tests/backportUnittest.py | 10 +++++++-- 8 files changed, 64 insertions(+), 20 deletions(-) diff --git a/product/CMFActivity/tests/testCMFActivity.py b/product/CMFActivity/tests/testCMFActivity.py index 2cec1738f6..d0165dfcbd 100644 --- a/product/CMFActivity/tests/testCMFActivity.py +++ b/product/CMFActivity/tests/testCMFActivity.py @@ -1883,7 +1883,10 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): Speed up test by not interrupting the first transaction as soon as we have the information we want. """ - original_query = DB.query.__func__ + original_query = DB.query + import six + if six.PY2: + original_query = original_query.__func__ def query(self, query_string, *args, **kw): if query_string.startswith('INSERT'): insert_list.append(len(query_string)) @@ -2054,7 +2057,10 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): def testTryNotificationSavedOnEventLogWhenNotifyUserRaises(self, activity): obj = self.portal.organisation_module.newContent(portal_type='Organisation') self.tic() - original_notifyUser = Message.notifyUser.im_func + original_notifyUser = Message.notifyUser + import six + if six.PY2: + original_notifyUser = original_notifyUser.__func__ def failSendingEmail(self, *args, **kw): raise MailHostError('Mail is not sent') activity_unit_test_error = Exception() @@ -2084,7 +2090,10 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): def testNotificationFailureIsNotSavedOnEventLogWhenMailNotificationIsDisabled(self, activity): obj = self.portal.organisation_module.newContent(portal_type='Organisation') self.tic() - original_notifyUser = Message.notifyUser.im_func + original_notifyUser = Message.notifyUser + import six + if six.PY2: + original_notifyUser = original_notifyUser.__func__ def failSendingEmail(self, *args, **kw): raise MailHostError('Mail is not sent') activity_unit_test_error = Exception() @@ -2152,8 +2161,10 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): def failingMethod(self): raise activity_unit_test_error from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog - original_raising = SiteErrorLog.raising.im_func - + original_raising = SiteErrorLog.raising + import six + if six.PY2: + original_raising = original_raising.__func__ # Monkey patch Site Error to induce conflict errors artificially. def raising(self, info): raise AttributeError diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py index 44cab4b730..ac2775857d 100644 --- a/product/ERP5/ERP5Site.py +++ b/product/ERP5/ERP5Site.py @@ -19,6 +19,7 @@ from __future__ import absolute_import from DateTime import DateTime from six.moves import map import thread, threading +import six from weakref import ref as weakref from OFS.Application import Application, AppInitializer from Products.ERP5Type import Globals @@ -2437,7 +2438,10 @@ class ERP5Generator(PortalGenerator): # Zope offers no mechanism to extend AppInitializer so let's monkey-patch. -AppInitializer_initialize = AppInitializer.initialize.__func__ +AppInitializer_initialize = AppInitializer.initialize +if six.PY2: + # No more unbound methods in py3 + AppInitializer_initialize = AppInitializer_initialize.__func__ def initialize(self): AppInitializer.initialize = AppInitializer_initialize self.initialize() diff --git a/product/ERP5/Interaction.py b/product/ERP5/Interaction.py index 2af4042ccb..ff5858e2a4 100644 --- a/product/ERP5/Interaction.py +++ b/product/ERP5/Interaction.py @@ -304,7 +304,11 @@ class InteractionDefinition (SimpleItem): def checkGuard(self, *args, **kwargs): from Products.ERP5Type.mixin.guardable import GuardableMixin - return GuardableMixin.checkGuard.im_func(self, *args, **kwargs) + checkGuard = GuardableMixin.checkGuard + import six + if six.PY2: + checkGuard = checkGuard.__func__ + return checkGuard(self, *args, **kwargs) def getPortalTypeGroupFilterList(self): if self.portal_type_group_filter is None: diff --git a/product/ERP5/InteractionWorkflow.py b/product/ERP5/InteractionWorkflow.py index 2b65f56d69..65e6d7ecc8 100644 --- a/product/ERP5/InteractionWorkflow.py +++ b/product/ERP5/InteractionWorkflow.py @@ -391,8 +391,10 @@ for method_name, security in ( ): if security is not None: security(method_name) - setattr(InteractionWorkflowDefinition, - method_name, - getattr(ERP5InteractionWorkflow, method_name).im_func) + func = getattr(ERP5InteractionWorkflow, method_name) + import six + if six.PY2: + func = func.__func__ + setattr(InteractionWorkflowDefinition, method_name, func) Globals.InitializeClass(InteractionWorkflowDefinition) diff --git a/product/ERP5/mixin/timer_service.py b/product/ERP5/mixin/timer_service.py index b16a2f6cad..55ffbfd1c7 100644 --- a/product/ERP5/mixin/timer_service.py +++ b/product/ERP5/mixin/timer_service.py @@ -26,7 +26,7 @@ # ############################################################################## -import warnings +import warnings, six from AccessControl import ClassSecurityInfo from Products.ERP5Type.Globals import InitializeClass from Products.CMFActivity.ActivityTool import ActivityTool @@ -79,11 +79,19 @@ class TimerServiceMixin(object): self.subscribe() super(TimerServiceMixin, self).manage_afterAdd(*args, **kw) - security.declarePublic('getCurrentNode') - getCurrentNode = ActivityTool.getCurrentNode.im_func - security.declarePublic('getServerAddress') - getServerAddress = ActivityTool.getServerAddress.im_func + if six.PY2: + security.declarePublic('getCurrentNode') + getCurrentNode = ActivityTool.getCurrentNode.__func__ + security.declarePublic('getServerAddress') + getServerAddress = ActivityTool.getServerAddress.__func__ + _isValidNodeName = ActivityTool._isValidNodeName.__func__ + else: + # no more unbound in py3, we got the function directly + security.declarePublic('getCurrentNode') + getCurrentNode = ActivityTool.getCurrentNode + security.declarePublic('getServerAddress') + getServerAddress = ActivityTool.getServerAddress + _isValidNodeName = ActivityTool._isValidNodeName - _isValidNodeName = ActivityTool._isValidNodeName.im_func InitializeClass(TimerServiceMixin) diff --git a/product/ERP5Type/dynamic/persistent_migration.py b/product/ERP5Type/dynamic/persistent_migration.py index a3aa70280f..07f60ec284 100644 --- a/product/ERP5Type/dynamic/persistent_migration.py +++ b/product/ERP5Type/dynamic/persistent_migration.py @@ -96,7 +96,13 @@ class PickleUpdater(ObjectReader, ObjectWriter, object): if _setOb: if isinstance(_setOb, WorkflowMethod): _setOb = _setOb._m - if _setOb.im_func is OFS_Folder._setOb.im_func: + import six + setOb_func = _setOb + OFS_Folder_setOb_func = OFS_Folder._setOb + if six.PY2: + setOb_func = setOb_func.__func__ + OFS_Folder_setOb_func = OFS_Folder_setOb.__func__ + if setOb_func is OFS_Folder_setOb_func: self.lazy = Ghost elif klass.__module__[:7] == 'BTrees.' and klass.__name__ != 'Length': self.lazy = LazyBTree() diff --git a/product/ERP5Type/patches/ExternalMethod.py b/product/ERP5Type/patches/ExternalMethod.py index d9f4cfe1c2..0ba5167792 100644 --- a/product/ERP5Type/patches/ExternalMethod.py +++ b/product/ERP5Type/patches/ExternalMethod.py @@ -88,7 +88,10 @@ class _(PatchClass(ExternalMethod)): arg_list.append('**' + argument_object.keywords) i = isinstance(f, MethodType) - ff = f.__func__ if i else f + ff = f + import six + if six.PY2 and i: + ff = f.__func__ has_self = len(arg_list) > i and arg_list[i] == 'self' i += has_self if i: diff --git a/product/ERP5Type/tests/backportUnittest.py b/product/ERP5Type/tests/backportUnittest.py index 4c47ca09f9..2a679fa50a 100644 --- a/product/ERP5Type/tests/backportUnittest.py +++ b/product/ERP5Type/tests/backportUnittest.py @@ -12,7 +12,10 @@ def patch(): import traceback from unittest import TextTestResult, TextTestRunner - TextTestResult_addError = TextTestResult.addError.__func__ + TextTestResult_addError = TextTestResult.addError + import six + if six.PY2: + TextTestResult_addError = TextTestResult_addError.__func__ def addError(self, test, err): if isinstance(err[1], SetupSiteError): self.errors.append(None) @@ -40,7 +43,10 @@ def patch(): self.stream.writeln("SUCCESS: %s" % self.getDescription(test)) TextTestResult.printErrors = printErrors - TextTestRunner_run = TextTestRunner.run.__func__ + TextTestRunner_run = TextTestRunner.run + import six + if six.PY2: + TextTestRunner_run = TextTestRunner_run.__func__ def run(self, test): def t(result): try: -- 2.30.9