From c5a8968bd3b0b33fd12898f9a2b6c722a8abe4ec Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Mon, 5 Dec 2011 15:11:29 +0100 Subject: [PATCH] appy.gen: Refactoring due to De-Plonization. --- bin/generate.py | 36 +++------- gen/__init__.py | 51 +++++---------- gen/descriptors.py | 86 ++++++++++++------------ gen/generator.py | 50 ++++++-------- gen/installer.py | 16 ++--- gen/migrator.py | 3 +- gen/mixins/TestMixin.py | 4 +- gen/mixins/ToolMixin.py | 19 +++--- gen/mixins/__init__.py | 22 +++---- gen/model.py | 101 ++++++++++++++--------------- gen/notifier.py | 18 ++--- gen/odt/__init__.py | 0 gen/odt/generator.py | 54 --------------- gen/odt/templates/basic.odt | Bin 10487 -> 0 bytes gen/plone25/__init__.py | 0 gen/templates/Class.py | 4 +- gen/templates/Styles.css.dtml | 90 ------------------------- gen/templates/__init__.py | 4 +- gen/templates/config.py | 4 +- gen/templates/configure.zcml | 6 -- gen/templates/testAll.py | 10 +-- gen/templates/wrappers.py | 10 +-- gen/ui/import.pt | 32 +++------ gen/ui/page.pt | 32 ++++----- gen/ui/portlet.pt | 4 +- gen/ui/result.pt | 5 +- gen/ui/widgets/action.pt | 5 +- gen/ui/widgets/boolean.pt | 4 +- gen/ui/widgets/file.pt | 11 ++-- gen/ui/widgets/ref.pt | 5 +- gen/utils.py | 23 ++++--- gen/wrappers/GroupWrapper.py | 2 +- gen/wrappers/ToolWrapper.py | 2 +- gen/wrappers/TranslationWrapper.py | 2 +- gen/wrappers/UserWrapper.py | 2 +- 35 files changed, 237 insertions(+), 480 deletions(-) delete mode 100644 gen/odt/__init__.py delete mode 100644 gen/odt/generator.py delete mode 100644 gen/odt/templates/basic.odt delete mode 100644 gen/plone25/__init__.py delete mode 100644 gen/templates/Styles.css.dtml delete mode 100644 gen/templates/configure.zcml diff --git a/bin/generate.py b/bin/generate.py index 72375e4..c92faf2 100644 --- a/bin/generate.py +++ b/bin/generate.py @@ -3,18 +3,15 @@ # ------------------------------------------------------------------------------ import sys, os.path from optparse import OptionParser -from appy.gen.generator import GeneratorError +from appy.gen.generator import GeneratorError, ZopeGenerator from appy.shared.utils import LinesCounter import appy.version # ------------------------------------------------------------------------------ ERROR_CODE = 1 -VALID_PRODUCT_TYPES = ('zope', 'odt') APP_NOT_FOUND = 'Application not found at %s.' WRONG_NG_OF_ARGS = 'Wrong number of arguments.' WRONG_OUTPUT_FOLDER = 'Output folder not found. Please create it first.' -PRODUCT_TYPE_ERROR = 'Wrong product type. Product type may be one of the ' \ - 'following: %s' % str(VALID_PRODUCT_TYPES) C_OPTION = 'Removes from i18n files all labels that are not automatically ' \ 'generated from your gen-application. It can be useful during ' \ 'development, when you do lots of name changes (classes, ' \ @@ -37,7 +34,7 @@ S_OPTION = 'Sorts all i18n labels. If you use this option, among the ' \ 'set of translation files.' class GeneratorScript: - '''usage: %prog [options] app productType outputFolder + '''usage: %prog [options] app outputFolder "app" is the path to your Appy application, which must be a Python package (= a folder containing a file named @@ -47,44 +44,29 @@ class GeneratorScript: generated product, stored or symlinked in /Products. - "productType" is the kind of product you want to generate. "zope" is - the only available production-ready target. - "odt" is experimental. - "outputFolder" is the folder where the Zope product will be generated. For example, if you develop your application in /home/gdy/MyProject/MyProject, you typically specify "/home/gdy/MyProject/zope" as outputFolder. ''' - - def generateProduct(self, options, application, productType, outputFolder): - if productType == 'odt': - exec 'from appy.gen.odt.generator import Generator' - else: - from appy.gen.generator import ZopeGenerator as Generator - Generator(application, outputFolder, options).run() - def manageArgs(self, parser, options, args): # Check number of args - if len(args) != 3: + if len(args) != 2: print WRONG_NG_OF_ARGS parser.print_help() sys.exit(ERROR_CODE) - # Check productType - if args[1] not in VALID_PRODUCT_TYPES: - print PRODUCT_TYPE_ERROR - sys.exit(ERROR_CODE) # Check existence of application if not os.path.exists(args[0]): print APP_NOT_FOUND % args[0] sys.exit(ERROR_CODE) - # Check existence of outputFolder basic type - if not os.path.exists(args[2]): + # Check existence of outputFolder + if not os.path.exists(args[1]): print WRONG_OUTPUT_FOLDER sys.exit(ERROR_CODE) # Convert all paths in absolute paths - for i in (0,2): + for i in (0,1): args[i] = os.path.abspath(args[i]) + def run(self): optParser = OptionParser(usage=GeneratorScript.__doc__) optParser.add_option("-c", "--i18n-clean", action='store_true', @@ -95,8 +77,8 @@ class GeneratorScript: try: self.manageArgs(optParser, options, args) print 'Appy version:', appy.version.verbose - print 'Generating %s product in %s...' % (args[1], args[2]) - self.generateProduct(options, *args) + print 'Generating Zope product in %s...' % args[1] + ZopeGenerator(args[0], args[1], options).run() # Give the user some statistics about its code LinesCounter(args[0]).run() except GeneratorError, ge: diff --git a/gen/__init__.py b/gen/__init__.py index 5c88e7b..6322b28 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -1026,8 +1026,7 @@ class String(Type): it will be given by the Appy validation machinery, so it must be specified as parameter. The function returns True if the check is successful.''' - if not value: return True # Plone calls me erroneously for - # non-mandatory fields. + if not value: return True # First, remove any non-digit char v = '' for c in value: @@ -1058,8 +1057,7 @@ class String(Type): '''Checks that p_value corresponds to a valid IBAN number. IBAN stands for International Bank Account Number (ISO 13616). If the number is valid, the method returns True.''' - if not value: return True # Plone calls me erroneously for - # non-mandatory fields. + if not value: return True # First, remove any non-digit or non-letter char v = '' for c in value: @@ -1088,8 +1086,7 @@ class String(Type): '''Checks that p_value corresponds to a valid BIC number. BIC stands for Bank Identifier Code (ISO 9362). If the number is valid, the method returns True.''' - if not value: return True # Plone calls me erroneously for - # non-mandatory fields. + if not value: return True # BIC number must be 8 or 11 chars if len(value) not in (8, 11): return False # 4 first chars, representing bank name, must be letters @@ -1176,15 +1173,7 @@ 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 @@ -1207,12 +1196,6 @@ class String(Type): res = [t('%s_list_%s' % (self.labelId, v)) for v in value] else: res = t('%s_list_%s' % (self.labelId, value)) - elif not isinstance(value, basestring): - # Archetypes "Description" fields may hold a BaseUnit instance. - try: - res = unicode(value) - except UnicodeDecodeError: - res = str(value) # If value starts with a carriage return, add a space; else, it will # be ignored. if isinstance(res, basestring) and \ @@ -1384,8 +1367,8 @@ class Boolean(Type): return value def getFormattedValue(self, obj, value): - if value: res = obj.translate('yes', domain='plone') - else: res = obj.translate('no', domain='plone') + if value: res = obj.translate('yes') + else: res = obj.translate('no') return res def getStorableValue(self, value): @@ -1517,7 +1500,7 @@ class File(Type): def getFormattedValue(self, obj, value): if not value: return value - return value._atFile + return value._zopeFile def getRequestValue(self, request): return request.get('%s_file' % self.name) @@ -1591,7 +1574,7 @@ class File(Type): elif isinstance(value, OFSImageFile): setattr(obj, self.name, value) elif isinstance(value, FileWrapper): - setattr(obj, self.name, value._atFile) + setattr(obj, self.name, value._zopeFile) elif isinstance(value, basestring): setattr(obj, self.name, File.getFileObject(value, zope=True)) elif type(value) in sequenceTypes: @@ -2189,7 +2172,7 @@ class Pod(Type): def store(self, obj, value): '''Stores (=freezes) a document (in p_value) in the field.''' if isinstance(value, FileWrapper): - value = value._atFile + value = value._zopeFile setattr(obj, self.name, value) class List(Type): @@ -2283,19 +2266,18 @@ appyToZopePermissions = { class Role: '''Represents a role.''' - ploneRoles = ('Manager', 'Member', 'Owner', 'Reviewer', 'Anonymous', - 'Authenticated') - ploneLocalRoles = ('Owner',) - ploneUngrantableRoles = ('Anonymous', 'Authenticated') + zopeRoles = ('Manager', 'Owner', 'Anonymous', 'Authenticated') + zopeLocalRoles = ('Owner',) + zopeUngrantableRoles = ('Anonymous', 'Authenticated') def __init__(self, name, local=False, grantable=True): self.name = name self.local = local # True if it can be used as local role only. - # It is a standard Plone role or an application-specific one? - self.plone = name in self.ploneRoles - if self.plone and (name in self.ploneLocalRoles): + # It is a standard Zope role or an application-specific one? + self.zope = name in self.zopeRoles + if self.zope and (name in self.zopeLocalRoles): self.local = True self.grantable = grantable - if self.plone and (name in self.ploneUngrantableRoles): + if self.zope and (name in self.zopeUngrantableRoles): self.grantable = False # An ungrantable role is one that is, like the Anonymous or # Authenticated roles, automatically attributed to a user. @@ -2575,8 +2557,7 @@ class Transition: # Return a message to the user if needed if not doSay or (transitionName == '_init_'): return if not msg: - msg = obj.translate(u'Your content\'s status has been modified.', - domain='plone') + msg = obj.translate(u'Changes saved.') obj.say(msg) class Permission: diff --git a/gen/descriptors.py b/gen/descriptors.py index 3459b05..40b05dd 100644 --- a/gen/descriptors.py +++ b/gen/descriptors.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ import types, copy -from appy.gen import State, Transition, Type +import appy.gen as gen from po import PoMessage from model import ModelClass, toolFieldPrefixes from utils import produceNiceMessage, getClassName @@ -27,8 +27,7 @@ class ClassDescriptor(Descriptor): '''This class gives information about an Appy class.''' def __init__(self, klass, orderedAttributes, generator): - appy.gen.descriptors.ClassDescriptor.__init__(self, klass, - orderedAttributes, generator) + Descriptor.__init__(self, klass, orderedAttributes, generator) self.methods = '' # Needed method definitions will be generated here # We remember here encountered pages and groups defined in the Appy # type. Indeed, after having parsed all application classes, we will @@ -70,7 +69,7 @@ class ClassDescriptor(Descriptor): except AttributeError: attrValue = getattr(self.modelClass, attrName) hookClass = self.modelClass - if isinstance(attrValue, Type): + if isinstance(attrValue, gen.Type): if not condition or eval(condition): attrs.append( (attrName, attrValue, hookClass) ) # Then, add attributes from parent classes @@ -142,7 +141,7 @@ class ClassDescriptor(Descriptor): attrValue = getattr(self.klass, attrName) except AttributeError: attrValue = getattr(self.modelClass, attrName) - if isinstance(attrValue, Type): + if isinstance(attrValue, gen.Type): if configClass: attrValue = copy.copy(attrValue) attrValue.optional = False @@ -184,13 +183,13 @@ class ClassDescriptor(Descriptor): res = [] if self.klass.__dict__.has_key('creators') and self.klass.creators: for creator in self.klass.creators: - if isinstance(creator, Role): + if isinstance(creator, gen.Role): if creator.local: raise 'Local role "%s" cannot be used as a creator.' % \ creator.name res.append(creator) else: - res.append(Role(creator)) + res.append(gen.Role(creator)) return res def getCreateMean(self, type='Import'): @@ -213,13 +212,17 @@ class ClassDescriptor(Descriptor): res = [] if klass.__dict__.has_key('search'): searches = klass.__dict__['search'] - if isinstance(searches, basestring): res.append(Search(searches)) - elif isinstance(searches, Search): res.append(searches) + if isinstance(searches, basestring): + res.append(gen.Search(searches)) + elif isinstance(searches, gen.Search): + res.append(searches) else: # It must be a list of searches. for search in searches: - if isinstance(search, basestring):res.append(Search(search)) - else: res.append(search) + if isinstance(search, basestring): + res.append(gen.Search(search)) + else: + res.append(search) return res @staticmethod @@ -268,11 +271,10 @@ class FieldDescriptor: '''This class gathers information about a specific typed attribute defined in a gen-class.''' - singleValuedTypes = ('Integer', 'Float', 'Boolean', 'Date', 'File') # Although Appy allows to specify a multiplicity[0]>1 for those types, it is - # not supported by Archetypes. So we will always generate single-valued type - # definitions for them. - specialParams = ('title', 'description') + # not currently. So we will always generate single-valued type definitions + # for them. + singleValuedTypes = ('Integer', 'Float', 'Boolean', 'Date', 'File') def __init__(self, fieldName, appyType, classDescriptor): self.appyType = appyType @@ -387,8 +389,7 @@ class FieldDescriptor: if self.appyType.editDefault: self.generator.tool.addDefaultField(self) # - put an index on this field? - if self.appyType.indexed and \ - (self.fieldName not in ('title', 'description')): + if self.appyType.indexed and (self.fieldName != 'title'): self.classDescr.addIndexMethod(self) # i18n labels messages = self.generator.labels @@ -477,7 +478,7 @@ class ToolClassDescriptor(ClassDescriptor): self.addField(fieldName, fieldType) fieldType.validator.append(fieldDescr.fieldName) fieldType.page.name = 'data' - fieldType.group = Group(fieldDescr.classDescr.klass.__name__) + fieldType.group = gen.Group(fieldDescr.classDescr.klass.__name__) def addDefaultField(self, fieldDescr): className = fieldDescr.classDescr.name @@ -485,22 +486,22 @@ class ToolClassDescriptor(ClassDescriptor): fieldType = fieldDescr.appyType.clone() self.addField(fieldName, fieldType) fieldType.page.name = 'data' - fieldType.group = Group(fieldDescr.classDescr.klass.__name__) + fieldType.group = gen.Group(fieldDescr.classDescr.klass.__name__) def addPodRelatedFields(self, fieldDescr): '''Adds the fields needed in the Tool for configuring a Pod field.''' className = fieldDescr.classDescr.name # On what page and group to display those fields ? pg = {'page': 'documentGeneration', - 'group': Group(fieldDescr.classDescr.klass.__name__, ['50%']*2)} + 'group':gen.Group(fieldDescr.classDescr.klass.__name__,['50%']*2)} # Add the field that will store the pod template. fieldName = 'podTemplateFor%s_%s' % (className, fieldDescr.fieldName) - fieldType = File(**pg) + fieldType = gen.File(**pg) self.addField(fieldName, fieldType) # Add the field that will store the output format(s) fieldName = 'formatsFor%s_%s' % (className, fieldDescr.fieldName) - fieldType = String(validator=Selection('getPodOutputFormats'), - multiplicity=(1,None), default=('odt',), **pg) + fieldType = gen.String(validator=gen.Selection('getPodOutputFormats'), + multiplicity=(1,None), default=('odt',), **pg) self.addField(fieldName, fieldType) def addQueryResultColumns(self, classDescr): @@ -508,7 +509,7 @@ class ToolClassDescriptor(ClassDescriptor): to select what default columns will be shown on query results.''' className = classDescr.name fieldName = 'resultColumnsFor%s' % className - fieldType = String(multiplicity=(0,None), validator=Selection( + fieldType = gen.String(multiplicity=(0,None), validator=gen.Selection( '_appy_getAllFields*%s' % className), page='userInterface', group=classDescr.klass.__name__) self.addField(fieldName, fieldType) @@ -520,21 +521,21 @@ class ToolClassDescriptor(ClassDescriptor): # Field that defines if advanced search is enabled for class # p_classDescr or not. fieldName = 'enableAdvancedSearchFor%s' % className - fieldType = Boolean(default=True, page='userInterface', - group=classDescr.klass.__name__) + fieldType = gen.Boolean(default=True, page='userInterface', + group=classDescr.klass.__name__) self.addField(fieldName, fieldType) # Field that defines how many columns are shown on the custom search # screen. fieldName = 'numberOfSearchColumnsFor%s' % className - fieldType = Integer(default=3, page='userInterface', - group=classDescr.klass.__name__) + fieldType = gen.Integer(default=3, page='userInterface', + group=classDescr.klass.__name__) self.addField(fieldName, fieldType) # Field that allows to select, among all indexed fields, what fields # must really be used in the search screen. fieldName = 'searchFieldsFor%s' % className defaultValue = [a[0] for a in classDescr.getOrderedAppyAttributes( condition='attrValue.indexed')] - fieldType = String(multiplicity=(0,None), validator=Selection( + fieldType = gen.String(multiplicity=(0,None), validator=gen.Selection( '_appy_getSearchableFields*%s' % className), default=defaultValue, page='userInterface', group=classDescr.klass.__name__) self.addField(fieldName, fieldType) @@ -546,8 +547,8 @@ class ToolClassDescriptor(ClassDescriptor): # Field that defines the path of the files to import. fieldName = 'importPathFor%s' % className defValue = classDescr.getCreateMean('Import').path - fieldType = String(page='data', multiplicity=(1,1), default=defValue, - group=classDescr.klass.__name__) + fieldType = gen.String(page='data', multiplicity=(1,1), + default=defValue,group=classDescr.klass.__name__) self.addField(fieldName, fieldType) def addWorkflowFields(self, classDescr): @@ -560,13 +561,13 @@ class ToolClassDescriptor(ClassDescriptor): if classDescr.isRoot() or issubclass(classDescr.klass, ModelClass): defaultValue = True fieldName = 'showWorkflowFor%s' % className - fieldType = Boolean(default=defaultValue, page='userInterface', - group=groupName) + fieldType = gen.Boolean(default=defaultValue, page='userInterface', + group=groupName) self.addField(fieldName, fieldType) # Adds the boolean field for showing or not the field "enter comments". fieldName = 'showWorkflowCommentFieldFor%s' % className - fieldType = Boolean(default=defaultValue, page='userInterface', - group=groupName) + fieldType = gen.Boolean(default=defaultValue, page='userInterface', + group=groupName) self.addField(fieldName, fieldType) # Adds the boolean field for showing all states in current state or not. # If this boolean is True but the current phase counts only one state, @@ -577,13 +578,12 @@ class ToolClassDescriptor(ClassDescriptor): if len(classDescr.getPhases()) > 1: defaultValue = True fieldName = 'showAllStatesInPhaseFor%s' % className - fieldType = Boolean(default=defaultValue, page='userInterface', - group=groupName) + fieldType = gen.Boolean(default=defaultValue, page='userInterface', + group=groupName) self.addField(fieldName, fieldType) class UserClassDescriptor(ClassDescriptor): - '''Represents an Archetypes-compliant class that corresponds to the User - for the generated application.''' + '''Appy-specific class for representing a user.''' def __init__(self, klass, generator): ClassDescriptor.__init__(self,klass,klass._appy_attributes[:],generator) self.modelClass = self.klass @@ -649,8 +649,8 @@ class TranslationClassDescriptor(ClassDescriptor): def addLabelField(self, messageId, page): '''Adds a Computed field that will display, in the source language, the content of the text to translate.''' - field = Computed(method=self.modelClass.label, plainText=False, - page=page, show=self.modelClass.show, layouts='f') + field = gen.Computed(method=self.modelClass.label, plainText=False, + page=page, show=self.modelClass.show, layouts='f') self.addField('%s_label' % messageId, field) def addMessageField(self, messageId, page, i18nFiles): @@ -683,7 +683,7 @@ class TranslationClassDescriptor(ClassDescriptor): params['width'] = width else: # This is a multi-line field, or a very-long-single-lined field - params['format'] = String.TEXT + params['format'] = gen.String.TEXT params['height'] = height - self.addField(messageId, String(**params)) + self.addField(messageId, gen.String(**params)) # ------------------------------------------------------------------------------ diff --git a/gen/generator.py b/gen/generator.py index fd7c58d..8ca3c75 100644 --- a/gen/generator.py +++ b/gen/generator.py @@ -2,7 +2,7 @@ import os, os.path, re, sys, parser, symbol, token, types import appy.pod, appy.pod.renderer from appy.shared.utils import FolderDeleter -#from appy.gen import * +import appy.gen as gen from po import PoMessage, PoFile, PoParser from descriptors import * from utils import produceNiceMessage, getClassName @@ -140,7 +140,7 @@ class Generator: self.user = None self.workflows = [] self.initialize() - self.config = Config.getDefault() + self.config = gen.Config.getDefault() self.modulesWithTests = set() self.totalNumberOfTests = 0 @@ -152,9 +152,9 @@ class Generator: workflow.''' res = 'none' for attrValue in klass.__dict__.itervalues(): - if isinstance(attrValue, Type): + if isinstance(attrValue, gen.Type): res = 'class' - elif isinstance(attrValue, State): + elif isinstance(attrValue, gen.State): res = 'workflow' if not res: for baseClass in klass.__bases__: @@ -219,13 +219,13 @@ class Generator: attrs = astClasses[moduleElem.__name__].attributes if appyType == 'class': # Determine the class type (standard, tool, user...) - if issubclass(moduleElem, Tool): + if issubclass(moduleElem, gen.Tool): if not self.tool: klass = self.descriptorClasses['tool'] self.tool = klass(moduleElem, attrs, self) else: self.tool.update(moduleElem, attrs) - elif issubclass(moduleElem, User): + elif issubclass(moduleElem, gen.User): if not self.user: klass = self.descriptorClasses['user'] self.user = klass(moduleElem, attrs, self) @@ -244,7 +244,7 @@ class Generator: self.workflows.append(descriptor) if self.containsTests(moduleElem): self.modulesWithTests.add(moduleObj.__name__) - elif isinstance(moduleElem, Config): + elif isinstance(moduleElem, gen.Config): self.config = moduleElem # Walk potential sub-modules @@ -461,7 +461,6 @@ class ZopeGenerator(Generator): self.generateTool() self.generateInit() self.generateTests() - self.generateConfigureZcml() # Create version.txt f = open(os.path.join(self.outputFolder, 'version.txt'), 'w') f.write(self.version) @@ -536,13 +535,13 @@ class ZopeGenerator(Generator): self.generateWrappers() self.generateConfig() - def getAllUsedRoles(self, plone=None, local=None, grantable=None): + def getAllUsedRoles(self, zope=None, local=None, grantable=None): '''Produces a list of all the roles used within all workflows and classes defined in this application. - If p_plone is True, it keeps only Plone-standard roles; if p_plone + If p_zope is True, it keeps only Zope-standard roles; if p_zope is False, it keeps only roles which are specific to this application; - if p_plone is None it has no effect (so it keeps both roles). + if p_zope is None it has no effect (so it keeps both roles). If p_local is True, it keeps only local roles (ie, roles that can only be granted locally); if p_local is False, it keeps only "global" @@ -557,8 +556,8 @@ class ZopeGenerator(Generator): for wfDescr in self.workflows: for attr in dir(wfDescr.klass): attrValue = getattr(wfDescr.klass, attr) - if isinstance(attrValue, State) or \ - isinstance(attrValue, Transition): + if isinstance(attrValue, gen.State) or \ + isinstance(attrValue, gen.Transition): for role in attrValue.getUsedRoles(): if role.name not in allRoles: allRoles[role.name] = role @@ -569,7 +568,7 @@ class ZopeGenerator(Generator): allRoles[role.name] = role res = allRoles.values() # Filter the result according to parameters - for p in ('plone', 'local', 'grantable'): + for p in ('zope', 'local', 'grantable'): if eval(p) != None: res = [r for r in res if eval('r.%s == %s' % (p, p))] return res @@ -613,17 +612,6 @@ class ZopeGenerator(Generator): res = configClasses return res - def generateConfigureZcml(self): - '''Generates file configure.zcml.''' - repls = self.repls.copy() - # Note every class as "deprecated". - depr = '' - for klass in self.getClasses(include='all'): - depr += '\n' % \ - (klass.name, klass.name) - repls['deprecated'] = depr - self.copyFile('configure.zcml', repls) - def generateConfig(self): repls = self.repls.copy() # Get some lists of classes @@ -677,9 +665,9 @@ class ZopeGenerator(Generator): attributes.append('"%s":[%s]' % (classDescr.name, ','.join(qNames))) repls['attributes'] = ',\n '.join(attributes) # Compute list of used roles for registering them if needed - specificRoles = self.getAllUsedRoles(plone=False) + specificRoles = self.getAllUsedRoles(zope=False) repls['roles'] = ','.join(['"%s"' % r.name for r in specificRoles]) - globalRoles = self.getAllUsedRoles(plone=False, local=False) + globalRoles = self.getAllUsedRoles(zope=False, local=False) repls['gRoles'] = ','.join(['"%s"' % r.name for r in globalRoles]) grantableRoles = self.getAllUsedRoles(local=False, grantable=True) repls['grRoles'] = ','.join(['"%s"' % r.name for r in grantableRoles]) @@ -780,7 +768,7 @@ class ZopeGenerator(Generator): self.copyFile('testAll.py', repls, destFolder='tests') def generateTool(self): - '''Generates the Plone tool that corresponds to this application.''' + '''Generates the tool that corresponds to this application.''' Msg = PoMessage # Create Tool-related i18n-related messages msg = Msg(self.tool.name, '', Msg.CONFIG % self.applicationName) @@ -874,7 +862,7 @@ class ZopeGenerator(Generator): poMsg.produceNiceDefault() if poMsg not in self.labels: self.labels.append(poMsg) - # Generate the resulting Archetypes class. + # Generate the resulting Zope class. self.copyFile('Class.py', repls, destName=fileName) def generateWorkflow(self, wfDescr): @@ -886,14 +874,14 @@ class ZopeGenerator(Generator): wfName = WorkflowDescriptor.getWorkflowName(wfDescr.klass) # Add i18n messages for states for name in dir(wfDescr.klass): - if not isinstance(getattr(wfDescr.klass, name), State): continue + if not isinstance(getattr(wfDescr.klass, name), gen.State): continue poMsg = PoMessage('%s_%s' % (wfName, name), '', name) poMsg.produceNiceDefault() self.labels.append(poMsg) # Add i18n messages for transitions for name in dir(wfDescr.klass): transition = getattr(wfDescr.klass, name) - if not isinstance(transition, Transition): continue + if not isinstance(transition, gen.Transition): continue poMsg = PoMessage('%s_%s' % (wfName, name), '', name) poMsg.produceNiceDefault() self.labels.append(poMsg) diff --git a/gen/installer.py b/gen/installer.py index 3ade52e..d32db31 100644 --- a/gen/installer.py +++ b/gen/installer.py @@ -5,7 +5,7 @@ import os, os.path, time import appy import appy.version -from appy.gen import Type, Ref, String, File +import appy.gen as gen from appy.gen.po import PoParser from appy.gen.utils import updateRolesForPermission, createObject from appy.shared.data import languages @@ -110,7 +110,7 @@ class ZopeInstaller: for name in files: baseName, ext = os.path.splitext(name) f = file(j(root, name)) - if ext in File.imageExts: + if ext in gen.File.imageExts: zopeFolder.manage_addImage(name, f) elif ext == '.pt': manage_addPageTemplate(zopeFolder, baseName, '', f.read()) @@ -302,13 +302,11 @@ class ZopeInstaller: # "po" file on disk. appFolder = self.config.diskFolder appName = self.config.PROJECTNAME - dn = os.path.dirname - jn = os.path.join - i18nFolder = jn(jn(jn(dn(dn(dn(appFolder))),'Products'),appName),'i18n') + i18nFolder = os.path.join(appFolder, 'tr') for translation in appyTool.translations: # Get the "po" file poName = '%s-%s.po' % (appName, translation.id) - poFile = PoParser(jn(i18nFolder, poName)).parse() + poFile = PoParser(os.path.join(i18nFolder, poName)).parse() for message in poFile.messages: setattr(translation, message.id, message.getMessage()) appyTool.log('Translation "%s" updated from "%s".' % \ @@ -359,7 +357,7 @@ class ZopeInstaller: 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 = gen.String(multiplicity=(1,1), show='edit',indexed=True) title.init('title', None, 'appy') setattr(wrapperClass, 'title', title) names = self.config.attributes[wrapperClass.__name__[:-8]] @@ -368,8 +366,8 @@ class ZopeInstaller: for baseClass in klass.wrapperClass.__bases__: if baseClass.__name__ == 'AbstractWrapper': continue for name, appyType in baseClass.__dict__.iteritems(): - if not isinstance(appyType, Type) or \ - (isinstance(appyType, Ref) and appyType.isBack): + if not isinstance(appyType, gen.Type) or \ + (isinstance(appyType, gen.Ref) and appyType.isBack): continue # Back refs are initialised within fw refs appyType.init(name, baseClass, appName) diff --git a/gen/migrator.py b/gen/migrator.py index a3db7b1..29d8386 100644 --- a/gen/migrator.py +++ b/gen/migrator.py @@ -9,8 +9,7 @@ class Migrator: self.installer = installer def migrateTo_0_7_1(self): - '''Appy 0.7.1 has its own management of Ref fields and does not use - Archetypes references and the reference catalog anymore. So we must + '''Appy 0.7.1 has its own management of Ref fields. So we must update data structures that store Ref info on instances.''' ins = self.installer ins.info('Migrating to Appy 0.7.1...') diff --git a/gen/mixins/TestMixin.py b/gen/mixins/TestMixin.py index c46337e..cafc4a7 100644 --- a/gen/mixins/TestMixin.py +++ b/gen/mixins/TestMixin.py @@ -3,7 +3,7 @@ import os, os.path, sys # ------------------------------------------------------------------------------ class TestMixin: - '''This class is mixed in with any PloneTestCase.''' + '''This class is mixed in with any ZopeTestCase.''' def createUser(self, userId, roles): '''Creates a user with id p_userId with some p_roles.''' self.acl_users.addMember(userId, 'password', [], []) @@ -59,7 +59,7 @@ class TestMixin: def beforeTest(test): '''Is executed before every test.''' g = test.globs - g['tool'] = test.app.plone.get('portal_%s' % g['appName'].lower()).appy() + g['tool'] = test.app.config.appy() cfg = g['tool'].o.getProductConfig() g['appFolder'] = cfg.diskFolder moduleOrClassName = g['test'].name # Not used yet. diff --git a/gen/mixins/ToolMixin.py b/gen/mixins/ToolMixin.py index 5d6f73e..86cef2a 100644 --- a/gen/mixins/ToolMixin.py +++ b/gen/mixins/ToolMixin.py @@ -6,9 +6,9 @@ from appy.shared.data import languages import appy.gen from appy.gen import Type, Search, Selection from appy.gen.utils import SomeObjects, sequenceTypes, getClassName -from appy.gen.plone25.mixins import BaseMixin -from appy.gen.plone25.wrappers import AbstractWrapper -from appy.gen.plone25.descriptors import ClassDescriptor +from appy.gen.mixins import BaseMixin +from appy.gen.wrappers import AbstractWrapper +from appy.gen.descriptors import ClassDescriptor try: from AccessControl.ZopeSecurityPolicy import _noroles except ImportError: @@ -411,7 +411,7 @@ class ToolMixin(BaseMixin): def getCreateMeans(self, contentTypeOrAppyClass): '''Gets the different ways objects of p_contentTypeOrAppyClass (which - can be a Plone content type or a Appy class) can be created + can be a Zope content type or a Appy class) can be created (via a web form, by importing external data, etc). Result is a dict whose keys are strings (ie "form", "import"...) and whose values are additional data bout the particular mean.''' @@ -810,7 +810,7 @@ class ToolMixin(BaseMixin): 9: 'month_sep', 10: 'month_oct', 11: 'month_nov', 12: 'month_dec'} def getMonthName(self, monthNumber): '''Gets the translated month name of month numbered p_monthNumber.''' - return self.translate(self.monthsIds[int(monthNumber)], domain='plone') + return self.translate(self.monthsIds[int(monthNumber)]) # -------------------------------------------------------------------------- # Authentication-related methods @@ -824,7 +824,7 @@ class ToolMixin(BaseMixin): if jsEnabled and not cookiesEnabled: msg = self.translate(u'You must enable cookies before you can ' \ - 'log in.', domain='plone') + 'log in.') return self.goto(urlBack, msg.encode('utf-8')) # Perform the Zope-level authentication login = rq.get('__ac_name', '') @@ -835,11 +835,10 @@ class ToolMixin(BaseMixin): user = self.acl_users.validate(rq) if self.userIsAnon(): rq.RESPONSE.expireCookie('__ac', path='/') - msg = self.translate(u'Login failed', domain='plone') + msg = self.translate(u'Login failed') logMsg = 'Authentication failed (tried with login "%s")' % login else: - msg = self.translate(u'Welcome! You are now logged in.', - domain='plone') + msg = self.translate(u'Welcome! You are now logged in.') logMsg = 'User "%s" has been logged in.' % login msg = msg.encode('utf-8') self.log(logMsg) @@ -865,7 +864,7 @@ class ToolMixin(BaseMixin): session.invalidate() self.log('User "%s" has been logged out.' % userId) # Remove user from variable "loggedUsers" - from appy.gen.plone25.installer import loggedUsers + from appy.gen.installer import loggedUsers if loggedUsers.has_key(userId): del loggedUsers[userId] return self.goto(self.getApp().absolute_url()) diff --git a/gen/mixins/__init__.py b/gen/mixins/__init__.py index e1528b2..9dbee23 100644 --- a/gen/mixins/__init__.py +++ b/gen/mixins/__init__.py @@ -1,17 +1,14 @@ '''This package contains mixin classes that are mixed in with generated classes: - - mixins/BaseMixin is mixed in with Standard Archetypes classes; + - mixins/BaseMixin is mixed in with standard Zope classes; - mixins/ToolMixin is mixed in with the generated application Tool class.''' # ------------------------------------------------------------------------------ import os, os.path, sys, types, mimetypes, urllib, cgi from appy import Object -import appy.gen -from appy.gen import Type, String, Selection, Role, No, WorkflowAnonymous, \ - Transition, Permission +import appy.gen as gen from appy.gen.utils import * from appy.gen.layout import Table, defaultPageLayouts -from appy.gen.descriptors import WorkflowDescriptor -from appy.gen.plone25.descriptors import ClassDescriptor +from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor # ------------------------------------------------------------------------------ class BaseMixin: @@ -187,8 +184,7 @@ class BaseMixin: fields in the database.''' rq = self.REQUEST tool = self.getTool() - errorMessage = self.translate( - 'Please correct the indicated errors.', domain='plone') + errorMessage = self.translate('Please correct the indicated errors.') isNew = rq.get('is_new') == 'True' # If this object is created from an initiator, get info about him. initiator = None @@ -209,7 +205,7 @@ class BaseMixin: urlBack = tool.getSiteUrl() else: urlBack = self.getUrl() - self.say(self.translate('Changes canceled.', domain='plone')) + self.say(self.translate('Changes canceled.')) return self.goto(urlBack) # Object for storing validation errors @@ -245,7 +241,7 @@ class BaseMixin: obj, msg = self.createOrUpdate(isNew, values, initiator, initiatorField) # Redirect the user to the appropriate page - if not msg: msg = obj.translate('Changes saved.', domain='plone') + if not msg: msg = obj.translate('Changes saved.') # If the object has already been deleted (ie, it is a kind of transient # object like a one-shot form and has already been deleted in method # onEdit), redirect to the main site page. @@ -711,7 +707,7 @@ class BaseMixin: if not includeFake: includeIt = mayTrigger else: - includeIt = mayTrigger or isinstance(mayTrigger, No) + includeIt = mayTrigger or isinstance(mayTrigger, gen.No) if not includeNotShowable: includeIt = includeIt and transition.isShowable(wf, self) if not includeIt: continue @@ -864,7 +860,7 @@ class BaseMixin: # Get the initial workflow state initialState = self.State(name=False) # Create a Transition instance representing the initial transition. - initialTransition = Transition((initialState, initialState)) + initialTransition = gen.Transition((initialState, initialState)) initialTransition.trigger('_init_', self, wf, '') def getWorkflow(self, name=False, className=None): @@ -875,7 +871,7 @@ class BaseMixin: else: appyClass = self.getTool().getAppyClass(className) if hasattr(appyClass, 'workflow'): wf = appyClass.workflow - else: wf = WorkflowAnonymous + else: wf = gen.WorkflowAnonymous if not name: return wf return WorkflowDescriptor.getWorkflowName(wf) diff --git a/gen/model.py b/gen/model.py index a42045c..0fafbc6 100644 --- a/gen/model.py +++ b/gen/model.py @@ -1,14 +1,10 @@ '''This file contains basic classes that will be added into any user application for creating the basic structure of the application "Tool" which - is the set of web pages used for configuring the application. The "Tool" is - available to administrators under the standard Plone link "site setup". Plone - itself is shipped with several tools used for conguring the various parts of - Plone (content types, catalogs, workflows, etc.)''' + is the set of web pages used for configuring the application.''' # ------------------------------------------------------------------------------ import types -from appy.gen import * -Grp=Group # Avoid name clash between appy.gen.Group and class Group below +import appy.gen as gen # Prototypical instances of every type ----------------------------------------- class Protos: @@ -73,7 +69,7 @@ class ModelClass: value = appyType.getInputLayouts() elif isinstance(value, basestring): value = '"%s"' % value - elif isinstance(value, Ref): + elif isinstance(value, gen.Ref): if not value.isBack: continue value = klass._appy_getTypeBody(value, wrapperName) elif type(value) == type(ModelClass): @@ -82,11 +78,11 @@ class ModelClass: value = value.__name__ else: value = '%s.%s' % (moduleName, value.__name__) - elif isinstance(value, Selection): + elif isinstance(value, gen.Selection): value = 'Selection("%s")' % value.methodName - elif isinstance(value, Grp): + elif isinstance(value, gen.Group): value = 'Grp("%s")' % value.name - elif isinstance(value, Page): + elif isinstance(value, gen.Page): value = 'pages["%s"]' % value.name elif callable(value): value = '%s.%s' % (wrapperName, value.__name__) @@ -135,20 +131,22 @@ class User(ModelClass): _appy_attributes = ['title', 'name', 'firstName', 'login', 'password1', 'password2', 'roles'] # All methods defined below are fake. Real versions are in the wrapper. - title = String(show=False, indexed=True) + title = gen.String(show=False, indexed=True) gm = {'group': 'main', 'multiplicity': (1,1), 'width': 25} - name = String(**gm) - firstName = String(**gm) + name = gen.String(**gm) + firstName = gen.String(**gm) def showLogin(self): pass def validateLogin(self): pass - login = String(show=showLogin, validator=validateLogin, indexed=True, **gm) + login = gen.String(show=showLogin, validator=validateLogin, + indexed=True, **gm) def showPassword(self): pass def validatePassword(self): pass - password1 = String(format=String.PASSWORD, show=showPassword, - validator=validatePassword, **gm) - password2 = String(format=String.PASSWORD, show=showPassword, **gm) + password1 = gen.String(format=gen.String.PASSWORD, show=showPassword, + validator=validatePassword, **gm) + password2 = gen.String(format=gen.String.PASSWORD, show=showPassword, **gm) gm['multiplicity'] = (0, None) - roles = String(validator=Selection('getGrantableRoles'), indexed=True, **gm) + roles = gen.String(validator=gen.Selection('getGrantableRoles'), + indexed=True, **gm) # The Group class -------------------------------------------------------------- class Group(ModelClass): @@ -156,25 +154,25 @@ class Group(ModelClass): _appy_attributes = ['title', 'login', 'roles', 'users'] # All methods defined below are fake. Real versions are in the wrapper. m = {'group': 'main', 'width': 25, 'indexed': True} - title = String(multiplicity=(1,1), **m) + title = gen.String(multiplicity=(1,1), **m) def showLogin(self): pass def validateLogin(self): pass - login = String(show=showLogin, validator=validateLogin, - multiplicity=(1,1), **m) - roles = String(validator=Selection('getGrantableRoles'), - multiplicity=(0,None), **m) - users = Ref(User, multiplicity=(0,None), add=False, link=True, - back=Ref(attribute='groups', show=True), - showHeaders=True, shownInfo=('title', 'login')) + login = gen.String(show=showLogin, validator=validateLogin, + multiplicity=(1,1), **m) + roles = gen.String(validator=gen.Selection('getGrantableRoles'), + multiplicity=(0,None), **m) + users = gen.Ref(User, multiplicity=(0,None), add=False, link=True, + back=gen.Ref(attribute='groups', show=True), + showHeaders=True, shownInfo=('title', 'login')) # The Translation class -------------------------------------------------------- class Translation(ModelClass): _appy_attributes = ['po', 'title'] # All methods defined below are fake. Real versions are in the wrapper. def getPoFile(self): pass - po = Action(action=getPoFile, page=Page('actions', show='view'), - result='filetmp') - title = String(show=False, indexed=True) + po = gen.Action(action=getPoFile, page=gen.Page('actions', show='view'), + result='filetmp') + title = gen.String(show=False, indexed=True) def label(self): pass def show(self, name): pass @@ -195,30 +193,31 @@ class Tool(ModelClass): # Tool attributes def validPythonWithUno(self, value): pass # Real method in the wrapper - unoEnabledPython = String(group="connectionToOpenOffice", - validator=validPythonWithUno) - openOfficePort = Integer(default=2002, group="connectionToOpenOffice") - numberOfResultsPerPage = Integer(default=30, show=False) - listBoxesMaximumWidth = Integer(default=100, show=False) - appyVersion = String(show=False, layouts='f') + unoEnabledPython = gen.String(group="connectionToOpenOffice", + validator=validPythonWithUno) + openOfficePort = gen.Integer(default=2002, group="connectionToOpenOffice") + numberOfResultsPerPage = gen.Integer(default=30, show=False) + listBoxesMaximumWidth = gen.Integer(default=100, show=False) + appyVersion = gen.String(show=False, layouts='f') def refreshSecurity(self): pass # Real method in the wrapper - refreshSecurity = Action(action=refreshSecurity, confirm=True) + refreshSecurity = gen.Action(action=refreshSecurity, confirm=True) # Ref(User) will maybe be transformed into Ref(CustomUserClass). - users = Ref(User, multiplicity=(0,None), add=True, link=False, - back=Ref(attribute='toTool', show=False), - page=Page('users', show='view'), - queryable=True, queryFields=('title', 'login'), - showHeaders=True, shownInfo=('title', 'login', 'roles')) - groups = Ref(Group, multiplicity=(0,None), add=True, link=False, - back=Ref(attribute='toTool2', show=False), - page=Page('groups', show='view'), - queryable=True, queryFields=('title', 'login'), - showHeaders=True, shownInfo=('title', 'login', 'roles')) - translations = Ref(Translation, multiplicity=(0,None),add=False,link=False, - back=Ref(attribute='trToTool', show=False), show='view', - page=Page('translations', show='view')) - enableNotifications = Boolean(default=True, - page=Page('notifications', show=False)) + users = gen.Ref(User, multiplicity=(0,None), add=True, link=False, + back=gen.Ref(attribute='toTool', show=False), + page=gen.Page('users', show='view'), + queryable=True, queryFields=('title', 'login'), + showHeaders=True, shownInfo=('title', 'login', 'roles')) + groups = gen.Ref(Group, multiplicity=(0,None), add=True, link=False, + back=gen.Ref(attribute='toTool2', show=False), + page=gen.Page('groups', show='view'), + queryable=True, queryFields=('title', 'login'), + showHeaders=True, shownInfo=('title', 'login', 'roles')) + translations = gen.Ref(Translation, multiplicity=(0,None), add=False, + link=False, show='view', + back=gen.Ref(attribute='trToTool', show=False), + page=gen.Page('translations', show='view')) + enableNotifications = gen.Boolean(default=True, + page=gen.Page('notifications', show=False)) @classmethod def _appy_clean(klass): diff --git a/gen/notifier.py b/gen/notifier.py index f5e2990..cdc273f 100644 --- a/gen/notifier.py +++ b/gen/notifier.py @@ -41,8 +41,8 @@ def sendMail(obj, transition, transitionName, workflow): '''Sends mail about p_transition that has been triggered on p_obj that is controlled by p_workflow.''' wfName = WorkflowDescriptor.getWorkflowName(workflow.__class__) - ploneObj = obj.o - portal = ploneObj.portal_url.getPortalObject() + zopeObj = obj.o + tool = zopeObj.getTool() mailInfo = transition.notify(workflow, obj) if not mailInfo[0]: return # Send a mail to nobody. # mailInfo may be one of the following: @@ -54,15 +54,15 @@ def sendMail(obj, transition, transitionName, workflow): # address or one role) or sequences of strings. # Determine mail subject and body. if len(mailInfo) <= 2: - # The user didn't mention mail body and subject. We will use - # those defined from i18n labels. - wfHistory = ploneObj.getWorkflowHistory() + # The user didn't mention mail body and subject. We will use those + # defined from i18n labels. + wfHistory = zopeObj.getHistory() labelPrefix = '%s_%s' % (wfName, transitionName) tName = obj.translate(labelPrefix) - keys = {'siteUrl': portal.absolute_url(), - 'siteTitle': portal.Title(), - 'objectUrl': ploneObj.absolute_url(), - 'objectTitle': ploneObj.Title(), + keys = {'siteUrl': tool.getPath('/').absolute_url(), + 'siteTitle': tool.getAppName(), + 'objectUrl': zopeObj.absolute_url(), + 'objectTitle': zopeObj.Title(), 'transitionName': tName, 'transitionComment': wfHistory[0]['comments']} mailSubject = obj.translate(labelPrefix + '_mail_subject', keys) diff --git a/gen/odt/__init__.py b/gen/odt/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gen/odt/generator.py b/gen/odt/generator.py deleted file mode 100644 index b4b4d89..0000000 --- a/gen/odt/generator.py +++ /dev/null @@ -1,54 +0,0 @@ -'''This file contains the main Generator class used for generating an - ODT file from an Appy application.''' - -# ------------------------------------------------------------------------------ -import os, os.path -from appy.gen import Page -from appy.gen.utils import produceNiceMessage -from appy.gen.generator import Generator as AbstractGenerator - -# ------------------------------------------------------------------------------ -class Generator(AbstractGenerator): - '''This generator generates ODT files from an Appy application.''' - - def __init__(self, *args, **kwargs): - AbstractGenerator.__init__(self, *args, **kwargs) - self.repls = {'generator': self} - - def finalize(self): - pass - - def getOdtFieldLabel(self, fieldName): - '''Given a p_fieldName, this method creates the label as it will appear - in the ODT file.''' - return '%s' % \ - (fieldName, produceNiceMessage(fieldName)) - - def generateClass(self, classDescr): - '''Is called each time an Appy class is found in the application.''' - repls = self.repls.copy() - repls['classDescr'] = classDescr - self.copyFile('basic.odt', repls, - destName='%sEdit.odt' % classDescr.klass.__name__, isPod=True) - - def fieldIsStaticallyInvisible(self, field): - '''This method determines if p_field is always invisible. It can be - verified for example if field.type.show is the boolean value False or - if the page where the field must be displayed has a boolean attribute - "show" having the boolean value False.''' - if (type(field.show) == bool) and not field.show: return True - if (type(field.page.show) == bool) and not field.page.show: return True - return False - - undumpable = ('Ref', 'Action', 'File', 'Computed') - def getRelevantAttributes(self, classDescr): - '''Some fields, like computed fields or actions, should not be dumped - into the ODT file. This method returns the list of "dumpable" - fields.''' - res = [] - for fieldName, field, klass in classDescr.getOrderedAppyAttributes(): - if (field.type not in self.undumpable) and \ - (not self.fieldIsStaticallyInvisible(field)): - res.append((fieldName, field)) - return res -# ------------------------------------------------------------------------------ diff --git a/gen/odt/templates/basic.odt b/gen/odt/templates/basic.odt deleted file mode 100644 index 7f3816a3b8ddb3cc478342b58de608603fc1be79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10487 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 diff --git a/gen/plone25/__init__.py b/gen/plone25/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gen/templates/Class.py b/gen/templates/Class.py index 2ec361c..38dec98 100644 --- a/gen/templates/Class.py +++ b/gen/templates/Class.py @@ -4,8 +4,8 @@ from OFS.Folder import Folder from appy.gen.utils import createObject from AccessControl import ClassSecurityInfo import Products..config as cfg -from appy.gen.plone25.mixins import BaseMixin -from appy.gen.plone25.mixins.ToolMixin import ToolMixin +from appy.gen.mixins import BaseMixin +from appy.gen.mixins.ToolMixin import ToolMixin from wrappers import _Wrapper as Wrapper def manage_add(self, id, title='', REQUEST=None): diff --git a/gen/templates/Styles.css.dtml b/gen/templates/Styles.css.dtml deleted file mode 100644 index 70f4dd9..0000000 --- a/gen/templates/Styles.css.dtml +++ /dev/null @@ -1,90 +0,0 @@ -#importedElem { color: grey; font-style: italic; } -.appyPod { float:right; } -.appyFocus { color: #900101; } - -.appyChanges th { - font-style: italic; - background-color: transparent; - border: 0 none transparent; - padding: 0.1em 0.1em 0.1em 0.1em; -} - -.appyChanges td { - padding: 0.1em 0.2em 0.1em 0.2em !important; - border-top: 1px dashed #8CACBB !important; - border-right: 0 none transparent !important; - border-left: 0 none transparent !important; - border-bottom: 0 none transparent !important; -} - -/* Tooltip */ -a.tooltip span { - display:none; - padding:2px 3px; - margin-top: 25px; -} -a.rtip span { margin-left:3px; } -a.ltip span { margin-left:-150px } -a.tooltip:hover span { - display: inline; - position: absolute; - border: 1px solid grey; - background-color: white; - color: #dd; -} - -/* Table styles */ -fieldset { - line-height: 1em; - border: 2px solid #8CACBB; - margin: 0.5em 0em 0.5em 0em; - padding: 0 0.7em 0.5em; -} - -.noPadding { - padding-right: 0em !important; - padding-left: 0em !important; - padding-top: 0em !important; - padding-bottom: 0em !important; -} - -.appyButton { - background: &dtml-globalBackgroundColor; url(&dtml-portal_url;/linkOpaque.gif) 5px 1px no-repeat; - cursor: pointer; - font-size: &dtml-fontSmallSize;; - padding: 1px 1px 1px 12px; - text-transform: &dtml-textTransform;; - /* overflow: visible; IE produces ugly results with this */ -} - -.fakeButton { - background: #ffd5c0 url(&dtml-portal_url;/ui/fakeTransition.gif) 5px 1px no-repeat; - padding: 3px 4px 3px 12px; -} - -/* Portlet elements */ -.portletHeader { - text-transform: none; - padding: 1px 0.5em; -} -.portletSearch { - padding: 0 0 0 0.6em; - font-style: normal; - font-size: 95%; -} -.portletGroup { - font-variant: small-caps; - font-weight: bold; - font-style: normal; -} - -.portletGroupItem { padding-left: 0.8em; font-style: italic; } -.portletMenu { margin-bottom: 0.4em; } - -/* image-right, but without border */ -.image-right { - border:0px solid Black; - clear:both; - float:right; - margin:0.5em; -} diff --git a/gen/templates/__init__.py b/gen/templates/__init__.py index 4d20f53..3452a0f 100644 --- a/gen/templates/__init__.py +++ b/gen/templates/__init__.py @@ -1,7 +1,7 @@ # Test coverage-related stuff -------------------------------------------------- import sys -from appy.gen.plone25.mixins.TestMixin import TestMixin +from appy.gen.mixins.TestMixin import TestMixin covFolder = TestMixin.getCovFolder() # The previous method checks in sys.argv whether Zope was lauched for performing # coverage tests or not. @@ -26,7 +26,7 @@ def countTest(): # ------------------------------------------------------------------------------ import config -from appy.gen.plone25.installer import ZopeInstaller +from appy.gen.installer import ZopeInstaller # Zope-level installation of the generated product. ---------------------------- def initialize(context): diff --git a/gen/templates/config.py b/gen/templates/config.py index 4d56cc9..b640024 100644 --- a/gen/templates/config.py +++ b/gen/templates/config.py @@ -5,9 +5,7 @@ import wrappers # The following imports are here for allowing mixin classes to access those -# elements without being statically dependent on Plone/Zope packages. Indeed, -# every Archetype instance has a method "getProductConfig" that returns this -# module. +# elements without being statically dependent on Zope packages. from persistent.list import PersistentList from zExceptions import BadRequest from ZPublisher.HTTPRequest import BaseRequest diff --git a/gen/templates/configure.zcml b/gen/templates/configure.zcml deleted file mode 100644 index be6e398..0000000 --- a/gen/templates/configure.zcml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/gen/templates/testAll.py b/gen/templates/testAll.py index 4edff9f..0e34d74 100644 --- a/gen/templates/testAll.py +++ b/gen/templates/testAll.py @@ -3,17 +3,13 @@ from unittest import TestSuite from Testing import ZopeTestCase from Testing.ZopeTestCase import ZopeDocTestSuite -from Products.PloneTestCase import PloneTestCase -from appy.gen.plone25.mixins.TestMixin import TestMixin, beforeTest, afterTest +from appy.gen.mixins.TestMixin import TestMixin, beforeTest, afterTest -# Initialize Zope & Plone test systems ----------------------------------------- -ZopeTestCase.installProduct('PloneLanguageTool') +# Initialize the Zope test system ---------------------------------------------- ZopeTestCase.installProduct('') -PloneTestCase.setupPloneSite(products=['PloneLanguageTool', - '']) -class Test(PloneTestCase.PloneTestCase, TestMixin): +class Test(ZopeTestCase.ZopeTestCase, TestMixin): '''Base test class for test cases.''' # Data needed for defining the tests ------------------------------------------- diff --git a/gen/templates/wrappers.py b/gen/templates/wrappers.py index 9149b7f..92f85b7 100644 --- a/gen/templates/wrappers.py +++ b/gen/templates/wrappers.py @@ -1,11 +1,11 @@ # ------------------------------------------------------------------------------ from appy.gen import * Grp = Group # Avoid name clashes with the Group class below and appy.gen.Group -from appy.gen.plone25.wrappers import AbstractWrapper -from appy.gen.plone25.wrappers.ToolWrapper import ToolWrapper as WTool -from appy.gen.plone25.wrappers.UserWrapper import UserWrapper as WUser -from appy.gen.plone25.wrappers.GroupWrapper import GroupWrapper as WGroup -from appy.gen.plone25.wrappers.TranslationWrapper import TranslationWrapper as WT +from appy.gen.wrappers import AbstractWrapper +from appy.gen.wrappers.ToolWrapper import ToolWrapper as WTool +from appy.gen.wrappers.UserWrapper import UserWrapper as WUser +from appy.gen.wrappers.GroupWrapper import GroupWrapper as WGroup +from appy.gen.wrappers.TranslationWrapper import TranslationWrapper as WT from Globals import InitializeClass from AccessControl import ClassSecurityInfo tfw = {"edit":"f","cell":"f","view":"f"} # Layout for Translation fields diff --git a/gen/ui/import.pt b/gen/ui/import.pt index 500956b..6f34d2c 100644 --- a/gen/ui/import.pt +++ b/gen/ui/import.pt @@ -1,23 +1,9 @@ - - -Disable standard Plone green tabs -
- -
-
- -Fill main slot of Plone main_template - - + + +
Form for importing several meetings at once.
+ tal:attributes="action python: tool.absolute_url()+'/do'" method="post"> @@ -120,6 +106,6 @@ tal:condition="python: importElems[1] and not allAreImported" tal:attributes="value python:tool.translate('import_many')"/>

- - + + diff --git a/gen/ui/page.pt b/gen/ui/page.pt index 88033e2..fa1afd9 100644 --- a/gen/ui/page.pt +++ b/gen/ui/page.pt @@ -70,11 +70,11 @@ - - - - - + + + + +   - History ||  + History ||  Show document creator @@ -263,32 +263,28 @@ + title="Previous" tal:attributes="src string:$appUrl/ui/previous.png"/> - + + title="Save" tal:attributes="src string:$appUrl/ui/save.png"/> + title="Cancel" tal:attributes="src string:$appUrl/ui/cancel.png"/> - @@ -303,14 +299,12 @@ + title="Next" tal:attributes="src string:$appUrl/ui/next.png"/> - + diff --git a/gen/ui/portlet.pt b/gen/ui/portlet.pt index 742aeb5..5784d18 100644 --- a/gen/ui/portlet.pt +++ b/gen/ui/portlet.pt @@ -117,7 +117,7 @@ tal:content="structure python: _(label)"> Delete the element diff --git a/gen/ui/widgets/action.pt b/gen/ui/widgets/action.pt index 53e9720..9967654 100644 --- a/gen/ui/widgets/action.pt +++ b/gen/ui/widgets/action.pt @@ -14,10 +14,7 @@ onClick python: 'askConfirm(\'form\', \'%s\', "%s")' % (formId, labelConfirm)"/> - The previous onClick is simply used to prevent Plone - from adding a CSS class that displays a popup when the user triggers the form multiple - times. + tal:attributes="value label"/> diff --git a/gen/ui/widgets/boolean.pt b/gen/ui/widgets/boolean.pt index fcd89bb..cc10d4c 100644 --- a/gen/ui/widgets/boolean.pt +++ b/gen/ui/widgets/boolean.pt @@ -29,11 +29,11 @@
   - + - + diff --git a/gen/ui/widgets/file.pt b/gen/ui/widgets/file.pt index d0372cb..de70889 100644 --- a/gen/ui/widgets/file.pt +++ b/gen/ui/widgets/file.pt @@ -24,14 +24,13 @@
- Keep the file untouched. + Keep the file unchanged. - +
Delete the file. @@ -39,8 +38,7 @@ tal:attributes="name string:${name}_delete; id string:${name}_delete; onclick string:document.getElementById('${name}_file').disabled=true;"/> - +
Replace with a new file. @@ -49,8 +47,7 @@ name string:${name}_delete; id string:${name}_upload; onclick string:document.getElementById('${name}_file').disabled=false"/> - +
The upload field. diff --git a/gen/ui/widgets/ref.pt b/gen/ui/widgets/ref.pt index 6f2a1cd..1d20dcd 100644 --- a/gen/ui/widgets/ref.pt +++ b/gen/ui/widgets/ref.pt @@ -43,14 +43,13 @@
Delete the element diff --git a/gen/utils.py b/gen/utils.py index 94872fd..5389cfd 100644 --- a/gen/utils.py +++ b/gen/utils.py @@ -247,30 +247,30 @@ CONVERSION_ERROR = 'An error occurred while executing command "%s". %s' class FileWrapper: '''When you get, from an appy object, the value of a File attribute, you get an instance of this class.''' - def __init__(self, atFile): + def __init__(self, zopeFile): '''This constructor is only used by Appy to create a nice File instance - from a Plone/Zope corresponding instance (p_atFile). If you need to + from a Zope corresponding instance (p_zopeFile). If you need to create a new file and assign it to a File attribute, use the attribute setter, do not create yourself an instance of this class.''' d = self.__dict__ - d['_atFile'] = atFile # Not for you! - d['name'] = atFile.filename - d['content'] = atFile.data - d['mimeType'] = atFile.content_type - d['size'] = atFile.size # In bytes + d['_zopeFile'] = zopeFile # Not for you! + d['name'] = zopeFile.filename + d['content'] = zopeFile.data + d['mimeType'] = zopeFile.content_type + d['size'] = zopeFile.size # In bytes def __setattr__(self, name, v): d = self.__dict__ if name == 'name': - self._atFile.filename = v + self._zopeFile.filename = v d['name'] = v elif name == 'content': - self._atFile.update_data(v, self.mimeType, len(v)) + self._zopeFile.update_data(v, self.mimeType, len(v)) d['content'] = v d['size'] = len(v) elif name == 'mimeType': - self._atFile.content_type = self.mimeType = v + self._zopeFile.content_type = self.mimeType = v else: raise 'Impossible to set attribute %s. "Settable" attributes ' \ 'are "name", "content" and "mimeType".' % name @@ -326,8 +326,7 @@ def getClassName(klass, appName=None): Zope class. For some classes, name p_appName is required: it is part of the class name.''' moduleName = klass.__module__ - if (moduleName == 'appy.gen.plone25.model') or \ - moduleName.endswith('.wrappers'): + if (moduleName == 'appy.gen.model') or moduleName.endswith('.wrappers'): # This is a model (generation time or run time) res = appName + klass.__name__ elif klass.__bases__ and (klass.__bases__[-1].__module__ == 'appy.gen'): diff --git a/gen/wrappers/GroupWrapper.py b/gen/wrappers/GroupWrapper.py index 32bd3f8..47c2ee7 100644 --- a/gen/wrappers/GroupWrapper.py +++ b/gen/wrappers/GroupWrapper.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------ -from appy.gen.plone25.wrappers import AbstractWrapper +from appy.gen.wrappers import AbstractWrapper # ------------------------------------------------------------------------------ class GroupWrapper(AbstractWrapper): diff --git a/gen/wrappers/ToolWrapper.py b/gen/wrappers/ToolWrapper.py index 949bab2..c240fe8 100644 --- a/gen/wrappers/ToolWrapper.py +++ b/gen/wrappers/ToolWrapper.py @@ -2,7 +2,7 @@ import os.path import appy from appy.shared.utils import executeCommand -from appy.gen.plone25.wrappers import AbstractWrapper +from appy.gen.wrappers import AbstractWrapper # ------------------------------------------------------------------------------ _PY = 'Please specify a file corresponding to a Python interpreter ' \ diff --git a/gen/wrappers/TranslationWrapper.py b/gen/wrappers/TranslationWrapper.py index 3a91233..d1ed616 100644 --- a/gen/wrappers/TranslationWrapper.py +++ b/gen/wrappers/TranslationWrapper.py @@ -1,6 +1,6 @@ # ------------------------------------------------------------------------------ import os.path -from appy.gen.plone25.wrappers import AbstractWrapper +from appy.gen.wrappers import AbstractWrapper from appy.gen.po import PoFile, PoMessage from appy.shared.utils import getOsTempFolder diff --git a/gen/wrappers/UserWrapper.py b/gen/wrappers/UserWrapper.py index 1d6c310..8c53709 100644 --- a/gen/wrappers/UserWrapper.py +++ b/gen/wrappers/UserWrapper.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------ -from appy.gen.plone25.wrappers import AbstractWrapper +from appy.gen.wrappers import AbstractWrapper # ------------------------------------------------------------------------------ class UserWrapper(AbstractWrapper):
ActionByDateComment
ActionByDateComment
- @@ -136,7 +136,7 @@ - diff --git a/gen/ui/result.pt b/gen/ui/result.pt index ebdae1f..318a3b7 100644 --- a/gen/ui/result.pt +++ b/gen/ui/result.pt @@ -125,13 +125,12 @@ - + - +