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 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 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 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 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 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 schemaclass_move_attribs(self, source, target): """Move the content class attribute to the schema class. """ klass = read_target_node(source, target.target) module = klass.parent schemaclassname = 'I' + klass.classname found = module.classes(schemaclassname) if found: schemaclass = found[0] else: return # transfer the attributes into the schema class for att in klass.attributes(): # move only schema attributes # we will decide this heuristically by checking if the properties stereotype is 'dexterity' # XXX: check if this is sufficient isschema = False try: prop = source[att.targets[0]] isschema = 'dexterity' in [ ss.profile.name for ss in prop.stereotypes ] except: print 'error checking for stereotype dexterity in att %s' % att.value if isschema or att.value == 'None' or att.value.startswith('schema.'): klass.detach(att.__name__) if not schemaclass.attributes(att.targets[0]): schemaclass.insertlast(att) else: del att
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 dxitem(self, source, target): schema = getschemaclass(source, target) klass = read_target_node(source, target.target) module = schema.parent bases = [b for b in klass.bases if b != 'dexterity.Container'] if 'dexterity.Item' not in bases: klass.bases = ['dexterity.Item'] + bases
def behaviorschema(self, source, target): schema = read_target_node(source, target.target) module = schema.parent # check whether this behavior has schema attributes if not 'form.Schema' in schema.bases: schema.bases.append('form.Schema') alsoprovides = "alsoProvides(%s, form.IFormFieldProvider)" \ % schema.classname alsoprovides_exists = False for block in module.blocks(): for line in block.lines: if line == alsoprovides: alsoprovides_exists = True block = python.Block() block.__name__ = str(uuid.uuid4()) if not alsoprovides_exists: block.lines.append(alsoprovides) if block.lines: module.insertafter(block, schema) egg = egg_source(source) imp = Imports(schema.parent) imp.set(egg.name, [['_', None]]) imp.set('plone.directives', [['form', None]]) imp.set('zope.interface', [['alsoProvides', None]])
def __call__(self, source): super(PackageSyncer, self).__call__(source) if (IClass.providedBy(source) or IInterface.providedBy(source)) \ and IDirectory.providedBy(self.anchor) \ and (source.parent.stereotype('pyegg:pypackage') is not None \ or source.parent.stereotype('pyegg:pyegg') is not None): modulename = '%s.py' % IModuleNameChooser(source)() self.anchor[modulename] = Module() self.anchor = self.anchor[modulename] elif (IClass.providedBy(source) or IInterface.providedBy(source)) \ and IModule.providedBy(self.anchor) \ and (source.parent.stereotype('pyegg:pypackage') is not None \ or source.parent.stereotype('pyegg:pyegg') is not None): modulename = '%s.py' % IModuleNameChooser(source)() container = self.anchor.parent container[modulename] = Module() self.anchor = container[modulename] else: if source.parent is None: return target_node = read_target_node(source.parent, self.target) if not target_node: super(PackageSyncer, self).__call__(source) return if len(target_node.path) < len(self.anchor.path): self.anchor = target_node
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 resourcedirectory(self, source, target): """Create resource directory and register in ZCML. """ egg = egg_source(source) eggname = egg.name targetdir = read_target_node(source, target.target) if 'resources' not in targetdir.keys(): targetdir['resources'] = Directory() 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) # add the resourceDirectory stmt zcautils.set_zcml_directive(targetdir, 'browser.zcml', 'include', 'package', "zope.browserresource", file="meta.zcml") if not zcml.filter( tag='browser:resourceDirectory', attr='name', value=eggname): directory = SimpleDirective( name='browser:resourceDirectory', parent=zcml) directory.attrs['name'] = eggname directory.attrs['directory'] = 'resources'
def resourceregistries(self, source, target): """Create main.css and main.js file in resources directory. Runs after browser.zcml has been created. """ egg = egg_source(source) eggname = egg.name targetdir = read_target_node(source, target.target) resources = targetdir['resources'] resources.factories['main.css'] = DTMLTemplate resources.factories['main.js'] = DTMLTemplate if not 'main.css' in resources: css = resources['main.css'] = DTMLTemplate() else: css = resources['main.css'] css.template = 'agx.generator.plone:templates/main.css.dtml' css.params['project'] = eggname css.SECTION_BEGIN = '/* code-section' css.SECTION_END = '/* /code-section' css.SECTION_POSTFIX = ' */' if not 'main.js' in resources: js = resources['main.js'] = DTMLTemplate() else: js = resources['main.js'] js.template = 'agx.generator.plone:templates/main.js.dtml' js.params['project'] = eggname js.SECTION_BEGIN = '// code-section' js.SECTION_END = '// /code-section' js.SECTION_POSTFIX = ''
def gsbehavior(self, source, target): if not source.client.stereotype('dexterity:behavior'): return package = read_target_node(egg_source(source), target.target) default = package['profiles']['default'] supplier = source.supplier full_name = type_id(supplier, target.target) name = '%s.xml' % full_name type_xml = default['types'][name] behavior_class = read_target_node(source.client, target.target) behavior = class_full_name(behavior_class) type_xml.params['ctype']['behaviors'].append(behavior)
def dxitem(self, source, target): schema = getschemaclass(source,target) klass = read_target_node(source, target.target) module = schema.parent bases = [b for b in klass.bases if b != 'dexterity.Container'] if 'dexterity.Item' not in bases: klass.bases = ['dexterity.Item'] + bases
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 resourcedirectory(self, source, target): """Create resource directory and register in ZCML. """ egg = egg_source(source) eggname = egg.name targetdir = read_target_node(source, target.target) if 'resources' not in targetdir.keys(): targetdir['resources'] = Directory() 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) # add the resourceDirectory stmt zcautils.set_zcml_directive(targetdir, 'browser.zcml', 'include', 'package', "zope.browserresource", file="meta.zcml") if not zcml.filter( tag='browser:resourceDirectory', attr='name', value=eggname): directory = SimpleDirective(name='browser:resourceDirectory', parent=zcml) directory.attrs['name'] = eggname directory.attrs['directory'] = 'resources'
def sql_config(self, source, target): """writes the sql config. """ nsmap = { None: 'http://namespaces.zope.org/zope', 'saconfig':'http://namespaces.zope.org/db', } tg = read_target_node(source, target.target) conf = zcautils.get_zcml(tg, 'configure.zcml', nsmap=nsmap) tgv = TaggedValues(source) engine_name = tgv.direct('engine_name', 'sql:z3c_saconfig', 'default') engine_url = tgv.direct( 'engine_url', 'sql:z3c_saconfig', 'sqlite:///test.db') session_name = tgv.direct('session_name', 'sql:z3c_saconfig', 'default') zcautils.set_zcml_directive( tg, 'configure.zcml', 'include', 'package', 'z3c.saconfig', file='meta.zcml') zcautils.set_zcml_directive( tg, 'configure.zcml', 'saconfig:engine', 'name', engine_name, url=engine_url) zcautils.set_zcml_directive( tg, 'configure.zcml', 'saconfig:session', 'name', session_name, engine=engine_name)
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 schemaclass_move_attribs(self, source, target): """Move the content class attribute to the schema class. """ klass = read_target_node(source, target.target) module = klass.parent schemaclassname = 'I' + klass.classname found = module.classes(schemaclassname) if found: schemaclass = found[0] else: return # transfer the attributes into the schema class for att in klass.attributes(): # move only schema attributes # we will decide this heuristically by checking if the properties stereotype is 'dexterity' # XXX: check if this is sufficient isschema=False try: prop=source[att.targets[0]] isschema = 'dexterity' in [ ss.profile.name for ss in prop.stereotypes] except: print 'error checking for stereotype dexterity in att %s' % att.value if isschema or att.value == 'None' or att.value.startswith('schema.'): klass.detach(att.__name__) if not schemaclass.attributes(att.targets[0]): schemaclass.insertlast(att) else: del att
def sqlcontentclass_engine_created_handler(self, source, target): """create and register the handler for the IEngineCreatedEvent. """ if source.stereotype('pyegg:stub'): return targetpack=read_target_node(source,target.target) targetpack['saconfig.py']=Module() module = targetpack['saconfig.py'] imps = Imports(module) # check if one of the parent packages has the z3c_saconfig stereotype z3c_saconfig=get_z3c_saconfig(source) # add engine-created handler if z3c_saconfig: eggtgv=TaggedValues(z3c_saconfig) engine_name = eggtgv.direct( 'engine_name', 'sql:z3c_saconfig', 'default') globalfuncs = [f for f in module.filtereditems(IFunction)] globalfuncnames = [f.functionname for f in globalfuncs] if 'engineCreatedHandler' not in globalfuncnames: imps.set('z3c.saconfig.interfaces', [['IEngineCreatedEvent', None]]) imps.set('zope', [['component', None]]) imps.set('z3c.saconfig.interfaces',[['IEngineFactory',None]]) imps.set('sqlalchemy.ext.declarative','declarative_base') #att = [att for att in module.filtereditems(IAttribute) \ # if att.targets == ['Base']][0] bases=module.attributes('Base') if not bases: base=Attribute('Base','declarative_base()') module.insertafterimports(base) else: base=bases[0] ff = Function('engineCreatedHandler') # 'engineCreatedHandler' ff.__name__ = ff.uuid ff.args = ('event',) dec = Decorator('component.adapter') dec.__name__ = dec.uuid dec.args = ('IEngineCreatedEvent',) ff.insertfirst(dec) block_lines = [ "fact = component.queryUtility(IEngineFactory, '%s')" \ % engine_name, "if fact and fact._args == event.engine_args:", " Base.metadata.create_all(event.engine)", ] block = Block('\n'.join(block_lines)) block.__name__ = block.uuid ff.insertlast(block) module.insertafter(ff, base) prov = Block('component.provideHandler(engineCreatedHandler)') prov.__name__ = prov.uuid module.insertafter(prov, ff)
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 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 generate_profile_location_zcml(self, source, target): if source.stereotype('pyegg:stub'): return targetclass = read_target_node(source, target.target) module = targetclass.parent blocks = module.blocks() egg = egg_source(source) eggtarget = read_target_node(egg, target.target) tgv = TaggedValues(source) #name = tgv.direct('name', 'generator:profile', None) set_zcml_directive(eggtarget, 'configure.zcml', 'utility', 'name', implicit_dotted_path(source), provides="agx.core.interfaces.IProfileLocation", component=implicit_dotted_path(source))
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 setup_i18n(self, source, target): tdir = read_target_node(source, target.target) init = tdir['__init__.py'] imps = Imports(init) imps.set('pyramid.i18n', 'TranslationStringFactory') if not init.attributes('_'): att = Attribute(['_'], "TranslationStringFactory('%s')" % source.name) att.__name__ = str(att.uuid) init.insertafterimports(att)
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 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 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 autoimport(self, source,target): """Takes classes with 'api' stereotype and imports them into the pyegg's __init__.py. """ targetob = read_target_node(source, target.target) if IModule.providedBy(targetob) or IDirectory.providedBy(targetob): init = targetob.parent['__init__.py'] else: init = targetob.parent.parent['__init__.py'] imps = Imports(init) imps.set(None, [[source.name, None]])
def transform_attribute(source, target, group, fetch_tgv): field_def = lookup_field_def(source, group) attribute = read_target_node(source, target.target) if not attribute: # attribute has been removed return attribute.value = field_def['factory'] tgv = TaggedValues(source) fetch_tgv(tgv, attribute, field_def['stereotype']) imp = Imports(attribute.parent.parent) imp.set(field_def['import_from'], [[field_def['import'], None]]) if field_def['depends']: pass # XXX write to setup.py setup_dependencies
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 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 generatescopeclass(self, source, target): """Generates scope classes. """ if source.stereotype('pyegg:stub'): return targetclass = read_target_node(source, target.target) module = targetclass.parent methods = [m for m in targetclass.functions()] methnames = [m.functionname for m in methods] methname = '__call__' tgv = TaggedValues(source) stereotypes = tgv.direct('stereotypes', 'generator:class_scope', None) or \ tgv.direct('stereotypes', 'generator:simple_scope', None) or [] transform = tgv.direct('transform', 'generator:class_scope', None) or \ tgv.direct('transform', 'generator:simple_scope', None) or \ 'uml2fs' if stereotypes: for st in stereotypes: if ':' not in st: msg = 'you have to specify the stereotype in the form ' + \ '"namespace:stereotype", but forgot the namespace ' + \ '(scope %s, stereotype %s)' % (source.name, st) raise ValueError(msg) #if not stereotypes: # msg = 'scope %s must have a stereotype attribute!!' % source.name # raise ValueError(msg) if 'Scope' not in targetclass.bases: targetclass.bases.append('Scope') if methname not in methnames: f = Function() f.functionname = methname f.args = ['self', 'node'] f.__name__ = str(f.uuid) targetclass.insertfirst(f) bl = Block() bl.__name__ = str(bl.uuid) conds = [ "node.stereotype('%s') is not None" % st for st in stereotypes ] cond = ' or '.join(conds) bl.lines.append("return %s" % cond) f.insertfirst(bl)
def standardbehavior(self, source, target): # XXX: cleanup standard behaviors, some inherit each other if source.stereotype('dexterity:behavior_standard'): behaviors = standard_behaviors.values() else: behaviors = get_standard_behaviors(source) package = read_target_node(egg_source(source), target.target) default = package['profiles']['default'] full_name = type_id(source, target.target) name = '%s.xml' % full_name type_xml = default['types'][name] for behavior in behaviors: type_xml.params['ctype']['behaviors'].append(behavior)
def plone__init__(self, source, target): egg = egg_source(source) eggname = egg.name targetdir = read_target_node(source, target.target) module = targetdir['__init__.py'] imp = Imports(module) imp.set('zope.i18nmessageid', [['MessageFactory', None]]) value = 'MessageFactory("%s")' % eggname atts = [att for att in module.attributes() if '_' in att.targets] if atts: atts[0].value = value else: module['_'] = Attribute('_', value)
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 gsdynamicview(self, source, target): """Add view method to FTI's of all dependent content types. """ if not source.supplier.stereotype('plone:content_type') \ or not source.client.stereotype('plone:dynamic_view'): return view = source.client content_type = source.supplier package = read_target_node(egg_source(content_type), target.target) default = package['profiles']['default'] full_name = type_id(content_type, target.target) name = '%s.xml' % full_name type_xml = default['types'][name] tgv = TaggedValues(view) viewname = tgv.direct('name', 'plone:dynamic_view', view.name) type_xml.params['ctype']['view_methods'].append(viewname)
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 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 generate_vanilla_profile(self, source, target): egg = egg_source(source) if not is_generator_egg(egg): return tgv = TaggedValues(source) profilename = tgv.direct('name', 'generator:profile', source.name) basepath = os.path.dirname(agx.generator.generator.__file__) profilepath = os.path.join(basepath, 'resources', 'vanilla_profile') # read the model files model_di = open(os.path.join(profilepath, 'model.profile.di')).read() model_uml = open(os.path.join(profilepath, 'model.profile.uml')).read() model_notation = open(os.path.join(profilepath, 'model.profile.notation')).read() eggdir = read_target_node(egg_source(source), target.target) # create profiles dir if 'profiles' not in eggdir.keys(): profiles = Directory() profiles.__name__ = 'profiles' eggdir['profiles'] = profiles profiles = eggdir['profiles'] # add the model files with correct name and change the references if profilename + '.profile.di' not in profiles.keys(): ff = File() ff._data = model_di.replace('model.profile.notation', profilename + '.profile.notation') profiles[profilename + '.profile.di'] = ff if profilename + '.profile.uml' not in profiles.keys(): ff = File() ff._data = model_uml.replace('profilename_changeme', profilename) profiles[profilename + '.profile.uml'] = ff if profilename + '.profile.notation' not in profiles.keys(): ff = File() ff._data = model_notation.replace('model.profile.uml', profilename + '.profile.uml') profiles[profilename + '.profile.notation'] = ff
def common_imports(self, source, target): """does common imports for modules with handlers """ handlerscope = getUtility(IScope, 'uml2fs.handler') module = read_target_node(source, target.target) has_handlers = False for klass in source.classes: if handlerscope(klass): has_handlers = True break if not has_handlers: return # do some common imports imps = Imports(module) imps.set('node.ext.uml.interfaces', [ ['IOperation', None], ['IClass', None], ['IPackage', None], ['IInterface', None], ['IInterfaceRealization', None], ['IDependency', None], ['IProperty', None], ['IAssociation', None], ]) imps.set('agx.core', [ ['handler', None], ['Scope', None], ['registerScope', None], ['token', None], ]) imps.set('agx.core.interfaces', [ ['IScope', None], ]) imps.set('agx.core.util', [ ['read_target_node', None], ['dotted_path', None], ]) imps.set('agx.generator.pyegg.utils', [ ['class_base_name', None], ['implicit_dotted_path', None], ])
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 zcviewfinalize(self, source, target): """Create zope interface. """ if source.stereotype('pyegg:stub') is not None: return view = source targetview = read_target_node(view, target.target) name = source.name module = targetview.parent imp = Imports(module) imp.set('Products.Five', [['BrowserView', None]]) set_copyright(source, module) if module.classes(name): class_ = module.classes(name)[0] else: class_ = python.Class(name) module[name] = class_ if 'BrowserView' not in targetview.bases: targetview.bases.append('BrowserView')
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 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 behavioradapter(self, source, target): schema = read_target_node(source, target.target) module = schema.parent adaptername = schema.classname[1:] if module.classes(adaptername): adapter = module.classes(adaptername)[0] else: adapter = python.Class() module[uuid.uuid4()] = adapter adapter.classname = adaptername implements = "implements(%s)" % schema.classname implements_exists = False for block in adapter.blocks(): for line in block.lines: if line == implements: implements_exists = True block = python.Block() block.__name__ = str(uuid.uuid4()) if not implements_exists: block.lines.append(implements) if block.lines: adapter.insertfirst(block) # ``__init__ only created once`` # XXX: check if signature changed and raise error if not adapter.functions('__init__'): init = python.Function(functionname='__init__') init.args.append('context') block = init[str(uuid.uuid4())] = python.Block() block.lines.append('self.context = context') adapter[str(uuid.uuid4())] = init imp = Imports(module) imp.set('zope.interface', [['implements', None]]) # read or create configure.zcml package = module.parent if 'configure.zcml' in package: configure = package['configure.zcml'] else: path = package.path path.append('configure.zcml') fullpath = os.path.join(*path) configure = ZCMLFile(fullpath) configure.nsmap['plone'] = 'http://namespaces.plone.org/plone' configure.nsmap['grok'] = 'http://namespaces.zope.org/grok' package['configure.zcml'] = configure provides = '.%s.%s' % (module.modulename, schema.classname) factory = '.%s.%s' % (module.modulename, adapter.classname) # XXX: maybe more filters if not configure.filter( tag='plone:behavior', attr='factory', value=factory): behavior = SimpleDirective(name='plone:behavior', parent=configure) behavior.attrs['title'] = adapter.classname # XXX: stereotype tgv behavior.attrs['description'] = adapter.classname behavior.attrs['provides'] = provides behavior.attrs['factory'] = factory