diff --git a/bin/eggify.py b/bin/eggify.py index ba25741..640a26f 100644 --- a/bin/eggify.py +++ b/bin/eggify.py @@ -3,7 +3,7 @@ # ------------------------------------------------------------------------------ import os, os.path, sys, zipfile, appy from appy.bin.clean import Cleaner -from appy.shared.utils import FolderDeleter, copyFolder +from appy.shared.utils import FolderDeleter, copyFolder, cleanFolder from optparse import OptionParser # ------------------------------------------------------------------------------ @@ -104,6 +104,8 @@ class EggifyScript: def eggify(self): '''Let's wrap a nice Python module into an ugly egg.''' j = os.path.join + # First, clean the Python module + cleanFolder(self.pythonModule, verbose=False) # Create the egg folder eggFullName = j(self.eggFolder, self.eggName) if os.path.exists(eggFullName): diff --git a/gen/__init__.py b/gen/__init__.py index 77a947a..f659aad 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -700,6 +700,28 @@ class Type: if self.isEmptyValue(value): return '' return value + def getIndexValue(self, obj, forSearch=False): + '''This method returns a version for this field value on p_obj that is + ready for indexing purposes. Needs to be overridden by some child + classes. + + If p_forSearch is True, it will return a "string" version of the + index value suitable for a global search.''' + value = self.getValue(obj) + if forSearch and (value != None): + if isinstance(value, unicode): + res = value.encode('utf-8') + elif type(value) in sequenceTypes: + res = [] + for v in value: + if isinstance(v, unicode): res.append(v.encode('utf-8')) + else: res.append(str(v)) + res = ' '.join(res) + else: + res = str(value) + return res + return value + def getRequestValue(self, request): '''Gets the string (or list of strings if multi-valued) representation of this field as found in the p_request.''' @@ -1065,11 +1087,16 @@ class String(Type): else: return value if isinstance(value, basestring) and self.isMultiValued(): value = [value] + # Some backward compatibilities with Archetypes. elif value.__class__.__name__ == 'BaseUnit': try: value = unicode(value) except UnicodeDecodeError: value = str(value) + elif isinstance(value, tuple): + # When Appy storage was based on Archetype, multivalued string + # fields stored values as tuples of unicode strings. + value = list(value) return value def getFormattedValue(self, obj, value): @@ -1369,8 +1396,8 @@ class File(Type): - mimeType is the MIME type of the file. ''' if value: - ZFileUpload = self.o.getProductConfig().FileUpload - OFSImageFile = self.o.getProductConfig().File + ZFileUpload = obj.o.getProductConfig().FileUpload + OFSImageFile = obj.o.getProductConfig().File if isinstance(value, ZFileUpload): # The file content comes from a HTTP POST. # Retrieve the existing value, or create one if None diff --git a/gen/plone25/descriptors.py b/gen/plone25/descriptors.py index 69f5a01..ca188a5 100644 --- a/gen/plone25/descriptors.py +++ b/gen/plone25/descriptors.py @@ -361,7 +361,8 @@ class ClassDescriptor(appy.gen.descriptors.ClassDescriptor): m += '\n' + ' '*spaces + 'def get%s%s(self):\n' % (n[0].upper(), n[1:]) spaces += TABS m += ' '*spaces + "'''Gets indexable value of field \"%s\".'''\n" % n - m += ' '*spaces + 'return self.getAppyType("%s").getValue(self)\n' % n + m += ' '*spaces + 'return self.getAppyType("%s").getIndexValue(' \ + 'self)\n' % n self.methods = m class ToolClassDescriptor(ClassDescriptor): diff --git a/gen/plone25/generator.py b/gen/plone25/generator.py index 7311c70..402b719 100644 --- a/gen/plone25/generator.py +++ b/gen/plone25/generator.py @@ -667,14 +667,14 @@ class Generator(AbstractGenerator): if classDescr.isFolder(): baseClass = 'OrderedBaseFolder' baseSchema = 'OrderedBaseFolderSchema' - parents = [baseClass, 'BaseMixin'] + parents = ['BaseMixin', baseClass] imports = [] implements = [baseClass] for baseClass in classDescr.klass.__bases__: if self.determineAppyType(baseClass) == 'class': bcName = getClassName(baseClass) parents.remove('BaseMixin') - parents.append(bcName) + parents.insert(0, bcName) implements.append(bcName) imports.append('from %s import %s' % (bcName, bcName)) baseSchema = '%s.schema' % bcName diff --git a/gen/plone25/installer.py b/gen/plone25/installer.py index 4f4e861..4cbc36c 100644 --- a/gen/plone25/installer.py +++ b/gen/plone25/installer.py @@ -56,9 +56,17 @@ class PloneInstaller: {s_indexName:s_indexType}. Here are some examples of index types: "FieldIndex", "ZCTextIndex", "DateIndex".''' catalog = ploneSite.portal_catalog - indexNames = catalog.indexes() + zopeCatalog = catalog._catalog for indexName, indexType in indexInfo.iteritems(): - if indexName not in indexNames: + # If this index already exists but with a different type, remove it. + if (indexName in zopeCatalog.indexes): + oldType = zopeCatalog.indexes[indexName].__class__.__name__ + if oldType != indexType: + catalog.delIndex(indexName) + logger.info('Existing index "%s" of type "%s" was removed:'\ + ' we need to recreate it with type "%s".' % \ + (indexName, oldType, indexType)) + if indexName not in zopeCatalog.indexes: # We need to create this index if indexType != 'ZCTextIndex': catalog.addIndex(indexName, indexType) @@ -68,8 +76,6 @@ class PloneInstaller: catalog.reindexIndex(indexName, ploneSite.REQUEST) logger.info('Created index "%s" of type "%s"...' % \ (indexName, indexType)) - # TODO: if the index already exists but has not the same type, we - # re-create it with the same type and we reindex it. actionsToHide = { 'portal_actions': ('sitemap', 'accessibility', 'change_state','sendto'), diff --git a/gen/plone25/mixins/__init__.py b/gen/plone25/mixins/__init__.py index d2248f1..9356ca7 100644 --- a/gen/plone25/mixins/__init__.py +++ b/gen/plone25/mixins/__init__.py @@ -793,7 +793,7 @@ class BaseMixin: transition on an object.''' rq = self.REQUEST self.portal_workflow.doActionFor(self, rq['workflow_action'], - comment = rq.get('comment', '')) + comment = rq.get('comment', '')) self.reindexObject() # Where to redirect the user back ? # TODO (?): remove the "phase" param for redirecting the user to the @@ -1040,4 +1040,13 @@ class BaseMixin: response.setHeader('Cachecontrol', 'no-cache') response.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:05 GMT') return theFile.index_html(self.REQUEST, self.REQUEST.RESPONSE) + + def SearchableText(self): + '''This method concatenates the content of every field with + searchable=True for indexing purposes.''' + res = [] + for field in self.getAllAppyTypes(): + if not field.searchable: continue + res.append(field.getIndexValue(self, forSearch=True)) + return res # ------------------------------------------------------------------------------ diff --git a/gen/plone25/templates/ToolTemplate.py b/gen/plone25/templates/ToolTemplate.py index cc53ade..9eafb8c 100644 --- a/gen/plone25/templates/ToolTemplate.py +++ b/gen/plone25/templates/ToolTemplate.py @@ -11,7 +11,7 @@ schema = Schema(( ),) fullSchema = OrderedBaseFolderSchema.copy() + schema.copy() -class (UniqueObject, OrderedBaseFolder, ToolMixin): +class (ToolMixin, UniqueObject, OrderedBaseFolder): '''Tool for .''' security = ClassSecurityInfo() __implements__ = (getattr(UniqueObject,'__implements__',()),) + (getattr(OrderedBaseFolder,'__implements__',()),) diff --git a/gen/plone25/templates/UserTemplate.py b/gen/plone25/templates/UserTemplate.py index dd352bc..4d98b5b 100644 --- a/gen/plone25/templates/UserTemplate.py +++ b/gen/plone25/templates/UserTemplate.py @@ -9,7 +9,7 @@ schema = Schema(( ),) fullSchema = BaseSchema.copy() + schema.copy() -class User(BaseContent, BaseMixin): +class User(BaseMixin, BaseContent): '''User mixin.''' security = ClassSecurityInfo() __implements__ = (getattr(BaseContent,'__implements__',()),)