appy.gen: use new index 'getState' for indexing object states; reduced size of generated file config.py; optimized debug mode: class reload is not done automatically: a 'refresh' icon is available on view and edit views.
This commit is contained in:
parent
9258b76bdf
commit
b6dcc42038
|
@ -326,7 +326,6 @@ class Search:
|
|||
elif fieldName == 'description':
|
||||
if usage == 'search': return 'Description'
|
||||
else: return None
|
||||
elif fieldName == 'state': return 'review_state'
|
||||
else:
|
||||
return 'get%s%s'% (fieldName[0].upper(),fieldName[1:])
|
||||
@staticmethod
|
||||
|
@ -487,24 +486,27 @@ class Type:
|
|||
called for storing the name of the Appy field (p_name) and other
|
||||
attributes that are based on the name of the Appy p_klass, and the
|
||||
application name (p_appName).'''
|
||||
if hasattr(self, 'name'): return # Already initialized
|
||||
self.name = name
|
||||
# Determine prefix for this class
|
||||
if not klass: prefix = appName
|
||||
else: prefix = getClassName(klass, appName)
|
||||
# Recompute the ID (and derived attributes) that may have changed if
|
||||
# we are in debug mode (because we recreate new Type instances).
|
||||
self.id = id(self)
|
||||
if self.slaves: self.master_css = 'appyMaster master_%s' % self.id
|
||||
# Determine ids of i18n labels for this field
|
||||
labelName = name
|
||||
prefix = None
|
||||
trPrefix = None
|
||||
if self.label:
|
||||
if isinstance(self.label, basestring): prefix = self.label
|
||||
else: # It is a tuple (prefix, name)
|
||||
if isinstance(self.label, basestring): trPrefix = self.label
|
||||
else: # It is a tuple (trPrefix, name)
|
||||
if self.label[1]: labelName = self.label[1]
|
||||
if self.label[0]: prefix = self.label[0]
|
||||
if not prefix:
|
||||
if not klass: prefix = appName
|
||||
else: prefix = getClassName(klass, appName)
|
||||
if self.label[0]: trPrefix = self.label[0]
|
||||
if not trPrefix:
|
||||
trPrefix = prefix
|
||||
# Determine name to use for i18n
|
||||
self.labelId = '%s_%s' % (prefix, labelName)
|
||||
self.labelId = '%s_%s' % (trPrefix, labelName)
|
||||
self.descrId = self.labelId + '_descr'
|
||||
self.helpId = self.labelId + '_help'
|
||||
# Determine read and write permissions for this field
|
||||
|
@ -522,9 +524,10 @@ class Type:
|
|||
self.writePermission = wp
|
||||
else:
|
||||
self.writePermission = 'Modify portal content'
|
||||
if isinstance(self, Ref):
|
||||
self.backd = self.back.__dict__
|
||||
if isinstance(self, Ref) and not self.isBack:
|
||||
# We must initialise the corresponding back reference
|
||||
self.back.klass = klass
|
||||
self.back.init(self.back.attribute, self.klass, appName)
|
||||
self.back.relationship = '%s_%s_rel' % (prefix, name)
|
||||
|
||||
def reload(self, klass, obj):
|
||||
|
@ -534,6 +537,7 @@ class Type:
|
|||
module has been performed.'''
|
||||
res = getattr(klass, self.name, None)
|
||||
if not res: return self
|
||||
if isinstance(self, Ref) and self.isBack: return self
|
||||
res.init(self.name, klass, obj.getProductConfig().PROJECTNAME)
|
||||
return res
|
||||
|
||||
|
@ -1693,6 +1697,7 @@ class Ref(Type):
|
|||
back.isBack = True
|
||||
back.back = self
|
||||
back.backd = self.__dict__
|
||||
setattr(klass, back.attribute, back)
|
||||
# When displaying a tabular list of referenced objects, must we show
|
||||
# the table headers?
|
||||
self.showHeaders = showHeaders
|
||||
|
@ -2487,7 +2492,7 @@ class Transition:
|
|||
targetState.updatePermissions(wf, obj)
|
||||
# Refresh catalog-related security if required
|
||||
if not obj.isTemporary():
|
||||
obj.reindexObject(idxs=('allowedRolesAndUsers','review_state'))
|
||||
obj.reindexObject(idxs=('allowedRolesAndUsers', 'getState'))
|
||||
# Execute the related action if needed
|
||||
msg = ''
|
||||
if doAction and self.action: msg = self.executeAction(obj, wf)
|
||||
|
@ -2654,12 +2659,4 @@ class Config:
|
|||
# Language that will be used as a basis for translating to other
|
||||
# languages.
|
||||
self.sourceLanguage = 'en'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Special field "type" is mandatory for every class. If one class does not
|
||||
# define it, we will add a copy of the instance defined below.
|
||||
title = String(multiplicity=(1,1), show='edit')
|
||||
title.init('title', None, 'appy')
|
||||
state = String()
|
||||
state.init('state', None, 'appy')
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -370,40 +370,21 @@ class Generator(AbstractGenerator):
|
|||
# Compute the list of ordered attributes (forward and backward,
|
||||
# inherited included) for every Appy class.
|
||||
attributes = []
|
||||
attributesDict = []
|
||||
for classDescr in classesAll:
|
||||
titleFound = False
|
||||
attrs = []
|
||||
attrNames = []
|
||||
names = []
|
||||
for name, appyType, klass in classDescr.getOrderedAppyAttributes():
|
||||
attrs.append(self.getAppyTypePath(name, appyType, klass))
|
||||
attrNames.append(name)
|
||||
names.append(name)
|
||||
if name == 'title': titleFound = True
|
||||
# Add the "title" mandatory field if not found
|
||||
if not titleFound:
|
||||
attrs.insert(0, 'copy.deepcopy(appy.gen.title)')
|
||||
attrNames.insert(0, 'title')
|
||||
if not titleFound: names.insert(0, 'title')
|
||||
# Any backward attributes to append?
|
||||
if classDescr.name in self.referers:
|
||||
for field, rel in self.referers[classDescr.name]:
|
||||
try:
|
||||
getattr(field.classDescr.klass, field.fieldName)
|
||||
klass = field.classDescr.klass
|
||||
except AttributeError:
|
||||
klass = field.classDescr.modelClass
|
||||
attrs.append(self.getAppyTypePath(field.fieldName,
|
||||
field.appyType, klass, isBack=True))
|
||||
attrNames.append(field.appyType.back.attribute)
|
||||
attributes.append('"%s":[%s]' % (classDescr.name,','.join(attrs)))
|
||||
aDict = ''
|
||||
i = -1
|
||||
for attr in attrs:
|
||||
i += 1
|
||||
aDict += '"%s":attributes["%s"][%d],' % \
|
||||
(attrNames[i], classDescr.name, i)
|
||||
attributesDict.append('"%s":{%s}' % (classDescr.name, aDict))
|
||||
names.append(field.appyType.back.attribute)
|
||||
qNames = ['"%s"' % name for name in names]
|
||||
attributes.append('"%s":[%s]' % (classDescr.name, ','.join(qNames)))
|
||||
repls['attributes'] = ',\n '.join(attributes)
|
||||
repls['attributesDict'] = ',\n '.join(attributesDict)
|
||||
# Compute list of used roles for registering them if needed
|
||||
specificRoles = self.getAllUsedRoles(plone=False)
|
||||
repls['roles'] = ','.join(['"%s"' % r.name for r in specificRoles])
|
||||
|
|
|
@ -6,7 +6,7 @@ import os, os.path, time
|
|||
from StringIO import StringIO
|
||||
from sets import Set
|
||||
import appy
|
||||
from appy.gen import Type, Ref
|
||||
from appy.gen import Type, Ref, String
|
||||
from appy.gen.po import PoParser
|
||||
from appy.gen.utils import produceNiceMessage
|
||||
from appy.gen.plone25.utils import updateRolesForPermission
|
||||
|
@ -231,10 +231,11 @@ class PloneInstaller:
|
|||
'''Creates or updates the POD templates in the tool according to pod
|
||||
declarations in the application classes.'''
|
||||
# Creates the templates for Pod fields if they do not exist.
|
||||
for contentType, appyTypes in self.attributes.iteritems():
|
||||
for contentType in self.attributes.iterkeys():
|
||||
appyClass = self.tool.getAppyClass(contentType)
|
||||
if not appyClass: continue # May be an abstract class
|
||||
for appyType in appyTypes:
|
||||
wrapperClass = self.tool.getAppyClass(contentType, wrapper=True)
|
||||
for appyType in wrapperClass.__fields__:
|
||||
if appyType.type != 'Pod': continue
|
||||
# Find the attribute that stores the template, and store on
|
||||
# it the default one specified in the appyType if no
|
||||
|
@ -290,6 +291,7 @@ class PloneInstaller:
|
|||
nvProps.manage_changeProperties(**{'idsNotToList': current})
|
||||
|
||||
self.tool = getattr(self.ploneSite, self.toolInstanceName)
|
||||
self.tool.refreshSecurity()
|
||||
self.appyTool = self.tool.appy()
|
||||
if self.reinstall:
|
||||
self.tool.createOrUpdate(False, None)
|
||||
|
@ -413,9 +415,12 @@ class PloneInstaller:
|
|||
def manageIndexes(self):
|
||||
'''For every indexed field, this method installs and updates the
|
||||
corresponding index if it does not exist yet.'''
|
||||
indexInfo = {}
|
||||
for className, appyTypes in self.attributes.iteritems():
|
||||
for appyType in appyTypes:
|
||||
# Create a special index for object state, that does not correspond to
|
||||
# a field.
|
||||
indexInfo = {'getState': 'FieldIndex'}
|
||||
for className in self.attributes.iterkeys():
|
||||
wrapperClass = self.tool.getAppyClass(className, wrapper=True)
|
||||
for appyType in wrapperClass.__fields__:
|
||||
if not appyType.indexed or (appyType.name == 'title'): continue
|
||||
n = appyType.name
|
||||
indexName = 'get%s%s' % (n[0].upper(), n[1:])
|
||||
|
@ -553,17 +558,25 @@ class ZopeInstaller:
|
|||
def completeAppyTypes(self):
|
||||
'''We complete here the initialisation process of every Appy type of
|
||||
every gen-class of the application.'''
|
||||
appName = self.productName
|
||||
for klass in self.classes:
|
||||
# Store on wrapper class the ordered list of Appy types
|
||||
wrapperClass = klass.wrapperClass
|
||||
if not hasattr(wrapperClass, 'title'):
|
||||
# Special field "type" is mandatory for every class.
|
||||
title = String(multiplicity=(1,1), show='edit', indexed=True)
|
||||
title.init('title', None, 'appy')
|
||||
setattr(wrapperClass, 'title', title)
|
||||
names = self.config.attributes[wrapperClass.__name__[:-8]]
|
||||
wrapperClass.__fields__ = [getattr(wrapperClass, n) for n in names]
|
||||
# Post-initialise every Appy type
|
||||
for baseClass in klass.wrapperClass.__bases__:
|
||||
if baseClass.__name__ == 'AbstractWrapper': continue
|
||||
for name, appyType in baseClass.__dict__.iteritems():
|
||||
if isinstance(appyType, Type):
|
||||
appyType.init(name, baseClass, self.productName)
|
||||
# Do not forget back references
|
||||
if isinstance(appyType, Ref):
|
||||
bAppyType = appyType.back
|
||||
bAppyType.init(bAppyType.attribute, appyType.klass,
|
||||
self.productName)
|
||||
bAppyType.klass = baseClass
|
||||
if not isinstance(appyType, Type) or \
|
||||
(isinstance(appyType, Ref) and appyType.isBack):
|
||||
continue # Back refs are initialised within fw refs
|
||||
appyType.init(name, baseClass, appName)
|
||||
|
||||
def installApplication(self):
|
||||
'''Performs some application-wide installation steps.'''
|
||||
|
|
|
@ -79,10 +79,9 @@ class ToolMixin(BaseMixin):
|
|||
def _appy_getAllFields(self, contentType):
|
||||
'''Returns the (translated) names of fields of p_contentType.'''
|
||||
res = []
|
||||
for appyType in self.getProductConfig().attributes[contentType]:
|
||||
if appyType.name != 'title': # Will be included by default.
|
||||
label = '%s_%s' % (contentType, appyType.name)
|
||||
res.append((appyType.name, self.translate(label)))
|
||||
for appyType in self.getAllAppyTypes(className=contentType):
|
||||
if appyType.name == 'title': continue # Will be included by default.
|
||||
res.append((appyType.name, self.translate(appyType.labelId)))
|
||||
# Add object state
|
||||
res.append(('workflowState', self.translate('workflow_state')))
|
||||
return res
|
||||
|
@ -91,7 +90,7 @@ class ToolMixin(BaseMixin):
|
|||
'''Returns the (translated) names of fields that may be searched on
|
||||
objects of type p_contentType (=indexed fields).'''
|
||||
res = []
|
||||
for appyType in self.getProductConfig().attributes[contentType]:
|
||||
for appyType in self.getAllAppyTypes(className=contentType):
|
||||
if appyType.indexed:
|
||||
res.append((appyType.name, self.translate(appyType.labelId)))
|
||||
return res
|
||||
|
@ -343,26 +342,23 @@ class ToolMixin(BaseMixin):
|
|||
def getPublishedObject(self):
|
||||
'''Gets the currently published object, if its meta_class is among
|
||||
application classes.'''
|
||||
rq = self.REQUEST
|
||||
obj = rq['PUBLISHED']
|
||||
obj = self.REQUEST['PUBLISHED']
|
||||
parent = obj.getParentNode()
|
||||
if parent.id == 'skyn':
|
||||
obj = parent.getParentNode()
|
||||
if obj.meta_type in self.getProductConfig().attributes:
|
||||
return obj
|
||||
return None
|
||||
if parent.id == 'skyn': obj = parent.getParentNode()
|
||||
if obj.meta_type in self.getProductConfig().attributes: return obj
|
||||
|
||||
def getAppyClass(self, contentType):
|
||||
def getAppyClass(self, contentType, wrapper=False):
|
||||
'''Gets the Appy Python class that is related to p_contentType.'''
|
||||
# Retrieve first the Archetypes class corresponding to p_ContentType
|
||||
portalType = self.portal_types.get(contentType)
|
||||
if not portalType: return None
|
||||
if not portalType: return
|
||||
atClassName = portalType.getProperty('content_meta_type')
|
||||
appName = self.getProductConfig().PROJECTNAME
|
||||
exec 'from Products.%s.%s import %s as atClass' % \
|
||||
(appName, atClassName, atClassName)
|
||||
# Get then the Appy Python class
|
||||
return atClass.wrapperClass.__bases__[-1]
|
||||
if wrapper: return atClass.wrapperClass
|
||||
else: return atClass.wrapperClass.__bases__[-1]
|
||||
|
||||
def getCreateMeans(self, contentTypeOrAppyClass):
|
||||
'''Gets the different ways objects of p_contentTypeOrAppyClass (which
|
||||
|
@ -395,6 +391,8 @@ class ToolMixin(BaseMixin):
|
|||
'''This method checks if the currently logged user can trigger searches
|
||||
on a given p_rootClass. This is done by calling method "maySearch"
|
||||
on the class. If no such method exists, we return True.'''
|
||||
# When editign a form, one should avoid annoying the user with this.
|
||||
if self.REQUEST['ACTUAL_URL'].endswith('/edit'): return
|
||||
pythonClass = self.getAppyClass(rootClass)
|
||||
if 'maySearch' in pythonClass.__dict__:
|
||||
return pythonClass.maySearch(self.appy())
|
||||
|
|
|
@ -51,10 +51,7 @@ class BaseMixin:
|
|||
for appyType in self.getAppyTypes('edit', rq.get('page')):
|
||||
value = getattr(values, appyType.name, None)
|
||||
appyType.store(obj, value)
|
||||
if created:
|
||||
# Now we have a title for the object, so we derive a nice id
|
||||
obj.unmarkCreationFlag()
|
||||
obj._renameAfterCreation(check_auto_id=True)
|
||||
if created: obj.unmarkCreationFlag()
|
||||
if previousData:
|
||||
# Keep in history potential changes on historized fields
|
||||
self.historizeData(previousData)
|
||||
|
@ -499,7 +496,6 @@ class BaseMixin:
|
|||
'''Are we in debug mode ?'''
|
||||
for arg in sys.argv:
|
||||
if arg == 'debug-mode=on': return True
|
||||
return False
|
||||
|
||||
def getClass(self, reloaded=False):
|
||||
'''Returns the Appy class that dictates self's behaviour.'''
|
||||
|
@ -524,30 +520,34 @@ class BaseMixin:
|
|||
def getAppyType(self, name, asDict=False, className=None):
|
||||
'''Returns the Appy type named p_name. If no p_className is defined, the
|
||||
field is supposed to belong to self's class.'''
|
||||
className = className or self.__class__.__name__
|
||||
attrs = self.getProductConfig().attributesDict[className]
|
||||
appyType = attrs.get(name, None)
|
||||
if appyType and asDict: return appyType.__dict__
|
||||
return appyType
|
||||
if not className:
|
||||
klass = self.__class__.wrapperClass
|
||||
else:
|
||||
klass = self.getTool().getAppyClass(className, wrapper=True)
|
||||
res = getattr(klass, name, None)
|
||||
if res and asDict: return res.__dict__
|
||||
return res
|
||||
|
||||
def getAllAppyTypes(self, className=None):
|
||||
'''Returns the ordered list of all Appy types for self's class if
|
||||
p_className is not specified, or for p_className else.'''
|
||||
className = className or self.__class__.__name__
|
||||
return self.getProductConfig().attributes[className]
|
||||
if not className:
|
||||
klass = self.__class__.wrapperClass
|
||||
else:
|
||||
klass = self.getTool().getAppyClass(className, wrapper=True)
|
||||
return klass.__fields__
|
||||
|
||||
def getGroupedAppyTypes(self, layoutType, pageName):
|
||||
'''Returns the fields sorted by group. For every field, the appyType
|
||||
(dict version) is given.'''
|
||||
res = []
|
||||
groups = {} # The already encountered groups
|
||||
# In debug mode, reload the module containing self's class.
|
||||
debug = self.isDebug()
|
||||
if debug:
|
||||
# If param "refresh" is there, we must reload the Python class
|
||||
refresh = ('refresh' in self.REQUEST)
|
||||
if refresh:
|
||||
klass = self.getClass(reloaded=True)
|
||||
for appyType in self.getAllAppyTypes():
|
||||
if debug:
|
||||
appyType = appyType.reload(klass, self)
|
||||
if refresh: appyType = appyType.reload(klass, self)
|
||||
if appyType.page.name != pageName: continue
|
||||
if not appyType.isShowable(self, layoutType): continue
|
||||
if not appyType.group:
|
||||
|
@ -594,13 +594,14 @@ class BaseMixin:
|
|||
the result.'''
|
||||
res = []
|
||||
for name in fieldNames:
|
||||
appyType = self.getAppyType(name, asDict)
|
||||
if appyType: res.append(appyType)
|
||||
elif name == 'state':
|
||||
if name == 'state':
|
||||
# We do not return a appyType if the attribute is not a *real*
|
||||
# attribute, but the workfow state.
|
||||
res.append({'name': name, 'labelId': 'workflow_state',
|
||||
'filterable': False})
|
||||
else:
|
||||
appyType = self.getAppyType(name, asDict)
|
||||
if appyType: res.append(appyType)
|
||||
else:
|
||||
self.appy().log('Field "%s", used as shownInfo in a Ref, ' \
|
||||
'was not found.' % name, type='warning')
|
||||
|
|
|
@ -183,10 +183,8 @@ class Tool(ModelClass):
|
|||
listBoxesMaximumWidth = Integer(default=100)
|
||||
def refreshSecurity(self): pass # Real method in the wrapper
|
||||
refreshSecurity = Action(action=refreshSecurity, confirm=True)
|
||||
# First arg of Ref field below is None because we don't know yet if it will
|
||||
# link to the predefined User class or a custom class defined in the
|
||||
# application.
|
||||
users = Ref(None, multiplicity=(0,None), add=True, link=False,
|
||||
# Ref(User) will maybe be transformed into Ref(CustomUserClass).
|
||||
users = Ref(User, multiplicity=(0,None), add=True, link=False,
|
||||
back=Ref(attribute='toTool'), page='users', queryable=True,
|
||||
queryFields=('login',), showHeaders=True,
|
||||
shownInfo=('login', 'title', 'roles'))
|
||||
|
|
|
@ -670,7 +670,7 @@
|
|||
isEdit python: layoutType == 'edit';
|
||||
pageInfo python: phaseInfo['pagesInfo'][page]">
|
||||
<br/>
|
||||
<tal:previousButton condition="python: previousPage and pageInfo['showPrevious']">
|
||||
<tal:previous condition="python: previousPage and pageInfo['showPrevious']">
|
||||
<tal:button condition="isEdit">
|
||||
<input type="image" class="imageInput" style="cursor:pointer" name="buttonPrevious"
|
||||
title="label_previous" i18n:attributes="title" i18n:domain="plone"
|
||||
|
@ -683,28 +683,34 @@
|
|||
title="label_previous" i18n:attributes="title" i18n:domain="plone"/>
|
||||
</a>
|
||||
</tal:link>
|
||||
</tal:previousButton>
|
||||
</tal:previous>
|
||||
|
||||
<tal:saveButton condition="python: isEdit and pageInfo['showSave']">
|
||||
<tal:save condition="python: isEdit and pageInfo['showSave']">
|
||||
<input type="image" class="imageInput" style="cursor:pointer" name="buttonOk"
|
||||
title="label_save" i18n:attributes="title" i18n:domain="plone"
|
||||
tal:attributes="src string:$portal_url/skyn/save.png"/>
|
||||
</tal:saveButton>
|
||||
</tal:save>
|
||||
|
||||
<tal:cancelButton condition="python: isEdit and pageInfo['showCancel']">
|
||||
<tal:cancel condition="python: isEdit and pageInfo['showCancel']">
|
||||
<input type="image" class="imageInput" style="cursor:pointer" name="buttonCancel"
|
||||
title="label_cancel" i18n:attributes="title" i18n:domain="plone"
|
||||
tal:attributes="src string:$portal_url/skyn/cancel.png"/>
|
||||
</tal:cancelButton>
|
||||
</tal:cancel>
|
||||
|
||||
<tal:editLink condition="python: not isEdit and pageInfo['showOnEdit']">
|
||||
<tal:edit condition="python: not isEdit and pageInfo['showOnEdit']">
|
||||
<img title="Edit" i18n:domain="plone" i18n:attributes="title" style="cursor:pointer"
|
||||
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode='edit', page=page);
|
||||
src string: $portal_url/skyn/editBig.png"
|
||||
tal:condition="python: member.has_permission('Modify portal content', contextObj)"/>
|
||||
</tal:editLink>
|
||||
</tal:edit>
|
||||
|
||||
<tal:nextButton condition="python: nextPage and pageInfo['showNext']">
|
||||
<tal:refresh condition="contextObj/isDebug">
|
||||
<img title="Refresh" style="cursor:pointer"
|
||||
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode=layoutType, page=page, refresh='yes');
|
||||
src string: $portal_url/skyn/refresh.png"/>
|
||||
</tal:refresh>
|
||||
|
||||
<tal:next condition="python: nextPage and pageInfo['showNext']">
|
||||
<tal:button condition="isEdit">
|
||||
<input type="image" class="imageInput" style="cursor:pointer" name="buttonNext"
|
||||
title="label_next" i18n:attributes="title" i18n:domain="plone"
|
||||
|
@ -717,7 +723,7 @@
|
|||
title="label_next" i18n:attributes="title" i18n:domain="plone"/>
|
||||
</a>
|
||||
</tal:link>
|
||||
</tal:nextButton>
|
||||
</tal:next>
|
||||
</div>
|
||||
|
||||
<tal:comment replace="nothing">
|
||||
|
|
BIN
gen/plone25/skin/refresh.png
Normal file
BIN
gen/plone25/skin/refresh.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -59,9 +59,6 @@ catalogMap = {}
|
|||
# In the following dict, we store, for every Appy class, the ordered list of
|
||||
# appy types (included inherited ones).
|
||||
attributes = {<!attributes!>}
|
||||
# In the following dict, we store, for every Appy class, a dict of appy types
|
||||
# keyed by their names.
|
||||
attributesDict = {<!attributesDict!>}
|
||||
|
||||
# Application roles
|
||||
applicationRoles = [<!roles!>]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# ------------------------------------------------------------------------------
|
||||
import os, os.path, time, mimetypes, random
|
||||
import appy.pod
|
||||
from appy.gen import Type, Search, Ref
|
||||
from appy.gen import Type, Search, Ref, String
|
||||
from appy.gen.utils import sequenceTypes
|
||||
from appy.shared.utils import getOsTempFolder, executeCommand, normalizeString
|
||||
from appy.shared.xml_parser import XmlMarshaller
|
||||
|
@ -41,7 +41,6 @@ class AbstractWrapper(object):
|
|||
elif name == 'typeName': return self.__class__.__bases__[-1].__name__
|
||||
elif name == 'id': return self.o.id
|
||||
elif name == 'uid': return self.o.UID()
|
||||
elif name == 'title': return self.o.Title()
|
||||
elif name == 'klass': return self.__class__.__bases__[-1]
|
||||
elif name == 'url': return self.o.absolute_url()
|
||||
elif name == 'state': return self.o.getState()
|
||||
|
@ -57,12 +56,7 @@ class AbstractWrapper(object):
|
|||
return self.o.portal_membership.getAuthenticatedMember()
|
||||
elif name == 'fields': return self.o.getAllAppyTypes()
|
||||
# Now, let's try to return a real attribute.
|
||||
try:
|
||||
res = object.__getattribute__(self, name)
|
||||
except AttributeError, ae:
|
||||
# Maybe a back reference?
|
||||
res = self.o.getAppyType(name)
|
||||
if not res: raise ae
|
||||
# If we got an Appy type, return the value of this type for this object
|
||||
if isinstance(res, Type):
|
||||
o = self.o
|
||||
|
|
Loading…
Reference in a new issue