def __init__(self, klass, orderedAttributes, generator): appy.gen.descriptors.ClassDescriptor.__init__(self, klass, orderedAttributes, generator) self.schema = '' # The archetypes schema will be generated here 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 # need to generate i18n labels for every child class of the class # that declared pages and groups. self.labelsToPropagate = [] #~[PoMessage]~ Some labels (like page, # group or action names) need to be propagated in children classes # (because they contain the class name). But at this time we don't know # yet every sub-class. So we store those labels here; the Generator # will propagate them later. self.toolFieldsToPropagate = [] # For this class, some fields have # been defined on the Tool class. Those fields need to be defined # for child classes of this class as well, but at this time we don't # know yet every sub-class. So we store field definitions here; the # Generator will propagate them later. self.name = getClassName(self.klass, generator.applicationName) self.predefined = False self.customized = False # Phase and page names will be calculated later, when first required. self.phases = None self.pages = None
def addReferer(self, fieldDescr, relationship): '''p_fieldDescr is a Ref type definition. We will create in config.py a dict that lists all back references, by type.''' k = fieldDescr.appyType.klass refClassName = getClassName(k, self.applicationName) if not self.referers.has_key(refClassName): self.referers[refClassName] = [] self.referers[refClassName].append( (fieldDescr, relationship))
def getPortalType(self, metaTypeOrAppyClass): '''Returns the name of the portal_type that is based on p_metaTypeOrAppyType.''' appName = self.getProductConfig().PROJECTNAME if not isinstance(metaTypeOrAppyClass, basestring): res = getClassName(metaTypeOrAppyClass, appName) if res.find('Extensions_appyWrappers') != -1: elems = res.split('_') res = '%s%s' % (elems[1], elems[4]) return res
def init(self, name, klass, appName): '''When the application server starts, this secondary constructor is 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 = gutils.getClassName(klass, appName) # Recompute the ID (and derived attributes) that may have changed if # we are in debug mode (because we recreate new Field instances). self.id = id(self) # Remember master name on every slave for slave in self.slaves: slave.masterName = name # Determine ids of i18n labels for this field labelName = name trPrefix = None if self.label: 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]: trPrefix = self.label[0] if not trPrefix: trPrefix = prefix # Determine name to use for i18n self.labelId = '%s_%s' % (trPrefix, labelName) self.descrId = self.labelId + '_descr' self.helpId = self.labelId + '_help' # Determine read and write permissions for this field rp = self.specificReadPermission if rp and not isinstance(rp, basestring): self.readPermission = '%s: Read %s %s' % (appName, prefix, name) elif rp and isinstance(rp, basestring): self.readPermission = rp else: self.readPermission = 'read' wp = self.specificWritePermission if wp and not isinstance(wp, basestring): self.writePermission = '%s: Write %s %s' % (appName, prefix, name) elif wp and isinstance(wp, basestring): self.writePermission = wp else: self.writePermission = 'write' if (self.type == '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) if self.type == "List": for subName, subField in self.fields: fullName = '%s_%s' % (name, subName) subField.init(fullName, klass, appName) subField.name = '%s*%s' % (name, subName)
def getPortalType(self, metaTypeOrAppyClass): '''Returns the name of the portal_type that is based on p_metaTypeOrAppyType.''' appName = self.getProductConfig().PROJECTNAME res = metaTypeOrAppyClass if not isinstance(metaTypeOrAppyClass, basestring): res = getClassName(metaTypeOrAppyClass, appName) if res.find('_wrappers') != -1: elems = res.split('_') res = '%s%s' % (elems[1], elems[4]) if res in ('User', 'Group', 'Translation'): res = appName + res return res
def walkRef(self): '''How to generate a Ref?''' relationship = '%s_%s_rel' % (self.classDescr.name, self.fieldName) self.fieldType = 'ReferenceField' self.widgetType = 'ReferenceWidget' self.fieldParams['relationship'] = relationship if self.appyType.isMultiValued(): self.fieldParams['multiValued'] = True # Update the list of referers self.generator.addReferer(self, relationship) # Add the widget label for the back reference refClassName = getClassName(self.appyType.klass, self.applicationName) backLabel = "%s_%s" % (refClassName, self.appyType.back.attribute) poMsg = PoMessage(backLabel, '', self.appyType.back.attribute) poMsg.produceNiceDefault() self.generator.labels.append(poMsg) # Add the label for the confirm message if relevant if self.appyType.addConfirm: label = '%s_%s_addConfirm' % (self.classDescr.name, self.fieldName) msg = PoMessage(label, '', PoMessage.CONFIRM) self.generator.labels.append(msg)
def generateClass(self, classDescr): '''Is called each time an Appy class is found in the application, for generating the corresponding Archetype class and schema.''' k = classDescr.klass print 'Generating %s.%s (gen-class)...' % (k.__module__, k.__name__) if not classDescr.isAbstract(): self.tool.addWorkflowFields(classDescr) # Determine base archetypes schema and class baseClass = 'BaseContent' baseSchema = 'BaseSchema' if classDescr.isFolder(): baseClass = 'OrderedBaseFolder' baseSchema = 'OrderedBaseFolderSchema' parents = ['BaseMixin', baseClass] imports = [] implements = [baseClass] for baseClass in classDescr.klass.__bases__: if self.determineAppyType(baseClass) == 'class': bcName = getClassName(baseClass) parents.remove('BaseMixin') parents.insert(0, bcName) implements.append(bcName) imports.append('from %s import %s' % (bcName, bcName)) baseSchema = '%s.schema' % bcName break parents = ','.join(parents) implements = '+'.join(['(getattr(%s,"__implements__",()),)' % i \ for i in implements]) classDoc = classDescr.klass.__doc__ if not classDoc: classDoc = 'Class generated with appy.gen.' # If the class is abstract I will not register it register = "registerType(%s, '%s')" % (classDescr.name, self.applicationName) if classDescr.isAbstract(): register = '' repls = self.repls.copy() classDescr.generateSchema() repls.update({ 'imports': '\n'.join(imports), 'parents': parents, 'className': classDescr.klass.__name__, 'global_allow': 1, 'genClassName': classDescr.name, 'baseMixin':'BaseMixin', 'classDoc': classDoc, 'applicationName': self.applicationName, 'fields': classDescr.schema, 'methods': classDescr.methods, 'implements': implements, 'baseSchema': baseSchema, 'static': '', 'register': register, 'toolInstanceName': self.toolInstanceName}) fileName = '%s.py' % classDescr.name # Create i18n labels (class name, description and plural form) poMsg = PoMessage(classDescr.name, '', classDescr.klass.__name__) poMsg.produceNiceDefault() self.labels.append(poMsg) poMsgDescr = PoMessage('%s_edit_descr' % classDescr.name, '', ' ') self.labels.append(poMsgDescr) poMsgPl = PoMessage('%s_plural' % classDescr.name, '', classDescr.klass.__name__+'s') poMsgPl.produceNiceDefault() self.labels.append(poMsgPl) # Create i18n labels for searches for search in classDescr.getSearches(classDescr.klass): searchLabel = '%s_search_%s' % (classDescr.name, search.name) labels = [searchLabel, '%s_descr' % searchLabel] if search.group: grpLabel = '%s_searchgroup_%s' % (classDescr.name, search.group) labels += [grpLabel, '%s_descr' % grpLabel] for label in labels: default = ' ' if label == searchLabel: default = search.name poMsg = PoMessage(label, '', default) poMsg.produceNiceDefault() if poMsg not in self.labels: self.labels.append(poMsg) # Generate the resulting Archetypes class and schema. self.copyFile('Class.py', repls, destName=fileName)