Commit 86951172 authored by Jérome Perrin's avatar Jérome Perrin

ERP5Type: make TempBase use TemporaryDocumentMixin

Now that TemporaryDocumentMixin and TempBase implementation details have
been made consistent, there's no reason to duplicate code.

This also make TempBase uses TemporaryDocumentMixin of __setstate__, so
TempBase have more sane behaviour when being pickled.
parent b2e03135
Pipeline #19399 failed with stage
in 0 seconds
...@@ -82,6 +82,14 @@ class SessionToolTestCase(ERP5TypeTestCase): ...@@ -82,6 +82,14 @@ class SessionToolTestCase(ERP5TypeTestCase):
session = self.portal.portal_sessions[self.session_id] session = self.portal.portal_sessions[self.session_id]
self.assertEqual(primitives_kw, session) self.assertEqual(primitives_kw, session)
def test_store_temp_base(self):
portal_sessions = self.portal.portal_sessions
from Products.ERP5Type.Document import newTempBase
session = portal_sessions.newContent(
self.session_id,
temp_base=newTempBase(self.portal, 'temp_base', title='Temp Base'))
self.assertEqual(session['temp_base'].getTitle(), 'Temp Base')
def test_store_temp_object(self): def test_store_temp_object(self):
portal_sessions = self.portal.portal_sessions portal_sessions = self.portal.portal_sessions
session = portal_sessions.newContent( session = portal_sessions.newContent(
......
...@@ -70,6 +70,7 @@ from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter ...@@ -70,6 +70,7 @@ from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from Products.ERP5Type.Accessor.TypeDefinition import list_types from Products.ERP5Type.Accessor.TypeDefinition import list_types
from Products.ERP5Type.Accessor import Base as BaseAccessor from Products.ERP5Type.Accessor import Base as BaseAccessor
from Products.ERP5Type.mixin.property_translatable import PropertyTranslatableBuiltInDictMixIn from Products.ERP5Type.mixin.property_translatable import PropertyTranslatableBuiltInDictMixIn
from Products.ERP5Type.mixin.temporary import TemporaryDocumentMixin
from Products.ERP5Type.XMLExportImport import Base_asXML from Products.ERP5Type.XMLExportImport import Base_asXML
from Products.ERP5Type.Cache import CachingMethod, clearCache, getReadOnlyTransactionCache from Products.ERP5Type.Cache import CachingMethod, clearCache, getReadOnlyTransactionCache
from .Accessor import WorkflowState from .Accessor import WorkflowState
...@@ -3626,51 +3627,16 @@ def removeIContentishInterface(cls): ...@@ -3626,51 +3627,16 @@ def removeIContentishInterface(cls):
removeIContentishInterface(Base) removeIContentishInterface(Base)
class TempBase(Base): class TempBase(TemporaryDocumentMixin, Base):
"""A version of Base that does not persist in ZODB. """A version of Base that does not persist in ZODB.
This class only has the Base methods, so most of the times it is This class only has the Base methods, so most of the times it is
preferable to use a temporary portal type instead. preferable to use a temporary portal type instead.
""" """
isIndexable = ConstantGetter('isIndexable', value=False)
isTempDocument = ConstantGetter('isTempDocument', value=True)
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
def reindexObject(self, *args, **kw):
pass
def recursiveReindexObject(self, *args, **kw):
pass
def activate(self, *args, **kw):
return self
def setUid(self, value):
self.uid = value # Required for Listbox so that no casting happens when we use TempBase to create new objects
def setTitle(self, value):
"""
Required so that getProperty('title') will work on tempBase objects
The dynamic acquisition work very well for a lot of properties, but
not for title. For example, if we do setProperty('organisation_url'), then
even if organisation_url is not in a propertySheet, the method getOrganisationUrl
will be generated. But this does not work for title, because I(seb)'m almost sure
there is somewhere a method '_setTitle' or 'setTitle' with no method getTitle on Base.
That why setProperty('title') and getProperty('title') does not work.
"""
self.title = value
def getTitle(self):
"""
Returns the title of this document
"""
return getattr(aq_base(self), 'title', None)
security.declarePublic('setProperty') security.declarePublic('setProperty')
security.declarePublic('getProperty') security.declarePublic('getProperty')
security.declarePublic('edit') security.declarePublic('edit')
# Persistence.Persistent is one of the superclasses of TempBase, and on Zope2.8 # Persistence.Persistent is one of the superclasses of TempBase, and on Zope2.8
......
...@@ -41,7 +41,7 @@ from OFS.Folder import Folder as OFS_Folder ...@@ -41,7 +41,7 @@ from OFS.Folder import Folder as OFS_Folder
from persistent import Persistent, wref from persistent import Persistent, wref
from ZODB.serialize import ObjectWriter, ObjectReader from ZODB.serialize import ObjectWriter, ObjectReader
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.Base import Base, WorkflowMethod from Products.ERP5Type.Base import Base, TempBase, WorkflowMethod
log = logging.getLogger('ERP5Type') log = logging.getLogger('ERP5Type')
log.trace = lambda *args, **kw: log.log(5, *args, **kw) log.trace = lambda *args, **kw: log.log(5, *args, **kw)
...@@ -165,6 +165,8 @@ if 1: ...@@ -165,6 +165,8 @@ if 1:
if klass.__module__ in ('erp5.portal_type', 'erp5.temp_portal_type'): if klass.__module__ in ('erp5.portal_type', 'erp5.temp_portal_type'):
return Base__setstate__(self, value) return Base__setstate__(self, value)
if klass is TempBase:
return Base__setstate__(self, value)
try: try:
portal_type = value.get('portal_type') or klass.portal_type portal_type = value.get('portal_type') or klass.portal_type
except AttributeError: except AttributeError:
......
...@@ -236,7 +236,7 @@ class TestERP5Type(ERP5TypeTestCase, LogInterceptor): ...@@ -236,7 +236,7 @@ class TestERP5Type(ERP5TypeTestCase, LogInterceptor):
'newTemp*(self, ID) will be removed, use self.newContent(temp_object=True, id=ID, portal_type=...)', 'newTemp*(self, ID) will be removed, use self.newContent(temp_object=True, id=ID, portal_type=...)',
DeprecationWarning, 2) DeprecationWarning, 2)
def test_03_NewTempObject(self): def test_newTempBase(self):
# Products.ERP5Type.Document.newTempBase is another (not recommended) way # Products.ERP5Type.Document.newTempBase is another (not recommended) way
# of creating temp objects # of creating temp objects
import Products.ERP5Type.Document import Products.ERP5Type.Document
...@@ -246,19 +246,33 @@ class TestERP5Type(ERP5TypeTestCase, LogInterceptor): ...@@ -246,19 +246,33 @@ class TestERP5Type(ERP5TypeTestCase, LogInterceptor):
self.assertTrue(o.isTempObject()) self.assertTrue(o.isTempObject())
self.assertTrue(guarded_import("Products.ERP5Type.Document", fromlist=["newTempBase"])) self.assertTrue(guarded_import("Products.ERP5Type.Document", fromlist=["newTempBase"]))
def test_TempObjectPersistent(self): def _test_temp_object_persistent(self, temp_object):
# Temp objects can not be stored in ZODB # Temp objects can not be stored in ZODB
temp_object = self.portal.person_module.newContent(portal_type='Person', temp_object=True)
self.assertTrue(temp_object.isTempObject()) self.assertTrue(temp_object.isTempObject())
# they can be pickled # they can be pickled
self.assertTrue(pickle.dumps(aq_base(temp_object))) self.assertTrue(pickle.dumps(aq_base(temp_object)))
# they can be unpickled
import ZODB.broken
self.assertNotIsInstance(
pickle.loads(pickle.dumps(aq_base(temp_object))),
ZODB.broken.Broken,
)
# but they can not be saved in ZODB accidentally # but they can not be saved in ZODB accidentally
self.portal.person_module.oops = temp_object self.portal.person_module.oops = temp_object
self.assertRaisesRegexp(Exception, "Temporary objects can't be pickled", self.commit) self.assertRaisesRegexp(Exception, "Temporary objects can't be pickled", self.commit)
self.abort() self.abort()
def test_temp_object_persistent(self):
temp_object = self.portal.person_module.newContent(portal_type='Person', temp_object=True)
self._test_temp_object_persistent(temp_object)
def test_newTempBase_persistent(self):
import Products.ERP5Type.Document
temp_object = Products.ERP5Type.Document.newTempBase(self.portal, 'id')
self._test_temp_object_persistent(temp_object)
def test_warnings_redirected_to_event_log(self): def test_warnings_redirected_to_event_log(self):
self._catch_log_errors() self._catch_log_errors()
self.addCleanup(self._ignore_log_errors) self.addCleanup(self._ignore_log_errors)
......
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