[gen] Cleaner and more robust approach when using Zope database indexes.
This commit is contained in:
parent
5c2d94236f
commit
c2eaab4b44
|
@ -33,6 +33,13 @@ def initMasterValue(v):
|
||||||
else: res = v
|
else: res = v
|
||||||
return [str(v) for v in res]
|
return [str(v) for v in res]
|
||||||
|
|
||||||
|
# Default Appy indexes ---------------------------------------------------------
|
||||||
|
defaultIndexes = {
|
||||||
|
'State': 'FieldIndex', 'UID': 'FieldIndex', 'Title': 'ZCTextIndex',
|
||||||
|
'SortableTitle': 'FieldIndex', 'SearchableText': 'ZCTextIndex',
|
||||||
|
'Creator': 'FieldIndex', 'Created': 'DateIndex', 'ClassName': 'FieldIndex',
|
||||||
|
'Allowed': 'KeywordIndex'}
|
||||||
|
|
||||||
# Descriptor classes used for refining descriptions of elements in types
|
# Descriptor classes used for refining descriptions of elements in types
|
||||||
# (pages, groups,...) ----------------------------------------------------------
|
# (pages, groups,...) ----------------------------------------------------------
|
||||||
class Page:
|
class Page:
|
||||||
|
@ -961,14 +968,17 @@ class Type:
|
||||||
try:
|
try:
|
||||||
return method(obj, self)
|
return method(obj, self)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
# Log the initial error.
|
if raiseOnError:
|
||||||
|
# Raise the initial error.
|
||||||
|
raise te
|
||||||
|
else:
|
||||||
obj.log(tb, type='error')
|
obj.log(tb, type='error')
|
||||||
if raiseOnError: raise te
|
return str(te)
|
||||||
else: return str(te)
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
obj.log(Traceback.get(), type='error')
|
|
||||||
if raiseOnError: raise e
|
if raiseOnError: raise e
|
||||||
else: return str(e)
|
else:
|
||||||
|
obj.log(Traceback.get(), type='error')
|
||||||
|
return str(e)
|
||||||
|
|
||||||
def process(self, obj):
|
def process(self, obj):
|
||||||
'''This method is a general hook allowing a field to perform some
|
'''This method is a general hook allowing a field to perform some
|
||||||
|
@ -2122,7 +2132,7 @@ class Computed(Type):
|
||||||
return self.callMacro(obj, self.method)
|
return self.callMacro(obj, self.method)
|
||||||
else:
|
else:
|
||||||
# self.method is a method that will return the field value
|
# self.method is a method that will return the field value
|
||||||
return self.callMethod(obj, self.method, raiseOnError=False)
|
return self.callMethod(obj, self.method, raiseOnError=True)
|
||||||
|
|
||||||
def getFormattedValue(self, obj, value):
|
def getFormattedValue(self, obj, value):
|
||||||
if not isinstance(value, basestring): return str(value)
|
if not isinstance(value, basestring): return str(value)
|
||||||
|
|
|
@ -163,10 +163,10 @@ class ZopeInstaller:
|
||||||
catalog.addIndex(indexName, indexType)
|
catalog.addIndex(indexName, indexType)
|
||||||
else:
|
else:
|
||||||
catalog.addIndex(indexName, indexType,extra=ZCTextIndexInfo)
|
catalog.addIndex(indexName, indexType,extra=ZCTextIndexInfo)
|
||||||
|
# Indexing database content based on this index.
|
||||||
catalog.reindexIndex(indexName, self.app.REQUEST)
|
catalog.reindexIndex(indexName, self.app.REQUEST)
|
||||||
logger.info('Created index "%s" of type "%s"...' % \
|
logger.info('Created index "%s" of type "%s"...' % \
|
||||||
(indexName, indexType))
|
(indexName, indexType))
|
||||||
# Indexing database content based on this index.
|
|
||||||
|
|
||||||
lexiconInfos = [
|
lexiconInfos = [
|
||||||
appy.Object(group='Case Normalizer', name='Case Normalizer'),
|
appy.Object(group='Case Normalizer', name='Case Normalizer'),
|
||||||
|
@ -188,19 +188,11 @@ class ZopeInstaller:
|
||||||
elements=self.lexiconInfos)
|
elements=self.lexiconInfos)
|
||||||
|
|
||||||
# Create or update Appy-wide indexes and field-related indexes
|
# Create or update Appy-wide indexes and field-related indexes
|
||||||
indexInfo = {'State': 'FieldIndex', 'UID': 'FieldIndex',
|
indexInfo = gen.defaultIndexes.copy()
|
||||||
'Title': 'ZCTextIndex', 'SortableTitle': 'FieldIndex',
|
|
||||||
'SearchableText': 'ZCTextIndex', 'Creator': 'FieldIndex',
|
|
||||||
'Created': 'DateIndex', 'ClassName': 'FieldIndex',
|
|
||||||
'Allowed': 'KeywordIndex'}
|
|
||||||
tool = self.app.config
|
tool = self.app.config
|
||||||
for className in self.config.attributes.iterkeys():
|
for className in self.config.attributes.iterkeys():
|
||||||
wrapperClass = tool.getAppyClass(className, wrapper=True)
|
wrapperClass = tool.getAppyClass(className, wrapper=True)
|
||||||
for appyType in wrapperClass.__fields__:
|
indexInfo.update(wrapperClass.getIndexes(includeDefaults=False))
|
||||||
if not appyType.indexed or (appyType.name == 'title'): continue
|
|
||||||
n = appyType.name
|
|
||||||
indexName = 'get%s%s' % (n[0].upper(), n[1:])
|
|
||||||
indexInfo[indexName] = appyType.getIndexType()
|
|
||||||
self.installIndexes(indexInfo)
|
self.installIndexes(indexInfo)
|
||||||
|
|
||||||
def getAddPermission(self, className):
|
def getAddPermission(self, className):
|
||||||
|
@ -345,7 +337,6 @@ class ZopeInstaller:
|
||||||
appyTool.log('Translation "%s" updated from "%s".' % \
|
appyTool.log('Translation "%s" updated from "%s".' % \
|
||||||
(translation.id, poName))
|
(translation.id, poName))
|
||||||
|
|
||||||
|
|
||||||
def configureSessions(self):
|
def configureSessions(self):
|
||||||
'''Configure the session machinery.'''
|
'''Configure the session machinery.'''
|
||||||
# Register a function warning us when a session object is deleted. When
|
# Register a function warning us when a session object is deleted. When
|
||||||
|
|
|
@ -321,7 +321,11 @@ class BaseMixin:
|
||||||
if indexes:
|
if indexes:
|
||||||
catalog.catalog_object(self, path, idxs=indexes)
|
catalog.catalog_object(self, path, idxs=indexes)
|
||||||
else:
|
else:
|
||||||
catalog.catalog_object(self, path)
|
# Get the list of indexes that apply on this object. Else, Zope
|
||||||
|
# will reindex all indexes defined in the catalog, and through
|
||||||
|
# acquisition, wrong methods can be called on wrong objects.
|
||||||
|
iNames = self.wrapperClass.getIndexes().keys()
|
||||||
|
catalog.catalog_object(self, path, idxs=iNames)
|
||||||
|
|
||||||
def say(self, msg, type='info'):
|
def say(self, msg, type='info'):
|
||||||
'''Prints a p_msg in the user interface. p_logLevel may be "info",
|
'''Prints a p_msg in the user interface. p_logLevel may be "info",
|
||||||
|
|
|
@ -143,7 +143,7 @@
|
||||||
<table><tr valign="top">
|
<table><tr valign="top">
|
||||||
<tal:comment replace="nothing">If there is no object...</tal:comment>
|
<tal:comment replace="nothing">If there is no object...</tal:comment>
|
||||||
<tal:noObject condition="not:objs">
|
<tal:noObject condition="not:objs">
|
||||||
<td tal:content="python: _('no_ref')"></td>
|
<td class="discreet" tal:content="python: _('no_ref')"></td>
|
||||||
<td><metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/></td>
|
<td><metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/></td>
|
||||||
</tal:noObject>
|
</tal:noObject>
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@
|
||||||
<metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/>
|
<metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/>
|
||||||
|
|
||||||
<tal:comment replace="nothing">No object is present</tal:comment>
|
<tal:comment replace="nothing">No object is present</tal:comment>
|
||||||
<p tal:condition="not:objs" tal:content="python: _('no_ref')"></p>
|
<p class="discreet" tal:condition="not:objs" tal:content="python: _('no_ref')"></p>
|
||||||
|
|
||||||
<table width="100%" tal:condition="python: objs"
|
<table width="100%" tal:condition="python: objs"
|
||||||
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
|
tal:attributes="class python:test(innerRef, 'innerAppyTable', '')">
|
||||||
|
|
|
@ -168,20 +168,41 @@ class ToolWrapper(AbstractWrapper):
|
||||||
# reindex all Appy-managed objects, ie those in folders "config"
|
# reindex all Appy-managed objects, ie those in folders "config"
|
||||||
# and "data".
|
# and "data".
|
||||||
# First, clear the catalog.
|
# First, clear the catalog.
|
||||||
|
self.log('Recomputing the whole catalog...')
|
||||||
app = self.o.getParentNode()
|
app = self.o.getParentNode()
|
||||||
app.catalog._catalog.clear()
|
app.catalog._catalog.clear()
|
||||||
app.config.reindex()
|
|
||||||
nb = 1
|
nb = 1
|
||||||
|
failed = []
|
||||||
for obj in app.config.objectValues():
|
for obj in app.config.objectValues():
|
||||||
nb += self.refreshCatalog(startObject=obj)
|
subNb, subFailed = self.refreshCatalog(startObject=obj)
|
||||||
|
nb += subNb
|
||||||
|
failed += subFailed
|
||||||
|
try:
|
||||||
|
app.config.reindex()
|
||||||
|
except:
|
||||||
|
failed.append(app.config)
|
||||||
# Then, refresh objects in the "data" folder.
|
# Then, refresh objects in the "data" folder.
|
||||||
for obj in app.data.objectValues():
|
for obj in app.data.objectValues():
|
||||||
nb += self.refreshCatalog(startObject=obj)
|
subNb, subFailed = self.refreshCatalog(startObject=obj)
|
||||||
print '%d object(s) were reindexed.' % nb
|
nb += subNb
|
||||||
|
failed += subFailed
|
||||||
|
# Re-try to index all objects for which reindexation has failed.
|
||||||
|
for obj in failed: obj.reindex()
|
||||||
|
if failed:
|
||||||
|
failMsg = ' (%d retried)' % len(failed)
|
||||||
|
else:
|
||||||
|
failMsg = ''
|
||||||
|
self.log('%d object(s) were reindexed%s.' % (nb, failMsg))
|
||||||
else:
|
else:
|
||||||
startObject.reindex()
|
|
||||||
nb = 1
|
nb = 1
|
||||||
|
failed = []
|
||||||
for obj in startObject.objectValues():
|
for obj in startObject.objectValues():
|
||||||
nb += self.refreshCatalog(startObject=obj)
|
subNb, subFailed = self.refreshCatalog(startObject=obj)
|
||||||
return nb
|
nb += subNb
|
||||||
|
failed += subFailed
|
||||||
|
try:
|
||||||
|
startObject.reindex()
|
||||||
|
except Exception, e:
|
||||||
|
failed.append(startObject)
|
||||||
|
return nb, failed
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import os, os.path, mimetypes
|
import os, os.path, mimetypes
|
||||||
import appy.pod
|
import appy.pod
|
||||||
from appy.gen import Type, Search, Ref, String, WorkflowAnonymous
|
from appy.gen import Type, Search, Ref, String, WorkflowAnonymous, \
|
||||||
|
defaultIndexes
|
||||||
from appy.gen.utils import createObject
|
from appy.gen.utils import createObject
|
||||||
from appy.shared.utils import getOsTempFolder, executeCommand, \
|
from appy.shared.utils import getOsTempFolder, executeCommand, \
|
||||||
normalizeString, sequenceTypes
|
normalizeString, sequenceTypes
|
||||||
|
@ -59,6 +60,24 @@ class AbstractWrapper(object):
|
||||||
if not res: res = cfg.defaultAddRoles
|
if not res: res = cfg.defaultAddRoles
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getIndexes(klass, includeDefaults=True):
|
||||||
|
'''Returns a dict whose keys are the names of the indexes that are
|
||||||
|
applicable to instances of this class, and whose values are the
|
||||||
|
(Zope) types of those indexes.'''
|
||||||
|
# Start with the standard indexes applicable for any Appy class.
|
||||||
|
if includeDefaults:
|
||||||
|
res = defaultIndexes.copy()
|
||||||
|
else:
|
||||||
|
res = {}
|
||||||
|
# Add the indexed fields found on this class
|
||||||
|
for field in klass.__fields__:
|
||||||
|
if not field.indexed or (field.name == 'title'): continue
|
||||||
|
n = field.name
|
||||||
|
indexName = 'get%s%s' % (n[0].upper(), n[1:])
|
||||||
|
res[indexName] = field.getIndexType()
|
||||||
|
return res
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# Instance methods
|
# Instance methods
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue