def calculate_joins(source, targetclass, otherclass, otherendname, nullable=False, force_fullname=False): joins = [] pks = get_pks(otherclass) my_pks=get_pks(source) if not pks: raise ValueError,'class %s has no primary key defined' % dotted_path(otherclass) try: lastattr = targetclass.attributes()[-1] except IndexError: lastattr = None for pk in pks: pkname = get_colid(pk) #import pdb;pdb.set_trace() fkname = get_fkname(source, pkname, otherendname, force_fullname=force_fullname) # this stmt will be attached to otherend in order to be used # for the join in the relationship stmt joinstmt = '%s.%s == %s.%s' % ( source.name, fkname, otherclass.name, pkname) if not targetclass.attributes(fkname): attr = Attribute() attr.__name__ = str(attr.uuid) if lastattr: targetclass.insertafter(attr, lastattr) else: targetclass.insertfirst(attr) attr.targets = [fkname] fk = "ForeignKey('%s.%s')" % ( get_tablename(otherclass), pkname) options = {} typename = pk.type.name # handle custom types (PrimitveType) if pk.type.stereotype('sql:sql_type'): tgv = TaggedValues(pk.type) typename = tgv.direct( 'classname', 'sql:sql_type', typename) import_from = tgv.direct( 'import_from', 'sql:sql_type', None) if import_from: imps = Imports(module) imps.set(import_from, [[typename, None]]) if nullable: options['nullable'] = 'True' else: options['nullable'] = 'False' if not my_pks: options['primary_key'] = 'True' oparray = [] for k in options: oparray.append('%s = %s' % (k, options[k])) attr.value = 'Column(%s, %s, %s)' % ( typename, fk, ', '.join(oparray)) joins.append(joinstmt) return joins
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 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 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 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 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 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 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 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_view_class(self, source, target): targetklass = read_target_node(source, target.target) try: module = targetklass.parent except AttributeError: # if there is no parent, this handler is not responsible return tdir = module.parent try: tok = token(str(source.uuid), False) has_view_methods = tok.has_view_methods except: has_view_methods = False view_class = source.stereotype('pyramid:view_class') # create init method if view_class or has_view_methods: inits = targetklass.functions('__init__') if inits: init = inits[0] else: init = Function('__init__') targetklass.insertfirst(init) # import pdb;pdb.set_trace() init.args = ['context', 'request'] if not init.blocks('self.request'): init.insertfirst(Block('self.request = request')) if not init.blocks('self.context'): init.insertfirst(Block('self.context = context')) # if its a view_class create the global_template if view_class: gtemplate = view_class.taggedvalue('global_template').value from_gtemplate = view_class.taggedvalue('from_global_template').value create_template_file(tdir, gtemplate, from_gtemplate) imps = Imports(module) imps.set('pyramid.renderers', 'get_renderer') if not init.blocks('global_template'): init.insertlast(Block('renderer = get_renderer("%s")' % gtemplate)) init.insertlast(Block('self.global_template = renderer.implementation()')) init.insertlast(Block('self.macros = self.global_template.macros'))
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 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 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 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 zcarealize_finalize(self, source, target): # get the collected realizes klass = source try: targetclass = read_target_node(klass, target.target) # stub if not targetclass: return targettok = token(str(targetclass.uuid), False) # class has no interfaces if not hasattr(targettok, 'realizes'): return ifacenames = [r['name'] for r in targettok.realizes] imptext = 'implements(%s)' % ','.join(ifacenames) docstrings = targetclass.filteredvalues(IDocstring) module = targetclass.__parent__ imp = Imports(module) imp.set('zope.interface', [['implements', None]]) # delete all implements stmts try: blocks = targetclass.filteredvalues(IBlock) for b in blocks: b.lines = \ [l for l in b.lines if not l.startswith('implements(')] if not b.lines: del targetclass[str(b.uuid)] # XXX: should be reparsed except KeyError, e: print 'error during delete: %s' % str(e) if klass.stereotype('pyegg:function'): return block = Block(imptext) block.__name__ = 'implements' targetclass.insertfirst(block) if docstrings: imp = targetclass.detach('implements') targetclass.insertafter(imp, docstrings[0])
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 pyramid_include(self, source, target): #creates a pyramid includeme hook if <<pyramid_include>> is applied on the root package #egg=egg_source(source) targetegg=read_target_node(source,target.target) db_attribute_name='db' tgv=source.stereotype('sql:pyramid_include').taggedvalue('db_attribute_name') if tgv: db_attribute_name=tgv.value fname='pyramid_include.py' if fname not in targetegg.keys(): templ=JinjaTemplate() templ.template=templatepath('pyramid_include.py.jinja') templ.params={ 'db_attribute_name':db_attribute_name} targetegg[fname]=templ init=targetegg['__init__.py'] imps=Imports(init) imps.set('pyramid_include','includeme')
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 generate_sqlalchemy_config(self, source, target): tgt = read_target_node(source, target.target) if IModule.providedBy(tgt): # target is a module, then its ok module = tgt target_dir = module.parent else: # fetch __init__.py module = tgt['__init__.py'] target_dir = tgt # first lets create sqla_config.py that does all the config situps fname = 'sqla_config.py' package_name = implicit_dotted_path(source) templ = JinjaTemplate() target_dir.factories[fname] = JinjaTemplate templ.template = templatepath(fname) + '.jinja' target_dir[fname] = templ target_dir[fname].params = {'engine_name':'default', 'package_name':dotted_path(source)} # now lets call config_db from the __init__.py imps = Imports(module) imps.set('sqla_config', 'config_db') main = module.functions('main')[0] term = 'config.make_wsgi_app' make_app = main.blocks(term)[0] lines = make_app.lines # find occurrence of line in block index = -1 found = False for i in range(len(lines)): if term in lines[i]: index = i if 'config_db' in lines[i]: found = True tok = token('config', True, main=main, module=module) if index != -1 and not found: lines.insert(index, 'config_db(config)')
def create_service(self, source, target): """create a module 'services.py' to hold the cornice services create a docstring at the top of the module. create an import statement (from cornice import Service). create an attribute of the name of the UML::Class and set it to a Service(with parameters) parameters are name = name of the """ klass = read_target_node(source, target.target) module = klass.parent # create imports for cornice service imps = Imports(module) imps.set('cornice', 'Service') # from cornice import Service # add the dep deps = token('setup_dependencies', True, deps=[]) if not 'cornice' in deps.deps: deps.deps.append('cornice') # prepare for later: get name of the service servicename = getservicename(source) servicepath = getservicepath(source) # create an Attribute that will define a cornice service serviceattr = Attribute() serviceattr.targets = [source.name] serviceattr.value = 'Service(name="%s", path="%s")' % (servicename, servicepath) serviceattr.__name__ = serviceattr.uuid # lets insert it after the class definition if not module.attributes(source.name): module.insertafter(serviceattr, klass) # mark importme dependencies for pyramid tok = token('pyramid_importmes', True, packages=[]) if 'cornice' not in tok.packages: tok.packages.append('cornice')
def zcainterface(self, source, target): """Create zope interface. """ if source.stereotype('pyegg:stub') is not None: return name = source.name module = target.anchor imp = Imports(module) imp.set('zope.interface', [['Interface', None]]) set_copyright(source, module) if module.classes(name): class_ = module.classes(name)[0] else: class_ = python.Class(name) module[name] = class_ # if not class_.bases: # class_.bases.append('Interface') token(str(class_.uuid), True, isInterface=True) target.finalize(source, class_)
def typeview(self, source, target): schema = getschemaclass(source, target) klass = read_target_node(source, target.target) module = schema.parent if IModule.providedBy(module): directory = module.parent else: directory = module nsmap = { None: 'http://namespaces.zope.org/zope', 'plone': 'http://namespaces.plone.org/plone', 'grok': 'http://namespaces.zope.org/grok', } zcmlfile = get_zcml(directory, 'configure.zcml', nsmap=nsmap) # include grok:grok directive if not set yet set_zcml_directive(directory, 'configure.zcml', 'grok:grok', 'package', '.') classname = '%sView' % klass.classname if module.classes(classname): view = module.classes(classname)[0] else: view = python.Class() module[uuid.uuid4()] = view view.classname = classname if not 'dexterity.DisplayForm' in view.bases: view.bases.append('dexterity.DisplayForm') context = "grok.context(%s)" % schema.classname require = "grok.require('zope2.View')" context_exists = False require_exists = False for block in view.blocks(): for line in block.lines: if line == context: context_exists = True if line == require: require_exists = True block = python.Block() block.__name__ = str(uuid.uuid4()) if not context_exists: block.lines.append(context) if not require_exists: block.lines.append(require) if block.lines: view.insertfirst(block) template = False for attr in view.attributes(): if 'template' in attr.targets: template = attr break if not template: template = python.Attribute() template.targets = ['template'] view[str(uuid.uuid4())] = template template.value = "PageTemplate('templates/%s.pt')" \ % klass.classname.lower() imp = Imports(module) imp.set('plone.directives', [['dexterity', None]]) imp.set('five', [['grok', None]]) imp.set('grokcore.view.components', [['PageTemplate', None]]) directory = module.parent template_name = '%s.pt' % klass.classname.lower() template = 'templates/%s' % template_name if not 'templates' in directory: directory['templates'] = Directory() templates = directory['templates'] templates.factories['.pt'] = XMLTemplate if template_name not in templates: pt = templates[template_name] = XMLTemplate() pt.template = 'agx.generator.dexterity:templates/displayform.pt'
def generatescopereg(self, source, target): if source.stereotype('pyegg:stub'): return targetclass = read_target_node(source, target.target) module = targetclass.parent blocks = module.blocks() tgv = TaggedValues(source) transform = tgv.direct('transform', 'generator:class_scope', None) or \ tgv.direct('transform', 'generator:simple_scope', None) or \ 'uml2fs' interfaces = tgv.direct('interfaces', 'generator:class_scope', None) or \ tgv.direct('interfaces', 'generator:simple_scope', None) scopename = tgv.direct('scopename', 'generator:class_scope', None) or \ tgv.direct('scopename', 'generator:simple_scope', None) or \ source.name.lower() #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], ]) # make the register statement if interfaces: ifstring = "[%s]" % ','.join(interfaces) else: ifstring = None if source.stereotype('generator:class_scope'): classname = source.name else: classname = 'Scope' reg = "registerScope('%s', '%s', %s, %s)" % \ (scopename, transform, ifstring, classname) # look if the reg stmt already exists regsearch = "registerScope('%s'" % scopename blockfound = None for b in blocks: for i in range(len(b.lines)): lcode = b.lines[i].strip().replace(' ', '') if lcode.startswith(regsearch): # replace the line b.lines[i] = reg return # else make a new block after the class declaration bl = Block() bl.__name__ = str(bl.uuid) bl.lines.append(reg) classes = [c for c in module.classes() if c.classname == source.name] if classes: klass = classes[0] module.insertafter(bl, klass) else: module.insertlast(bl)
def generate_configuration(self, source, target): tgt = read_target_node(source, target.target) if IModule.providedBy(tgt): # target is a module, then its ok module = tgt else: # fetch __init__.py module = tgt['__init__.py'] tok = token('pyramid_configuration', True, imports=[], static_views=[], scans=[]) imps = Imports(module) imps.set('wsgiref.simple_server', 'make_server') imps.set('pyramid.config', 'Configurator') # create a function main if not present if 'main' not in [f.functionname for f in module.functions()]: func = Function('main') func.args = ['global_config', '**settings'] module.insertafterimports(func) main = module.functions(name='main')[0] try: srtok = token('site_root', False) bootstrap = srtok.bootstrap except ComponentLookupError: bootstrap = None if not main.blocks('Configurator'): if bootstrap: import_if_necessary(module, bootstrap) main.insertfirst(Block('config = Configurator(root_factory=bootstrap)')) else: main.insertfirst(Block('config = Configurator()')) # do the configurator stuff mainblock = main.blocks('Configurator')[0] # importmes imptok = token('pyramid_importmes', True, packages=[]) for pack in imptok.packages: mainblock.insertlineafter( "config.include('%s')" % pack,'Configurator', ifnotpresent=True) # static views for sv in tok.static_views: mainblock.insertlineafter('''config.add_static_view('%s', '%s/',%s)''' % \ (sv[0], sv[1], sv[2]), 'Configurator', ifnotpresent=True) # scans for scan in tok.scans: if scan: mainblock.insertlineafter("config.scan('%s')" % scan, 'add_static_view', ifnotpresent=True) else: mainblock.insertlineafter("config.scan()" , 'add_static_view', ifnotpresent=True) # insert app stuff at end of block mainblock.appendline("app = config.make_wsgi_app()", ifnotpresent=True) mainblock.appendline("return app", ifnotpresent=True) if not module.blocks('__main__'): module.insertlast(Block('''if __name__ == '__main__': app = main() server = make_server('0.0.0.0', 8080, app) server.serve_forever()'''))
def typeview(self, source, target): schema = getschemaclass(source,target) klass = read_target_node(source, target.target) module = schema.parent if IModule.providedBy(module): directory = module.parent else: directory = module nsmap = { None: 'http://namespaces.zope.org/zope', 'plone': 'http://namespaces.plone.org/plone', 'grok': 'http://namespaces.zope.org/grok', } zcmlfile = get_zcml(directory, 'configure.zcml', nsmap=nsmap) # include grok:grok directive if not set yet set_zcml_directive(directory, 'configure.zcml', 'grok:grok', 'package', '.') classname = '%sView' % klass.classname if module.classes(classname): view = module.classes(classname)[0] else: view = python.Class() module[uuid.uuid4()] = view view.classname = classname if not 'dexterity.DisplayForm' in view.bases: view.bases.append('dexterity.DisplayForm') context = "grok.context(%s)" % schema.classname require = "grok.require('zope2.View')" context_exists = False require_exists = False for block in view.blocks(): for line in block.lines: if line == context: context_exists = True if line == require: require_exists = True block = python.Block() block.__name__ = str(uuid.uuid4()) if not context_exists: block.lines.append(context) if not require_exists: block.lines.append(require) if block.lines: view.insertfirst(block) template = False for attr in view.attributes(): if 'template' in attr.targets: template = attr break if not template: template = python.Attribute() template.targets = ['template'] view[str(uuid.uuid4())] = template template.value = "PageTemplate('templates/%s.pt')" \ % klass.classname.lower() imp = Imports(module) imp.set('plone.directives', [['dexterity', None]]) imp.set('five', [['grok', None]]) imp.set('grokcore.view.components', [['PageTemplate', None]]) directory = module.parent template_name = '%s.pt' % klass.classname.lower() template = 'templates/%s' % template_name if not 'templates' in directory: directory['templates'] = Directory() templates = directory['templates'] templates.factories['.pt'] = XMLTemplate if template_name not in templates: pt = templates[template_name] = XMLTemplate() pt.template = 'agx.generator.dexterity:templates/displayform.pt'
def generate_view_function(self, source, target): tgv = TaggedValues(source) func = read_target_node(source, target.target) if IPythonClass.providedBy(func.parent): # We have a method module = func.parent.parent klass = source.parent token(str(klass.uuid), True, has_view_methods=True) is_method = True else: module = func.parent is_method = False imps = Imports(module) funccode = "return Response('this is the stub for view %s')" % source.name # name of view route_name = tgv.direct('route_name', 'pyramid:view', source.name) if route_name == '/': route_name = '' if not func.decorators('view_config'): func.insertfirst(Decorator('view_config')) dec = func.decorators('view_config')[0] dec.kwargs['name'] = "'%s'" % route_name # necessary imports imps.set('pyramid.view', 'view_config') # the request argument if not is_method and not 'request' in func.args: func.args.append('request') # create the page template template = tgv.direct('template', 'pyramid:view', None) # template from which the template file will be generated from_template = tgv.direct('from_template', 'pyramid:view', None) if from_template and from_template != 'none' and not template: template = source.name + '.pt' print 'template name:', template, from_template if template: tdir = module.parent # set the renderer parameter based on the template name dec.kwargs['renderer'] = "'%s'" % template # create the template in target dir template_code = tgv.direct('template_code', 'pyramid:view', None) create_template_file(tdir, template, from_template, template_code=template_code and template_code.strip()) # generate default function body funccode = '''return {"page_title": "%s"}''' % source.name # if given set the renderer parameter renderer = tgv.direct('renderer', 'pyramid:view', None) if renderer and not dec.kwargs.get('renderer'): dec.kwargs['renderer'] = "'%s'" % renderer # if view function is empty, make a default code displaying info if not func.blocks(): func.insertfirst(Block(funccode)) imps.set('pyramid.response', 'Response')
def pyattribute(self, source, target): """Create Attribute. """ klass = source.parent if klass.stereotype('pyegg:stub'): return if not klass.stereotype('sql:sql_content'): return targetclass = read_target_node(klass, target.target) module = targetclass.parent read_target_node(source, target.target) typename = source.type.name options = {} if source.stereotype('sql:primary'): options['primary_key'] = 'True' colid = None # retrieve options if the primitive type has <<sql_type>> if source.type.stereotype('sql:sql_type'): tgv = TaggedValues(source.type) typename = tgv.direct('classname', 'sql:sql_type', typename) default = tgv.direct('default', 'sql:sql_type', None) if default: options['default'] = default import_from = tgv.direct('import_from', 'sql:sql_type', None) if import_from: imps = Imports(module) imps.set(import_from, [[typename, None]]) positionals = [typename] # collect params from column stereotype if source.stereotype('sql:column') or source.stereotype('sql:primary'): coltgv = TaggedValues(source) # id colid = coltgv.direct('id', 'sql:column', None) or \ coltgv.direct('id', 'sql:primary', None) if colid: positionals.insert(0, "'%s'" % colid) # index index = coltgv.direct('index', 'sql:column', None) or \ source.stereotype('sql:primary') if index: options['index'] = 'True' # default default = coltgv.direct('default', 'sql:column', None) or \ coltgv.direct('dafault', 'sql:primary', None) or \ options.get('default') if default: options['default'] = default # nullable not_null = None if coltgv.direct('not_null', 'sql:column', None) is not None: not_null = coltgv.direct('not_null', 'sql:column') if not_null is not None: options['nullable'] = { 'true': False, 'false': True, }[not_null] # server_default server_default = coltgv.direct( 'server_default', 'sql:column', None) or coltgv.direct( 'server_default', 'sql:primary', None) if server_default: options['server_default'] = server_default # sequence sequence = coltgv.direct('sequence', 'sql:column', None) or \ coltgv.direct('sequence', 'sql:primary', None) if sequence: positionals.append("Sequence('%s')" % sequence) targetatt = read_target_node(source, target.target) if options: oparray = [] for k in options: oparray.append('%s = %s' % (k, options[k])) targetatt.value = 'Column(%s,%s)' % ( ','.join(positionals), ', '.join(oparray)) else: targetatt.value = 'Column(%s)' % (','.join(positionals))
def sqlrelations_relations(self, source, target): """generate relations. """ if source.stereotype('pyegg:stub'): return if not source.stereotype('sql:sql_content'): return targetclass = read_target_node(source, target.target) module = targetclass.parent directory = module.parent # get the last attribute and append there the relations attrs = targetclass.attributes() attrnames = [att.targets[0] for att in attrs] try: lastattr = targetclass.attributes()[-1] except IndexError: lastattr = None outgoing_relations = token(str(source.uuid), True, outgoing_relations=[]).outgoing_relations imps = Imports(module) if outgoing_relations: imps.set('sqlalchemy.orm', [['relationship', None]]) for relend in outgoing_relations: assoc = relend.association if relend==relend.association.memberEnds[0]: otherend = relend.association.memberEnds[1] else: otherend = relend.association.memberEnds[0] #Association classes are handled seperately #once we support association tables, we have to handle it here tgv = TaggedValues(assoc) if IAssociationClass.providedBy(assoc): # tgv = TaggedValues(otherend) We need to build support for tgvs on # member ends later klass = relend.type otherclass = relend.association relname = token(str(otherend.uuid), True, relname=otherend.name+'_associations').relname else: klass = relend.type otherclass = otherend.type relname = otherend.name if relname not in attrnames: attr = Attribute() attr.__name__ = str(attr.uuid) if lastattr: targetclass.insertafter(attr, lastattr) else: targetclass.insertfirst(attr) attr.targets = [relname] options = {} # collect options for relationship if otherend.aggregationkind == 'composite': options['cascade'] = "'all, delete-orphan'" if assoc.stereotype('sql:ordered'): order_by = tgv.direct('order_by', 'sql:ordered', None) if not order_by: msg = 'when setting a relation ordered you have to ' +\ 'specify order_by!' raise ValueError(msg) # if not prefixed, lets prefix it if not '.' in order_by: order_by = '%s.%s' % (otherclass.name, order_by) options['order_by'] = "'%s'" % order_by if assoc.stereotype('sql:attribute_mapped'): keyname = tgv.direct('key', 'sql:attribute_mapped', None) if not keyname: msg = 'when defining attribute_mapped you have to ' + \ 'specify a key' raise ValueError(msg) if assoc.stereotype('sql:ordered'): # support for ordered mapped collection # in this case we have to provide our own collection # see http://docs.sqlalchemy.org/en/rel_0_7/orm/collections.html, # secion 'Custom Dictionary-Based Collections' fname = 'orderedcollection.py' if fname not in directory: src = JinjaTemplate() src.template = templatepath(fname + '.jinja') src.params = {} directory[fname] = src # XXX: so that emptymoduleremoval doesnt kick the # template out better would be that jinjatemplates # dont get removed at all token('pymodules', True, modules=set()).modules.add(src) options['collection_class'] = \ "ordered_attribute_mapped_collection('%s')" % keyname imps.set('orderedcollection', [['ordered_attribute_mapped_collection', None]]) # unordered else: options['collection_class'] = \ "attribute_mapped_collection('%s')" % keyname imps.set('sqlalchemy.orm.collections', [['attribute_mapped_collection', None]]) # make the primaryjoin stmt if 1 or not IAssociationClass.providedBy(relend.association): tok = token(str(relend.uuid), True, joins=[]) if tok.joins: options['primaryjoin'] = "'%s'" % ','.join(tok.joins) # XXX: .navigable isn't yet correctly parsed from uml, thus the # hardcoding if True or relend.navigable: options['backref'] = "'%s'" % relend.name.lower() if assoc.stereotype('sql:lazy'): laziness = tgv.direct('laziness', 'sql:lazy', 'dynamic') options['lazy'] = "'%s'" % laziness #convert options into keyword params oparray = [] for k in options: oparray.append('%s = %s' % (k, options[k])) attr.value = "relationship('%s', %s)" % ( otherclass.name, ', '.join(oparray))
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
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
def sqlcontentclass(self, source, target): """sqlalchemy class. """ if source.stereotype('pyegg:stub'): return targetclass = read_target_node(source, target.target) module = targetclass.parent imps = Imports(module) imps.set('sqlalchemy', [['Column', None], ['Integer', None], ['String', None], ['ForeignKey', None], ['Sequence', None]]) # find last import and do some assignments afterwards lastimport = [imp for imp in module.filtereditems(IImport)][-1] globalatts = [att for att in module.filtereditems(IAttribute)] classatts = [att for att in targetclass.filtereditems(IAttribute)] # generate the Base=declarative_base() statement saconfig=get_z3c_saconfig(source) if saconfig: # if we have a z3c_saconfig setting we import the Base from # the corresponding package imps.set(dotted_path(saconfig)+'.saconfig','Base') else: # otherwise we create it by default imps.set('sqlalchemy.ext.declarative', 'declarative_base') att = Attribute(['Base'], 'declarative_base()') att.__name__ = 'Base' if not [a for a in globalatts if a.targets == ['Base']]: module.insertafter(att, lastimport) # generate the __tablename__ attribute if not [a for a in classatts if a.targets == ['__tablename__']]: tablename = Attribute(['__tablename__'], "'%s'" % (get_tablename(source))) tablename.__name__ = '__tablename__' targetclass.insertfirst(tablename) # if a class is a base class for concrete_table_inheritance it must be # abstract if source.stereotype('sql:concrete_table_inheritance'): if not [a for a in classatts if a.targets == ['__abstract__']]: abstract = Attribute(['__abstract__'], "True") abstract.__name__ = '__abstract__' targetclass.insertfirst(abstract) # lets inherit from Base unless we dont inherit from a sql_content class has_sql_parent = False joined_parents = [] table_per_class_parents = [] for inh in Inheritance(source).values(): if inh.context.stereotype('sql:sql_content'): has_sql_parent = True if inh.context.stereotype('sql:joined_table_inheritance'): joined_parents.append(inh.context) elif inh.context.stereotype('sql:concrete_table_inheritance'): table_per_class_parents.append(inh.context) else: msg = 'when inheriting from an sql_content class (%s) ' + \ 'the parent has to have either ' + \ '<<joined_table_inheritance>> or ' + \ '<<concrete_table_inheritance>> stereotype! ' + \ 'see "http://docs.sqlalchemy.org/en/rel_0_7/' + \ 'orm/inheritance.html" for further info' msg = msg % source.name raise ValueError(msg) if targetclass.bases == ['object']: targetclass.bases = ['Base'] else: if not has_sql_parent and 'Base' not in targetclass.bases: targetclass.bases.insert(0, 'Base') # if the class has parents that are joined base classes # we need __mapper_args__ and a foreign primary key for parent in joined_parents: pks = get_pks(parent) if not pks: msg = 'class %s must have a primary key defined!' % parent.name raise ValueError(msg) pk = pks[0] pkname = get_colid(pk) pfkname = pkname typename = pk.type.name if pk.type.stereotype('sql:sql_type'): tgv = TaggedValues(pk.type) typename = tgv.direct('classname', 'sql:sql_type', typename) fk = "ForeignKey('%s.%s')" % (get_tablename(parent), pkname) pfkstmt = "Column(%s, %s,primary_key = True)" % (typename, fk) if not [a for a in classatts if a.targets == [pfkname]]: pfk = Attribute([pfkname], pfkstmt) pfk.__name__ = pfkname targetclass.insertfirst(pfk) if not [a for a in classatts if a.targets == ['__mapper_args__']]: mapper_val = "{'polymorphic_identity':'%s'}" % source.name.lower() abstract = Attribute(['__mapper_args__'], mapper_val) abstract.__name__ = '__mapper_args__' targetclass.insertfirst(abstract)