def type_id(source, target): # calculate type id class_ = read_target_node(source, target) if source.parent.stereotype('pyegg:pymodule'): name = '%s.%s' % (class_base_name(class_), class_.classname.lower()) else: name = class_base_name(class_) return name
def console_scripts_collect(self, source, target): # collect information to define console_script entry points tok = token('console_scripts', True, defs={}) tgv = TaggedValues(source) name = tgv.direct('script_name', 'pyegg:console_script', source.name) tgt = read_target_node(source, target.target) if source.stereotype('pyegg:function') and not source.parent.stereotype('pyegg:pymodule'): path = class_base_name(tgt.parent) else: path = class_base_name(tgt) tok.defs[name] = '%s:%s' % (path, source.name)
def pyclass(self, source, target): """Create python classes. """ if source.stereotype('pyegg:stub'): return # skip class generation if previous custom handler mark this class as # already handled custom_handled = token('custom_handled_classes', True, classes=list()) handled_classes = [str(uuid) for uuid in custom_handled.classes] if str(source.uuid) in handled_classes: return name = source.name module = target.anchor try: set_copyright(source, module) except AttributeError: msg = 'Package "%s" must have either <<pymodule>> or ' + \ '<<pypackage>> stereotype' msg = msg % dotted_path(module) raise ValueError(msg) if module.classes(name): class_ = module.classes(name)[0] target.finalize(source, class_) return class_ = python.Class(name) module[str(class_.uuid)] = class_ if not is_class_a_function(source) \ and not source.parent.stereotype('pyegg:pymodule'): imp = Imports(module.parent['__init__.py']) imp.set(class_base_name(class_), [[class_.classname, None]]) target.finalize(source, class_)
def interfacegeneralization(self, source, target): """Create generalization between interfaces . """ inheritance = Inheritance(source) targetclass = read_target_node(source, target.target) if targetclass: tok = token(str(targetclass.uuid), True, depends_on=set()) for obj in inheritance.values(): tok.depends_on.add(read_target_node(obj.context, target.target)) if not obj.context.name in targetclass.bases: targetclass.bases.append(obj.context.name) tgv = TaggedValues(obj.context) import_from = tgv.direct('import', 'pyegg:stub') if import_from is not UNSET: imp = Imports(targetclass.__parent__) imp.set(import_from, [[obj.context.name, None]]) derive_from = read_target_node(obj.context, target.target) if not derive_from: continue if targetclass.__parent__ is not derive_from.__parent__: imp = Imports(targetclass.__parent__) imp.set(class_base_name(derive_from), [[derive_from.classname, None]]) if targetclass and not targetclass.bases: targetclass.bases.append('Interface')
def apiexporter(self, source,target): """Takes classes with 'api' stereotype and imports them into the pyegg's __init__.py. """ egg = egg_source(source) targetegg = read_target_node(egg, target.target) init = targetegg['__init__.py'] imps = Imports(init) klass = read_target_node(source, target.target) imps.set(class_base_name(klass), [[source.name, None]])
def createpermission(self, source, target): targetclass = read_target_node(source, target.target) module = targetclass.parent targetdir = module.parent path = class_base_name(targetclass) # prevent python class from being generated sts = [st.name for st in source.stereotypes] # only if no other steroetypes are attached if 'zca:permission' in sts and len(sts) == 1: # class also has to be deleted from __init__ init = targetdir['__init__.py'] for imp in init.imports(): if imp.fromimport == path and imp.names[0][0] == source.name: del init[imp.__name__] del module[targetclass.__name__] # and now write the permission definition into confure.zcml zcmlpath = targetdir.path zcmlpath.append('configure.zcml') fullpath = os.path.join(*zcmlpath) if 'configure.zcml' not in targetdir.keys(): zcml = ZCMLFile(fullpath) targetdir['configure.zcml'] = zcml else: zcml = targetdir['configure.zcml'] addZcmlRef(targetdir, zcml) id = TaggedValues(source).direct('id', 'zca:permission') if id is UNSET: permid = dotted_path(source) else: permid = id found_directives = zcml.filter(tag='permission', attr='id', value=permid) if found_directives: directive = found_directives[0] else: directive = SimpleDirective(name='permission', parent=zcml) directive.attrs['id'] = permid title = TaggedValues(source).direct('title', 'zca:permission') if not title is UNSET: directive.attrs['title'] = title description = TaggedValues(source).direct('description', 'zca:permission') if not description is UNSET: directive.attrs['description'] = description
def zcarealize(self, source, target): klass = source.implementingClassifier # if klass.stereotype('pyegg:function'): # # XXX: <<function>> <<adapter>> on class # return ifacename = source.contract.name targetclass = read_target_node(klass, target.target) targetinterface = read_target_node(source.contract, target.target) tok = token(str(targetclass.uuid), True, realizes=[], provides=None) ifdef = {'name':source.contract.name} if targetinterface: ifdef['path'] = dotted_path(source.contract) # then its a stub else: tgv = TaggedValues(source.contract) impf = tgv.direct('import', 'pyegg:stub') if not impf: msg = 'Stub class %s needs a TaggedValue for "import"' \ % dotted_path(klass) raise ValueError(msg) ifdef['path'] = '.'.join([impf, ifdef['name']]) tok.realizes.append(ifdef) if source.stereotype('zca:provides'): tok.provides = ifdef # import the interface tgv = TaggedValues(source.contract) import_from = tgv.direct('import', 'pyegg:stub') imp = Imports(targetclass.__parent__) if targetinterface: tok = token(str(targetclass.uuid), True, depends_on=set()) tok.depends_on.add(targetinterface) # if (targetinterface is None -> Stub) or targetinterface is in another # module -> import if not targetinterface \ or targetclass.__parent__ is not targetinterface.__parent__: # we have a stub interface if import_from is not UNSET: basepath = import_from imp.set(basepath, [[source.contract.name, None]]) else: basepath = class_base_name(targetinterface) imp.set(basepath, [[targetinterface.classname, None]])
def createschemaclass(self, source, target): """create the schema interface class on the fly. """ klass = read_target_node(source, target.target) module = klass.parent schemaclassname = 'I' + klass.classname found = module.classes(schemaclassname) if found: schemaclass = found[0] else: schemaclass = python.Class(classname=schemaclassname) schemaclass.__name__ = schemaclass.uuid module.insertbefore(schemaclass, klass) # expose it in __init__ imp = Imports(module.parent['__init__.py']) imp.set(class_base_name(schemaclass), [[schemaclassname, None]]) # mark the content class for deletion if not needed createit = TaggedValues(source).direct('create_contentclass', 'plone:content_type', False) if not (createit or klass.functions()): token(str(klass.uuid), True, dont_generate=True)
def gsprofiletypes(self, source, target): """Create or extend types.xml and corresponding TYPENAME.xml. """ egg = egg_source(source) package = read_target_node(egg, target.target) default = package['profiles']['default'] # create types foder if not exists if not 'types' in default: default['types'] = Directory() # read or create types.xml if 'types.xml' in default: types = default['types.xml'] else: types = default['types.xml'] = DTMLTemplate() # set template and params if not done yet if not types.template: types.template = 'agx.generator.plone:templates/types.xml' types.params['portalTypes'] = list() # calculate type name full_name = type_id(source, target.target) # add portal type to types.xml types.params['portalTypes'].append({ 'name': full_name, 'meta_type': 'Dexterity FTI', }) # add TYPENAME.xml to types folder # read or create TYPENAME.xml name = '%s.xml' % full_name if name in default['types']: type = default['types'][name] else: type = default['types'][name] = DTMLTemplate() # set template used for TYPENAME.xml type.template = 'agx.generator.plone:templates/type.xml' # set template params # FTI properties can be added by prefixing param key with 'fti:' # XXX: calculate from model content_icon = '++resource++%s/%s_icon.png' % ( egg.name, source.name.lower()) type.params['ctype'] = dict() # general type.params['ctype']['name'] = full_name type.params['ctype']['meta_type'] = 'Dexterity FTI' type.params['ctype']['i18n_domain'] = egg.name # basic metadata type.params['ctype']['title'] = source.name type.params['ctype']['description'] = source.name type.params['ctype']['content_icon'] = content_icon type.params['ctype']['allow_discussion'] = 'False' type.params['ctype']['global_allow'] = 'True' # XXX: maybe False for non contained ones? type.params['ctype']['filter_content_types'] = 'True' type.params['ctype']['allowed_content_types'] = list() # dexterity specific class_ = read_target_node(source, target.target) schemaclass=getschemaclass(source,target) schema = '%s.%s' % (class_base_name(class_), schemaclass.classname) # XXX: check whether container or leaf if token(str(class_.uuid), False, dont_generate=False).dont_generate: klass = 'plone.dexterity.content.Item' else: klass = '%s.%s' % (class_base_name(class_), class_.classname) type.params['ctype']['schema'] = schema type.params['ctype']['klass'] = klass type.params['ctype']['add_permission'] = 'cmf.AddPortalContent' type.params['ctype']['behaviors'] = list() # View information type.params['ctype']['view_methods'] = ['view'] type.params['ctype']['default_view'] = 'view' type.params['ctype']['default_view_fallback'] = 'False' # Method aliases type.params['ctype']['aliases'] = list() type.params['ctype']['aliases'].append({ 'from': '(Default)', 'to': '(dynamic view)', }) type.params['ctype']['aliases'].append({ 'from': 'view', 'to': '(selected layout)', }) type.params['ctype']['aliases'].append({ 'from': 'edit', 'to': '@@edit', }) type.params['ctype']['aliases'].append({ 'from': 'sharing', 'to': '@@sharing', }) # Actions type.params['ctype']['actions'] = list() type.params['ctype']['actions'].append({ 'action_id': 'edit', 'title': 'Edit', 'category': 'object', 'condition_expr': '', 'url_expr': 'string:${object_url}/edit', 'visible': 'True', 'permissions': ['Modify portal content'], }) type.params['ctype']['actions'].append({ 'action_id': 'view', 'title': 'View', 'category': 'object', 'condition_expr': '', 'url_expr': 'string:${object_url}/view', 'visible': 'True', 'permissions': ['View'], })