def sqlrelations_foreignkeys(self, source, target): """Generate foreign key attributes. """ if source.stereotype('pyegg:stub'): return if not source.stereotype('sql:sql_content'): return targetclass = read_target_node(source, target.target) module=targetclass.parent # get the last attribute and append there the foreignkeys attrs = targetclass.attributes() attrnames = [att.targets[0] for att in attrs] incoming_relations = token(str(source.uuid), True, incoming_relations=[]).incoming_relations for relend in incoming_relations: klass = relend.type #no foreign keys needed for Association Classes if IAssociationClass.providedBy(relend.association): continue #fetch the opposite relation end if relend==relend.association.memberEnds[0]: otherend = relend.association.memberEnds[1] else: otherend = relend.association.memberEnds[0] otherclass = otherend.type nullable = not relend.aggregationkind=='composite' joins=calculate_joins(source, targetclass, otherclass, otherend.name, nullable = nullable) token(str(otherend.uuid), True, joins=joins)
def mark_generators_as_stub(self, source, target): isgenerator = getUtility(IScope, 'uml2fs.generator') if not isgenerator(source): return token('custom_handled_classes', True, classes=[]).classes.append(str(source.uuid)) token(str(source.uuid), True, dont_generate=True).dont_generate = True
def property(self, source, target): """Create property. """ if isprofilemember(source): return if source.attributes.get('association', None) is not None: return if 'type' in source.attributes.keys(): typedef = source.refindex[source.attributes['type']] tok = token('sourcetotargetuuidmapping', False) type = target.anchor.node(tok.uuids[typedef.uuid]) else: try: name = source['type'].attributes['href'] except KeyError: raise ValueError,'Property "%s" in class "%s" has no datatype!' % \ (source.element.get('name'),source.parent.element.get('name')) name = name[name.rfind('#') + 1:] tok = token('primitivetypemapping', False) type = target.anchor.node(tok.types[name]) property = Property() assignxmiprops(property,source) property.type = type target.anchor[source.attributes['name']] = property target.finalize(source, property)
def zcaadapterdefaultinit(self, source, target): """Set default __init__ function on adapter class if not present yet. """ if source.stereotype('pyegg:function'): # XXX: <<function>> <<adapter>> on class return adapter_class = read_target_node(source, target.target) exists = False for function in adapter_class.filteredvalues(IFunction): if function.functionname == '__init__': exists = function break if not exists: tok = token(str(adapter_class.uuid), False) adapts = token(str(source.uuid), False).adapts if len(adapts) == 1: params = ['context'] else: params = [] for cl in adapts: if cl.name.startswith('I'): params.append(cl.name[1:].lower()) else: params.append(cl.name.lower()) func = Function('__init__') func.args = params block = Block() for param in params: block.lines.append('self.%s = %s' % (param, param)) func[block.uuid] = block adapter_class[func.uuid] = func
def sqlrelations_collect(self, source, target): """Finds all associations, prepares them and adds them to the corrsponding classes. """ detail = source.memberEnds[0] detailclass = detail.type master = source.memberEnds[1] masterclass = master.type if not masterclass.stereotype('sql:sql_content'): return if not detailclass.stereotype('sql:sql_content'): return mastertok = token(str(masterclass.uuid), True, outgoing_relations=[],incoming_relations=[]) detailtok = token(str(detailclass.uuid), True, outgoing_relations=[],incoming_relations=[]) if IAssociationClass.providedBy(source): detailtok.outgoing_relations.append(detail) mastertok.outgoing_relations.append(master) elif detail.aggregationkind in ['composite','aggregation','shared'] or \ IAssociationClass.providedBy(source): #for aggregations the arrow points from the master to the detail detailtok.incoming_relations.append(detail) mastertok.outgoing_relations.append(master) else: #simple FK relation, so other direction mastertok.incoming_relations.append(master)
def dxcomposition(self, source, target): # get container. ownedEnds len should always be 2 container = source.ownedEnds[0].type if container.stereotype('plone:content_type'): klass = read_target_node(container, target.target) token(str(klass.uuid), True, folderish=True) bases = [b for b in klass.bases if b != 'dexterity.Item'] if 'dexterity.Container' not in bases: klass.bases = ['dexterity.Container'] + bases
def make_generators(self, source, target): if source.stereotype('pyegg:stub'): return egg = egg_source(source) eggtarget = read_target_node(egg, target.target) zcml = get_zcml(eggtarget, 'configure.zcml', nsmap={None: 'http://namespaces.zope.org/zope', 'agx': 'http://namespaces.zope.org/agx'}) tgv = TaggedValues(source) # if transform isnt specified as tgv, get it from dependency relations to # other generators transform = tgv.direct('transform', 'generator:generator', None) if not transform: transforms = token(str(source.uuid), True, transforms=[]).transforms if len(transforms) > 1: msg = 'Currently only one transform per generator allowed (%s)' msg = msg % source.name raise ValueError(msg) elif len(transforms) == 1: transform = transforms[0].name if not transform: transform = 'uml2fs' # if depends isnt specified as tgv, get it from dependency relations to # transforms depend = tgv.direct('depends', 'generator:generator', None) if not depend: depends = token(str(source.uuid), True, depends_on=[]).depends_on if len(depends) > 1: msg = 'Currently only one depends per generator allowed (%s)' msg = msg % source.name raise ValueError(msg) elif len(depends) == 1: depend = depends[0].name if not depend: depend = 'NO' directives = zcml.filter(tag='agx:generator', attr='name') directive = None for d in directives: if d.attrs['name'] == source.name: directive = d break if not directive: directive = SimpleDirective(name='agx:generator', parent=zcml) directive.attrs['name'] = source.name directive.attrs['transform'] = transform directive.attrs['depends'] = depend set_zcml_directive(eggtarget, 'configure.zcml', 'agx:generator', 'name', source.name, overwrite=True)
def zcaadapts(self, source, target): adapter = source if adapter.stereotype('pyegg:function'): # XXX: <<function>> <<adapter>> on class return targetadapter = read_target_node(adapter, target.target) tok = token(str(adapter.uuid), True) pack = source.parent target = read_target_node(pack, target.target) targetclass = read_target_node(adapter, target) if isinstance(target, python.Module): targetdir = target.parent else: targetdir = target path = targetdir.path path.append('adapters.zcml') fullpath = os.path.join(*path) if 'adapters.zcml' not in targetdir.keys(): zcml = ZCMLFile(fullpath) targetdir['adapters.zcml'] = zcml else: zcml = targetdir['adapters.zcml'] addZcmlRef(targetdir, zcml) targettok = token(str(targetclass.uuid), True, realizes=[], provides=None) if not hasattr(tok, 'adapts'): msg = 'adapter class %s has no <<adapts>> dependency' \ % dotted_path(adapter) raise ValueError(msg) _for = [token(str(adaptee.uuid), False).fullpath for adaptee in tok.adapts] factory = class_full_name(targetadapter) tgv = TaggedValues(adapter) name = tgv.direct('name', 'zca:adapter') found_adapts = zcml.filter(tag='adapter', attr='factory', value=factory) if found_adapts: adapts = found_adapts[0] else: adapts = SimpleDirective(name='adapter', parent=zcml) adapts.attrs['for'] = _for if not name is UNSET: adapts.attrs['name'] = name adapts.attrs['factory'] = factory # write the provides which is collected in the zcarealize handler if len(targettok.realizes) == 1: provides = targettok.realizes[0] else: provides = targettok.provides if not provides: msg = 'adapter class %s has no interface realization' \ % dotted_path(adapter) raise ValueError(msg) adapts.attrs['provides'] = provides['path'] if hasattr(tok, 'permission'): adapts.attrs['permission'] = tok.permission
def console_entry_points(self, source, target): tok = token('console_scripts', True, defs={}) if tok.defs: stmt = """[console_scripts]\n""" lines = [] for key in tok.defs: lines.append(" %s=%s" % (key, tok.defs[key])) ep_tok = token('entry_points', True, defs=[]) ep_tok.defs.append(stmt + '\n'.join(lines) + '\n')
def create_site_root(self, source, target): targetclass = read_target_node(source, target.target) module = targetclass.parent if not module.functions('bootstrap'): func = Function('bootstrap') func.insertlast(Block(bootstrap_templ % source.name)) module.insertafter(func, targetclass) else: func = module.functions('bootstrap')[0] # mark the class because it has to be referenced by main token('site_root', True, site_root=source, klass=read_target_node(source, target.target), bootstrap=func)
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 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 addZcmlRef(directory, zcml): """Adds a reference to a zcml file and implicitly taks care for creating a configure.zcml""" # collect zcmls to determine whether to include configure.zcml. path = directory.path path.append(confname) # fullpath = os.path.join(*path) if confname not in directory.keys(): # conf = ZCMLFile(fullpath) conf = ZCMLFile() directory[confname] = conf else: conf = directory[confname] zcmlpath = relpath(directory,zcml) if zcmlpath != 'configure.zcml': if zcml.name == 'configure.zcml': packname = '.' + zcml.parent.name found_include = conf.filter( tag='include', attr='package', value=packname) # add include directive if necessary if not found_include: include = SimpleDirective(name='include', parent=conf) include.attrs['package'] = packname else: found_include = conf.filter(tag='include', attr='file', value=zcmlpath) # add include directive if necessary if not found_include: include = SimpleDirective(name='include', parent=conf) include.attrs['file'] = zcmlpath if directory not in token('pyeggs', False).directories: parentdir = directory.__parent__ addZcmlRef(parentdir, conf)
def purgeclasses(self, source, target): """Remove the classes that should not be generated, should run quite in the end. XXX: this one sould belong to pyegg in a final generator, but there needs to be done some work on sorting generators first """ klass = read_target_node(source, target.target) if not klass: return module = klass.parent try: tok = token(str(source.uuid), False, dont_generate=False) # no tok with flag found, so ignore except ComponentLookupError: return if tok.dont_generate: module.detach(klass.__name__) # remove the imports init = module.parent['__init__.py'] imps = init.imports() impname = [klass.classname, None] for imp in imps: if impname in imp.names: if len(imp.names) > 1: # if more names are in the imp delete the name imp.names = [n for n in imp.names if n != impname] else: # delete the whole import init.detach(imp.__name__)
def eggdirectories(self, source, target): """Create egg directory structure and corresponding ``__init__.py`` files. """ if not 'src' in target.anchor: target.anchor['src'] = Directory() package = target.anchor['src'] names = source.name.split('.') for i in range(len(names)): if not names[i] in package: package[names[i]] = Directory() package = package[names[i]] module = python.Module() package['__init__.py'] = module if i < len(names) - 1: if not module.blocks(): block = python.Block() block.text = u"__import__('pkg_resources')" + \ u".declare_namespace(__name__)" module['ns_dec'] = block else: set_copyright(source, module) # store all pyeggs in a token eggtok = token('pyeggs', True, packages=set(), directories=set()) eggtok.packages.add(source) eggtok.directories.add(package) target.finalize(source, package)
def grokforcontentclass(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 # add the schemaclass to realizes, the rest is done by the # zcagenerator::zcarealize_finalize handler impltok = token(str(klass.uuid), True, realizes=[], provides=None) impltok.realizes.insert(0, {'name': schemaclassname}) require = "grok.name('%s')" % dotted_path(source) require_exists = False for block in klass.blocks(): for line in block.lines: if line == require: require_exists = True block = python.Block() block.__name__ = str(uuid.uuid4()) if not require_exists: block.lines.append(require) if block.lines: klass.insertfirst(block)
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 generate_static_view(self, source, target): directory = read_target_node(source, target.target) tok = token('pyramid_configuration', True, static_views=[]) tgv = TaggedValues(source) path = source.name url = tgv.direct('url', 'pyramid:static_view', source.name) tok.static_views.append([url, path, '']) # if from_template is given, copy the files from the given # resource template into the target from_template = tgv.direct('from_template', 'pyramid:static_view', None) if from_template: basepath = os.path.dirname(agx.generator.pyramid.__file__) srcpath = os.path.join(basepath, 'resources', 'static_templates', from_template) tgtpath = os.path.join(*directory.fs_path) if not os.path.exists(tgtpath): os.makedirs(tgtpath) # copy over the files flist = os.listdir(srcpath) for f in flist: srcfile = os.path.join(srcpath, f) tgtfile = os.path.join(tgtpath, f) if not os.path.exists(tgtfile): if os.path.isdir(srcfile): shutil.copytree(srcfile, tgtfile) else: shutil.copy(srcfile, tgtfile)
def gscomposition(self, source, target): # get container. ownedEnds len should always be 1 container = source.ownedEnds[0].type class_ = read_target_node(container, target.target) # lookup child from memberEnds child = None for member in source.memberEnds: if member.type is not container: child = member.type break # self containment if child is None: child = container # both end types need to be content types if not container.stereotype('plone:content_type') \ or not child.stereotype('plone:content_type'): return # read fti and append allowed content type container_name = type_id(container, target.target) child_name = type_id(child, target.target) egg = egg_source(source) package = read_target_node(egg, target.target) default = package['profiles']['default'] name = '%s.xml' % container_name fti = default['types'][name] fti.params['ctype']['allowed_content_types'].append(child_name) # otherwise the class name is already set if token(str(class_.uuid), False, dont_generate=False).dont_generate: fti.params['ctype']['klass'] = 'plone.dexterity.content.Container'
def ownedend(self, source, target): """Create owned end. """ if isprofilemember(source): return oe_source = source.refindex[source.attributes['association']] tok = token('sourcetotargetuuidmapping', False) associationuuid = tok.uuids[oe_source.uuid] association = target.anchor.node(associationuuid) associationend = AssociationEnd() assignxmiprops(associationend,source) associationend.association = association # XXX: we the private uuid listing pointing to member ends. could # be simlified, read node.ext.uml.classes for details association._memberEnds.append(associationend.uuid) cla_source = source.refindex[source.attributes['type']] classuuid = tok.uuids[cla_source.uuid] associationend.type = target.anchor.node(classuuid) uppervalue = source['upperValue'].attributes['value'] if source.has_key('uppervalue') else '*' if uppervalue == '*': uppervalue = INFINITE else: uppervalue = int(uppervalue) associationend.uppervalue = uppervalue lowervalue = source['lowerValue'].attributes.get('value', '*') if source.has_key('lowervalue') else 1 if lowervalue == '*': lowervalue = INFINITE else: lowervalue = int(lowervalue) associationend.lowervalue = lowervalue association[source.attributes['name']] = associationend target.finalize(source, associationend)
def emptymoduleremoval(self, source, target): directory = read_target_node(source, target.target) try: modtok = token('pymodules', False) ignores = modtok.modules except ComponentLookupError, e: # no modules created with <<pymodule>> packages ignores = set()
def primitivetype(self, source, target): """Create datatypes out of primitivetypes. """ datatype = Datatype() name = source.attributes['name'] tok = token('primitivetypemapping', True, types={}) tok.types[name] = datatype.uuid target.anchor[name] = datatype target.finalize(source, datatype)
def inheritancetokenizer(self, source, target): """Write inheritanceorder to token. """ tgv = TaggedValues(source) order = tgv.direct('order', 'pyegg:derive', -1) if order == -1: return tok = token(source.specific.path, True, order=dict()) tok.order[source.general.name] = order
def sqlassociationclasses(self, source, target): # generate the foreign keys + relations from the assoc class to # its relation ends end0 = source.memberEnds[0] klass0 = end0.type end1 = source.memberEnds[1] klass1 = end1.type targetclass=read_target_node(source,target.target) targetklass0=read_target_node(klass0, target.target) targetklass1=read_target_node(klass1, target.target) module=targetclass.parent if not klass0.stereotype('sql:sql_content'): return if not klass1.stereotype('sql:sql_content'): return #generate the foreign key properties joins0=calculate_joins(source, targetclass, klass0, end0.name, nullable = False, force_fullname=True) joins1=calculate_joins(source, targetclass, klass1, end1.name, nullable = False, force_fullname=True) #generate the association_proxy attributes templ='''association_proxy("%s", "%s", creator=lambda c: %s(%s=c))''' for klass,targetklass_, end, otherend, joins in ((klass0,targetklass1, end0, end1, joins0), (klass1, targetklass0, end1, end0, joins1)): if end.type != otherend.type: relname=source.name.lower()+'s' else: relname=end.name+'_assocs' proxyname=end.name token(str(end.uuid),True,relname=relname,joins=joins) #XXX: if a sql_content class has 2 generalisation links to #other sql_content classes (which makes no sense for sqlalchemy) # targetklass_.attributes() leads to an #infinite loop (some odict stuff) if not targetklass_.attributes(proxyname): code=templ % (relname, get_tablename(klass), source.name, end.name) targetklass_.insertafterlastattr(Attribute(proxyname, code)) #import association_proxy imps=Imports(module) imps.set('sqlalchemy.ext.associationproxy','association_proxy')
def importedprimitivetype(self, source, target): """Create datatypes out of imported primitivetypes. """ datatype = Datatype() name = source.attributes['href'] name = name[name.rfind('#') + 1:] tok = token('primitivetypemapping', True, types={}) tok.types[name] = datatype.uuid target.anchor[name] = datatype target.finalize(source, datatype)
def setup_entry_points(self, source, target): # hooks in the entry point as a token, so that it gets generated # by pyeggs eggdocuments handler if not is_generator_egg(source): return ept = """[agx.generator] register = %s:register""" tok = token('entry_points', True, defs=[]) tok.defs.append(ept % dotted_path(source))
def pymodule(self, source, target): """Create python modules. """ module = python.Module() container = target.anchor container['%s.py' % source.name] = module set_copyright(source, module) # store all pymodules in a token modtok = token('pymodules', True, modules=set()) modtok.modules.add(module) target.finalize(source, module)
def zcaeventforcollect(self, source, target): pack = source.parent adaptee = source.supplier adapter = source.client target = read_target_node(pack, target.target) targetadaptee = read_target_node(adaptee, target) tok = token(str(adapter.uuid), True, fors=[]) adapteetok = token(str(adaptee.uuid), True, fullpath=None) if targetadaptee: adapteetok.fullpath = dotted_path(adaptee) # its a stub else: adapteetok.fullpath = '.'.join( [TaggedValues(adaptee).direct('import', 'pyegg:stub'), adaptee.name]) if isinstance(target, python.Module): targetdir = target.parent else: targetdir = target tok.fors.append(adaptee)
def stereotype(self, source, target): """Create stereotypes. """ attrname = None for key in source.attributes.keys(): if key.startswith('base_'): attrname = key if not attrname: return st_target = source.refindex[source.attributes[attrname]] tok = token('sourcetotargetuuidmapping', False) try: targetuuid = tok.uuids[st_target.uuid] except KeyError: # XXX: Heuristics: if a stereotype has accidentially been assigned to # the toplevel element, it doesnt work and should be ignored. if st_target.name.endswith('}Model'): logging.warn('Error getting the stereotype on the top-level ' 'model (propably you have assigned a stereotype ' 'there, which should not be), ignoring it ' '[agx.generator.uml.stereotypes, stereotype()]') return else: raise target = target.anchor.node(targetuuid) stereotype = Stereotype() stereotype.profile = target.root[source.ns_name] name = '%s:%s' % (source.ns_name, source.__name__[source.__name__.rfind('}') + 1:]) target[name] = stereotype for key in source.attributes.keys(): if key.startswith('base_') or active_flavour().is_profile(key): continue taggedvalue = TaggedValue() taggedvalue.value = source.attributes[key] stereotype[key] = taggedvalue multivals = {} # collect the multivalued stereotype props for child in source.values(): key = child.element.tag if not multivals.has_key(key): multivals[key] = [] multivals[key].append(child.element.text.strip()) for k, v in multivals.items(): tgv = TaggedValue() tgv.value = v stereotype[k] = tgv
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 zcviewdepcollect(self, source, target): """Collect all view dependencies """ scope = getUtility(IScope, 'uml2fs.viewclass') pack = source.parent dep = source context = source.supplier view = source.client if not scope(view): #we are only interested in views! return target = read_target_node(pack, target.target) targetcontext = read_target_node(context, target) targetview = read_target_node(view, target) tok = token(str(view.uuid), True, browserpages=[]) contexttok = token(str(context.uuid), True, fullpath=None) if targetcontext: try: dont_generate = token(str(targetcontext.uuid), False, dont_generate=False).dont_generate if dont_generate: iface = targetcontext.parent.classes( 'I' + targetcontext.classname)[0] contexttok.fullpath = class_full_name(iface) else: contexttok.fullpath = class_full_name(targetcontext) # dont_generate doesnt seem to be defined here except ComponentLookupError: pass # its a stub else: contexttok.fullpath = '.'.join([ TaggedValues(context).direct('import', 'pyegg:stub'), context.name ]) if isinstance(target, python.Module): targetdir = target.parent else: targetdir = target tok.browserpages.append(dep)
def finalize_handler(self, source, target): func = read_target_node(source, target.target) tok = token(str(source.uuid), True, scopes=[], generators=[]) tgv = TaggedValues(source) order = tgv.direct('order', 'generator:handler', None) func.args = ['self', 'source', 'target'] # ...or by dependency on a generator if tok.generators: generatornames = [g.name for g in tok.generators] else: # the generator can be defined by tgv generatornames = [tgv.direct('generator', 'generator:handler', None)] for scope in tok.scopes: stgv = TaggedValues(scope) scopename = stgv.direct('scopename', 'generator:class_scope', None) or \ stgv.direct('scopename', 'generator:simple_scope', None) or \ scope.name.lower() transform = stgv.direct('transform', 'generator:class_scope', None) or \ stgv.direct('transform', 'generator:class_scope', None) or \ 'uml2fs' transformarg = "'%s'" % transform scopenamearg = "'%s'" % scopename decfound = None for generatorname in generatornames: generatornamearg = "'%s'" % generatorname # find the dec for dec in func.decorators(): if dec.args[1] == transformarg \ and dec.args[2] == generatornamearg \ and dec.args[3] == scopenamearg: decfound = dec if decfound: dec = decfound # if not found make it else: dec = Decorator() dec.decoratorname = 'handler' dec.__name__ = dec.uuid func.insertfirst(dec) # define the args for the generator dec.args = [ "'%s'" % source.name, transformarg, generatornamearg, scopenamearg ] if not order is None: dec.kwargs['order'] = order
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 prepare_zcml(self, source, target): """Prepares zcml for generator stuff, therefore the check. """ try: tok = token(str(source.uuid), False, is_generator_egg=False) if tok.is_generator_egg: package = read_target_node(source, target.target) nsmap = { None: "http://namespaces.zope.org/zope", 'agx': "http://namespaces.zope.org/agx", } zcml = get_zcml(package, 'configure.zcml', nsmap=nsmap) set_zcml_directive(package, 'configure.zcml', 'include', 'package', 'agx.generator.pyegg') except ComponentLookupError: # if we dont have a token, do nothing pass
def schemaclass(self, source, target): schema = getschemaclass(source, target) klass = read_target_node(source, target.target) module = schema.parent view = module.classes('%sView' % klass.classname)[0] tok = token(str(view.uuid), True, depends_on=set()) tok.depends_on.add(schema) if not 'form.Schema' in schema.bases: schema.bases.append('form.Schema') egg = egg_source(source) imp = Imports(schema.parent) imp.set(egg.name, [['_', None]]) imp.set('plone.directives', [['form', None]])
def generate_profile_location(self, source, target): targetclass = read_target_node(source, target.target) module = targetclass.parent ifspec = { 'path': 'agx.core.interfaces.IProfileLocation', 'name': 'IProfileLocation', } tok = token(str(targetclass.uuid), False, realizes=[]) if ifspec not in tok.realizes: tok.realizes.append(ifspec) tgv = TaggedValues(source) name = tgv.direct('profile_name', 'generator:profile', None) if not name: name = source.name #msg = 'profile_name tagged value not defined for %s!' % source.name #raise ValueError(msg) imps = Imports(module) frompath = '.'.join(ifspec['path'].split('.')[:-1]) imps.set(frompath, [[ifspec['name'], None]]) attributenames = [att.targets[0] for att in targetclass.attributes()] if 'name' not in attributenames: att = Attribute() att.__name__ = att.uuid targetclass[att.name] = att att.targets = ['name'] att.value = "'%s.profile.uml'" % name if 'package' not in attributenames: att = Attribute() att.__name__ = att.uuid targetclass[att.name] = att att.targets = ['package'] att.value = dotted_path(source.parent) imps.set('', [[att.value, None]]) # remove the import from this class init = targetclass.parent.parent['__init__.py'] fromimp = '.'.join(implicit_dotted_path(source).split('.')[:-1]) imps = [imp for imp in init.imports() if imp.fromimport == fromimp] for imp in imps: init.detach(str(imp.uuid))
def purgecontentclasses(self, source, target): """remove the content classes that should not be generated. """ klass = read_target_node(source, target.target) module = klass.parent if token(str(klass.uuid), False, dont_generate=False).dont_generate: module.detach(klass.__name__) # remove the imports init = module.parent['__init__.py'] imps = init.imports() impname = [klass.classname, None] for imp in imps: if impname in imp.names: if len(imp.names) > 1: # if more names are in the imp delete the name imp.names = [n for n in imp.names if n != impname] else: # delete the whole import init.detach(imp.__name__)
def __call__(self): if self.model.functionname is None: raise Incomplete, u"Incomplete function definition." showNotImplemented=True ret = list() for decorator in self.model.filtereditems(IDecorator): ret.append(decorator()) name = self.model.functionname level = self.model.nodelevel args, kwargs = self.model.extract_arguments() indent = level * 4 * u' ' base_str = u'def %s(' % name rfunc = u'%s%s' % (indent, base_str) parent=self.model.__parent__ if not IClass.providedBy(parent) and u'self' in args: args = args[1:] if IClass.providedBy(parent): #add self to methods, but only if the class is not an interface try: isInterface=token(str(parent.uuid),False,isInterface=False).isInterface except ComponentLookupError: isInterface=False if not isInterface and not u'self' in args: args = [u'self'] + args else: showNotImplemented=False #interface methods are empty on purpose rargs = self.render_arguments(level, len(name) + 5, args, kwargs) rfunc = u'%s%s):\n' % (rfunc, rargs) ret.append(rfunc) values = [val for val in self.model.values() \ if not IDecorator.providedBy(val)] for child in values: child.postlf = 0 ret.append(child()) if not values: if showNotImplemented: ret.append(u'%s raise NotImplementedError, "stub generated by AGX."\n' % indent) else: ret.append(u'%s pass\n' % indent) ret += [u'\n' for i in range(self.model.postlf)] return u''.join(ret)
def typeicon(self, source, target): egg = egg_source(source) package = read_target_node(egg, target.target) resources = package['resources'] icon = '%s_icon.png' % source.name.lower() klass = read_target_node(source, target.target) folderish = token(str(klass.uuid), True, folderish=False).folderish if not icon in resources: default = package['profiles']['default'] type_name = type_id(source, target.target) name = '%s.xml' % type_name fti = default['types'][name] if folderish: path = templatepath('folder_icon.png') else: path = templatepath('document_icon.png') file = resources[icon] = File() file.mode = MODE_BINARY with open(path) as template: file.data = template.read()
def create_register_func(self, source, target): """Creates the register function. """ if not token(str(source.uuid), True, is_generator_egg=False).is_generator_egg: return init = read_target_node(source, target.target)['__init__.py'] fname = 'register' path = dotted_path(source) if fname not in [f.functionname for f in init.functions()]: f = Function() f.functionname = fname f.__name__ = str(f.uuid) bl = Block() bl.__name__ = str(bl.uuid) bl.lines.append('"""register this generator"""') bl.lines.append("import %s" % path) bl.lines.append("from agx.core.config import register_generator") bl.lines.append("register_generator(%s)" % path) f.insertfirst(bl) init[f.name] = f
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'], })
def block_simple_scopes(self, source, target): """prevent simple_scopes from being generated as class. """ if source.stereotype('generator:simple_scope'): token(str(source.uuid), True, dont_generate=True).dont_generate = True
def collect_dependencies(self, source, target): handlerscope = getUtility(IScope, 'uml2fs.handler') scopescope = getUtility(IScope, 'uml2fs.scope') generatorscope = getUtility(IScope, 'uml2fs.generator') transformscope = getUtility(IScope, 'uml2fs.transform') deps = token(str(source.uuid), True, genDeps=odict()) if handlerscope(source.client): if scopescope(source.supplier): token(str(source.client.uuid), True, scopes=[]).scopes.append(source.supplier) elif handlerscope(source.supplier): token(str(source.client.uuid), True, depends_on=[]).depends_on.append(source.supplier) elif generatorscope(source.supplier): token(str(source.client.uuid), True, generators=[]).generators.append(source.supplier) if generatorscope(source.client): if generatorscope(source.supplier): token(str(source.client.uuid), True, depends_on=[]).depends_on.append(source.supplier) elif transformscope(source.supplier): token(str(source.client.uuid), True, transforms=[]).transforms.append(source.supplier)
def mark_handler_as_function(self, source, target): token(str(source.uuid), True, is_function=True) egg = egg_source(source) tok = token(str(egg.uuid), True, is_generator_egg=True) tok.is_generator_egg = True
def plonebrowserview(self, source, target): view = source if view.stereotype('pyegg:function'): # XXX: <<function>> <<adapter>> on class return tok = token(str(view.uuid), True, browserpages=[]) pack = source.parent target = read_target_node(pack, target.target) targetclass = read_target_node(view, target) if isinstance(target, python.Module): targetdir = target.parent else: targetdir = target path = targetdir.path path.append('browser.zcml') fullpath = os.path.join(*path) if 'browser.zcml' not in targetdir: zcml = ZCMLFile(fullpath) zcml.nsmap['browser'] = 'http://namespaces.zope.org/browser' targetdir['browser.zcml'] = zcml else: zcml = targetdir['browser.zcml'] addZcmlRef(targetdir, zcml) targettok = token(str(targetclass.uuid), True, browserpages=[], provides=None) _for = [token(str(context.supplier.uuid), False).fullpath \ for context in tok.browserpages] or ['*'] classpath = class_full_name(targetclass) tgv = TaggedValues(view) # create the templates dir if 'templates' not in targetdir.keys(): targetdir['templates'] = Directory('templates') templates = targetdir['templates'] templates.factories['.pt'] = XMLTemplate #create the browser:page entries for bp in tok.browserpages or [None]: #name of view: if it should have a constant name, change the last param viewname = tgv.direct('name', 'plone:view', None) or \ tgv.direct('name', 'plone:dynamic_view', view.xminame.lower()) name_raw = tgv.direct('name', 'plone:view', None) or \ tgv.direct('name', 'plone:vdynamic_view', None) name = name_raw or view.xminame.lower() template_name_raw = tgv.direct('template_name', 'plone:view', None) or \ tgv.direct('template_name', 'plone:dynamic_view', None) template_name = template_name_raw or name + '.pt' permission = tgv.direct('permission', 'plone:view', None) or \ tgv.direct('permission', 'plone:dynamic_view', None) layer = tgv.direct('layer', 'plone:view', None) or \ tgv.direct('layer', 'plone:dynamic_view', None) if bp: bptgv = TaggedValues(bp) bptok = token(str(bp.supplier.uuid), False) _for = bptok.fullpath print 'xminame:', bp, bp.xminame # consider uuid as an unset name if bp.xminame is None or re.match( '[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}', bp.xminame): bpname = None else: bpname = bp.xminame.lower() if bp.xminame: viewname = bp.xminame viewname = bptgv.direct('name', 'plone:view', None) or \ bptgv.direct('name', 'plone:dynamic_view', viewname) name = bptgv.direct('name', 'plone:view', None) or \ bptgv.direct('name', 'plone:dynamic_view', bpname or name) # override template name template_name = bptgv.direct( 'template_name', 'plone:view', None) or \ bptgv.direct( 'template_name', 'plone:dynamic_view', None) or \ template_name_raw or name + '.pt' permission = bptgv.direct('permission', 'plone:view', None) or \ bptgv.direct('permission', 'plone:dynamic_view', permission) layer = bptgv.direct('layer', 'plone:view', None) or \ bptgv.direct('layer', 'plone:dynamic_view', layer) else: _for = '*' found_browserpages = zcml.filter(tag='browser:page', attr='name', value=viewname) browser = None templatepath = 'templates/' + template_name if found_browserpages: for br in found_browserpages: #check if it really matches if br.attrs.get('class') == classpath and \ _for == br.attrs['for']: browser = br break if not browser: browser = SimpleDirective(name='browser:page', parent=zcml) browser.attrs['for'] = _for if viewname and not viewname is UNSET: browser.attrs['name'] = viewname browser.attrs['class'] = classpath browser.attrs['template'] = templatepath browser.attrs['permission'] = permission or 'zope2.View' if layer: browser.attrs['layer'] = layer # spit out the page vanilla template if template_name not in templates.keys(): pt = XMLTemplate() templates[template_name] = pt # set template for viewtemplate pt.template = 'agx.generator.plone:templates/viewtemplate.pt'
def make_generators(self, source, target): if source.stereotype('pyegg:stub'): return egg = egg_source(source) eggtarget = read_target_node(egg, target.target) zcml = get_zcml(eggtarget, 'configure.zcml', nsmap={ None: 'http://namespaces.zope.org/zope', 'agx': 'http://namespaces.zope.org/agx' }) tgv = TaggedValues(source) # if transform isnt specified as tgv, get it from dependency relations to # other generators transform = tgv.direct('transform', 'generator:generator', None) if not transform: transforms = token(str(source.uuid), True, transforms=[]).transforms if len(transforms) > 1: msg = 'Currently only one transform per generator allowed (%s)' msg = msg % source.name raise ValueError(msg) elif len(transforms) == 1: transform = transforms[0].name if not transform: transform = 'uml2fs' # if depends isnt specified as tgv, get it from dependency relations to # transforms depend = tgv.direct('depends', 'generator:generator', None) if not depend: depends = token(str(source.uuid), True, depends_on=[]).depends_on if len(depends) > 1: msg = 'Currently only one depends per generator allowed (%s)' msg = msg % source.name raise ValueError(msg) elif len(depends) == 1: depend = depends[0].name if not depend: depend = 'NO' directives = zcml.filter(tag='agx:generator', attr='name') directive = None for d in directives: if d.attrs['name'] == source.name: directive = d break if not directive: directive = SimpleDirective(name='agx:generator', parent=zcml) directive.attrs['name'] = source.name directive.attrs['transform'] = transform directive.attrs['depends'] = depend set_zcml_directive(eggtarget, 'configure.zcml', 'agx:generator', 'name', source.name, overwrite=True)