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 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 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 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 gsprofilesetuphandlers(self, source, target): """Create jsregistry.xml """ package = target.anchor default = package['profiles']['default'] egg = egg_source(source) egg_name = egg.name path = dotted_path(egg) + '.setuphandlers.install' markerfilename = '%s_marker.txt' % dotted_path(egg) #create setuphandlers.py setupname = 'setuphandlers.py' if setupname not in package.keys(): setup = JinjaTemplate() package[setupname] = setup setup.template = 'agx.generator.plone:templates/setuphandlers.py.jinja' setup.params = {'egg': path, 'markerfilename': markerfilename} #create the markerfile if not markerfilename in default.keys(): markerfile = default[markerfilename] = DTMLTemplate() markerfile.template = \ 'agx.generator.plone:templates/productname_marker.txt' # read or create import_steps.xml if 'import_steps.xml' in default: xml = default['import_steps.xml'] else: xml = default['import_steps.xml'] = DTMLTemplate() # set template used for import_steps.xml xml.template = 'agx.generator.plone:templates/import_steps.xml' # set template params xml.params = { 'eggid': path, 'handler': path, 'handlertitle': 'Installer for ' + dotted_path(egg), 'version': '1', # XXX: extend profile with import step version. 'description': '', # XXX: extend profile with import step version. }
def gsprofilesetuphandlers(self, source, target): """Create jsregistry.xml """ package = target.anchor default = package['profiles']['default'] egg = egg_source(source) egg_name = egg.name path = dotted_path(egg) + '.setuphandlers.install' markerfilename = '%s_marker.txt' % dotted_path(egg) #create setuphandlers.py setupname = 'setuphandlers.py' if setupname not in package.keys(): setup = JinjaTemplate() package[setupname] = setup setup.template = 'agx.generator.plone:templates/setuphandlers.py.jinja' setup.params = {'egg':path, 'markerfilename':markerfilename} #create the markerfile if not markerfilename in default.keys(): markerfile = default[markerfilename] = DTMLTemplate() markerfile.template = \ 'agx.generator.plone:templates/productname_marker.txt' # read or create import_steps.xml if 'import_steps.xml' in default: xml = default['import_steps.xml'] else: xml = default['import_steps.xml'] = DTMLTemplate() # set template used for import_steps.xml xml.template = 'agx.generator.plone:templates/import_steps.xml' # set template params xml.params = { 'eggid' : path, 'handler' : path, 'handlertitle' : 'Installer for ' + dotted_path(egg), 'version': '1', # XXX: extend profile with import step version. 'description':'',# XXX: extend profile with import step version. }
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 createpermission(self, source, target): targetclass = read_target_node(source, target.target) module = targetclass.parent targetdir = module.parent path = class_base_name(targetclass) # prevent python class from being generated sts = [st.name for st in source.stereotypes] # only if no other steroetypes are attached if 'zca:permission' in sts and len(sts) == 1: # class also has to be deleted from __init__ init = targetdir['__init__.py'] for imp in init.imports(): if imp.fromimport == path and imp.names[0][0] == source.name: del init[imp.__name__] del module[targetclass.__name__] # and now write the permission definition into confure.zcml zcmlpath = targetdir.path zcmlpath.append('configure.zcml') fullpath = os.path.join(*zcmlpath) if 'configure.zcml' not in targetdir.keys(): zcml = ZCMLFile(fullpath) targetdir['configure.zcml'] = zcml else: zcml = targetdir['configure.zcml'] addZcmlRef(targetdir, zcml) id = TaggedValues(source).direct('id', 'zca:permission') if id is UNSET: permid = dotted_path(source) else: permid = id found_directives = zcml.filter(tag='permission', attr='id', value=permid) if found_directives: directive = found_directives[0] else: directive = SimpleDirective(name='permission', parent=zcml) directive.attrs['id'] = permid title = TaggedValues(source).direct('title', 'zca:permission') if not title is UNSET: directive.attrs['title'] = title description = TaggedValues(source).direct('description', 'zca:permission') if not description is UNSET: directive.attrs['description'] = description
def generate_ini_files(self, source, target): print "generate_ini_files" egg = target.anchor for name in ['development.ini']: egg.factories[name] = JinjaTemplate if name not in egg.keys(): egg[name] = JinjaTemplate() egg[name].template = templatepath(name + '.jinja') egg[name].params = {'package':source.name, 'host':'0.0.0.0', 'port':'8080'} ept = """[paste.app_factory] main = %s:main""" tok = token('entry_points', True, defs=[]) tok.defs.append(ept % dotted_path(source))
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_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 pydecorator(self, source, target): """Create Decorator. """ tgv = TaggedValues(source) name = tgv.direct('name', 'pyegg:decorator', None) if not name: raise ValueError, 'decorator for %s must have a TaggedValue "name"' % \ dotted_path(source) args = tgv.direct('args', 'pyegg:decorator', None) kwargs = tgv.direct('kwargs', 'pyegg:decorator', None) container = read_target_node(source, target.target) if container.decorators(name): decorator = container.decorators(name)[0] else: decorator = python.Decorator(name) container[str(decorator.uuid)] = decorator if args is not None: decorator.s_args = args if kwargs is not None: decorator.s_kwargs = kwargs
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 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 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 sql_sample(self, source, target): if not source.stereotype('sql:z3c_saconfig'): return root=target.anchor 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') # write the readme fname = 'sample-sqlalchemy.py' if fname not in root.keys(): readme = JinjaTemplate() readme.template = templatepath(fname + '.jinja') readme.params = { 'engine_name': engine_name, 'engine_url': engine_url, 'session_name': session_name, 'packagename': dotted_path(source), } root[fname] = readme
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 collectpermissions(self, source, target): permid = dotted_path(source.supplier) id = TaggedValues(source.supplier).direct('id', 'zca:permission') if not id is UNSET: permid = id tok = token(str(source.client.uuid), True, permission=permid)
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)
def zcaeventfor(self, source, target): adapter = source tok = token(str(adapter.uuid), True) if not hasattr(tok, 'fors'): msg = 'subscriber class %s has no <<for>> dependency' \ % dotted_path(adapter) raise ValueError(msg) pack = source.parent target = read_target_node(pack, target.target) if isinstance(target, python.Module): targetdir = target.parent else: targetdir = target path = targetdir.path path.append('subscribers.zcml') fullpath = os.path.join(*path) if 'subscribers.zcml' not in targetdir.keys(): zcml = ZCMLFile(fullpath) targetdir['subscribers.zcml'] = zcml else: zcml = targetdir['subscribers.zcml'] addZcmlRef(targetdir, zcml) targetclass = read_target_node(adapter, target) targettok = token(str(targetclass.uuid), True, realizes=[], provides=None) # make sure that the event is the second entry in the for list if tok.fors[0].stereotype('zca:event'): tok.fors.reverse() _for = [token(str(adaptee.uuid), False).fullpath for adaptee in tok.fors] factory = dotted_path(adapter) tgv = TaggedValues(adapter) name = tgv.direct('name', 'zca:for') isfunc = adapter.stereotype('pyegg:function') # functions are declared handler, classes factories if isfunc: attrname = 'handler' else: attrname = 'factory' found_adapts = zcml.filter(tag='subscriber', attr=attrname, value=factory) if found_adapts: adapts = found_adapts[0] else: adapts = SimpleDirective(name='subscriber', parent=zcml) adapts.attrs['for'] = _for if not name is UNSET: adapts.attrs['name'] = name adapts.attrs[attrname] = 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 isfunc: if provides: adapts.attrs['provides'] = provides['path'] if hasattr(tok, 'permission'): adapts.attrs['permission'] = tok.permission