def _get(discriminator): """Get the TypeInfo instance for discriminator, that may be any of: type_key: str (the lowercase underscore-separated of domain cls name) workflow: an instance of Workflow, provides IWorkflow interface: provides IInterface domain model: provides IBungeniContent domain model instance: type provides IBungeniContent descriptor: provides IModelDescriptor Raise KeyError if no entry matched. Usage: capi.get_type_info(discriminator) """ if discriminator is None: m = "type_info._get discriminator is None" log.error(m) raise ValueError(m) discri = removeSecurityProxy(discriminator) getter = None # !+IALCHEMISTCONTENT normalize trickier discriminator cases to type_key if IIModelInterface.providedBy(discri): discri = naming.type_key("table_schema_interface_name", discri.__name__) elif IInterface.providedBy(discri): discri = naming.type_key("model_interface_name", discri.__name__) elif type(discri) is type and issubclass(discri, domain.Entity): discri = naming.polymorphic_identity(discri) elif isinstance(discri, domain.Entity): discri = naming.polymorphic_identity(type(discri)) if isinstance(discri, basestring): getter = _get_by_type_key #elif IInterface.providedBy(discri): # getter = _get_by_interface #!+elif interfaces.IBungeniContent.implementedBy(discri): #elif issubclass(discri, domain.Entity): # getter = _get_by_model #!+elif interfaces.IBungeniContent.providedBy(discri): #elif isinstance(discri, domain.Entity): # getter = _get_by_instance elif IWorkflow.providedBy(discri): getter = _get_by_workflow elif IModelDescriptor.implementedBy(discri): getter = _get_by_descriptor_model if getter is not None: ti = getter(discri) if ti is not None: return ti else: m = "No type registered for discriminator: %r" % (discriminator) else: m = "Invalid type info lookup discriminator: %r" % (discriminator) from bungeni.utils import probing log.debug(probing.interfaces(discriminator)) log.debug(m) raise KeyError(m)
def _get(discriminator): """Get the TypeInfo instance for discriminator, that may be any of: type_key: str (the lowercase underscore-separated of domain cls name) workflow: an instance of Workflow, provides IWorkflow interface: provides IInterface domain model: provides IBungeniContent domain model instance: type provides IBungeniContent descriptor: provides IModelDescriptor Raise KeyError if no entry matched. Usage: capi.get_type_info(discriminator) """ if discriminator is None: m = "type_info._get discriminator is None" log.error(m) raise ValueError(m) discri = removeSecurityProxy(discriminator) getter = None # !+IALCHEMISTCONTENT normalize trickier discriminator cases to type_key if IIModelInterface.providedBy(discri): discri = naming.type_key("table_schema_interface_name", discri.__name__) elif IInterface.providedBy(discri): discri = naming.type_key("model_interface_name", discri.__name__) elif type(discri) is type and issubclass(discri, domain.Entity): discri = naming.polymorphic_identity(discri) elif isinstance(discri, domain.Entity): discri = naming.polymorphic_identity(type(discri)) if isinstance(discri, basestring): getter = _get_by_type_key #elif IInterface.providedBy(discri): # getter = _get_by_interface #!+elif interfaces.IBungeniContent.implementedBy(discri): #elif issubclass(discri, domain.Entity): # getter = _get_by_model #!+elif interfaces.IBungeniContent.providedBy(discri): #elif isinstance(discri, domain.Entity): # getter = _get_by_instance elif IWorkflow.providedBy(discri): getter = _get_by_workflow elif IModelDescriptor.implementedBy(discri): getter = _get_by_descriptor_model if getter is not None: ti = getter(discri) if ti is not None: return ti else: m = "No type registered for discriminator: %r" % (discriminator) else: m = "Invalid type info lookup discriminator: %r" % (discriminator) from bungeni.ui.utils import debug log.debug(debug.interfaces(discriminator)) log.debug(m) raise KeyError(m)
def serialize_cls(cls, depth=1): """(cls:ModelDescriptor) -> [str] Assumption: cls (subclass of ModelDescriptor) is localizable. """ type_key = naming.type_key("descriptor_class_name", cls.__name__) _acc = [] for f in cls.fields: _acc.extend(serialize_field(f, depth+1)) _acc.extend(serialize_integrity( cls.schema_invariants, cls.custom_validators, depth+1)) acc = [] ind = INDENT * depth acc.append(ind) if _acc: if cls.order != 999: # default "not ordered": acc.append('%s<descriptor name="%s" order="%s">' % ( ind, type_key, cls.order)) else: acc.append('%s<descriptor name="%s">' % (ind, type_key)) acc.extend(_acc) acc.append('%s</descriptor>' % (ind)) else: acc.append('%s<descriptor name="%s" />' % (ind, type_key)) return acc
def getMenuItems(self, context, request): results = [] unproxied = proxy.removeSecurityProxy(context.__parent__) try: items = unproxied.items() except AttributeError: items = [] for key, info in capi.iter_type_info(): if IScheduleContent.implementedBy(info.domain_model): name = naming.plural(key) if hasattr(unproxied, name): items.append((name, getattr(unproxied, name))) for key, item in items: if not IAlchemistContainer.providedBy(item): continue if not IScheduleContent.implementedBy(item.domain_model): continue type_info = capi.get_type_info(item.domain_model) permission = "bungeni.%s.Add" % ( type_info.workflow_key or naming.type_key("model_name", item.domain_model.__name__)) if not checkPermission(permission, context): continue dc_adapter = IDCDescriptiveProperties(item, None) if dc_adapter: _title = dc_adapter.title else: _title = getattr(item, "title", "Unknown") results.append( dict(title=_title, description=_title, action=url.absoluteURL(item, request), selected=False, icon=None, extra={}, submenu=None)) return results
def reset_zope_schema_properties_on_model_interface(descriptor_cls): type_key = naming.type_key("descriptor_class_name", descriptor_cls.__name__) ti = capi.get_type_info(type_key) domain_model = ti.domain_model sast = alchemist.sa2zs.SQLAlchemySchemaTranslator() domain_table = alchemist.utils.get_local_table(domain_model) # zope.schema field property map zsfp_map = sast.generate_fields(domain_table, descriptor_cls) # apply manually overridden field properties sast.apply_properties(zsfp_map, descriptor_cls) # stuff back onto derived_table_schema derived_table_schema = ti.derived_table_schema assert set(derived_table_schema.names(all=False)) == set(zsfp_map), \ "Incosistency in descriptor %r field lists:\n old:%s\n new:%s" % ( type_key, sorted(set(derived_table_schema.names(all=False))), sorted(set(zsfp_map))) for name in derived_table_schema.names(all=False): # !+ zsfp == descriptor_cls.fields_by_name[name].property zsfp = zsfp_map[name] # !+property.__name__ needed downstream by # zope.formlib.form.FormField __init__() does assert name !?! zsfp.__name__ = name # !+ cannot simply set the property directly on derived_table_schema: # derived_table_schema[f.name] = zsfp # as this gives: # *** TypeError: 'InterfaceClass' object does not support item assignment # So we have to workaround it !! derived_table_schema._InterfaceClass__attrs[name] = zsfp # and we need to notify (only once) that the schema has changed derived_table_schema.changed("localize_descriptors")
def permission_type_key(self): if self.custom: # custom types ALWAYS have a type_key-bound workflow instance - that # may therefore have a different name than workflow_key e.g. Office # uses the "group" workflow, that is type-relative reloaded as the # "office" workflow instance. return self.workflow.name # system types ALWAYS use workflow_key - even if multiple types use the # same workflow e.g. UserAddress & GroupAddress. # if no workflow, compute type_key from domain_model # #!+REDUNDANT(mb, 2012) This type key is already known during type # setup i.e. TYPE_REGISTRY return (self.workflow_key or naming.type_key("model_name", self.domain_model.__name__))
def permission_type_key(self): if self.custom: # custom types ALWAYS have a type_key-bound workflow instance - that # may therefore have a different name than workflow_key e.g. Office # uses the "group" workflow, that is type-relative reloaded as the # "office" workflow instance. return self.workflow.name # system types ALWAYS use workflow_key - even if multiple types use the # same workflow e.g. UserAddress & GroupAddress. # if no workflow, compute type_key from domain_model # #!+REDUNDANT(mb, 2012) This type key is already known during type # setup i.e. TYPE_REGISTRY return (self.workflow_key or naming.type_key("model_name", self.domain_model.__name__) )
def getMenuItems(self, context, request): results = [] unproxied = proxy.removeSecurityProxy(context.__parent__) items = [] for key, info in capi.iter_type_info(): if IScheduleContent.implementedBy(info.domain_model): name = naming.plural(key) traverser = component.getMultiAdapter((unproxied, request), IPublishTraverse) try: item = traverser.publishTraverse(request, name) items.append((name, item)) except NotFound: continue for key, item in items: if not IAlchemistContainer.providedBy(item): continue if not IScheduleContent.implementedBy(item.domain_model): continue type_info = capi.get_type_info(item.domain_model) permission = "bungeni.%s.Add" % ( type_info.workflow_key or naming.type_key("model_name", item.domain_model.__name__)) if not checkPermission(permission, context): continue dc_adapter = IDCDescriptiveProperties(item, None) if dc_adapter: _title = dc_adapter.title else: _title = getattr(item, "title", "Unknown") results.append( dict( title=_title, description=_title, action=url.absoluteURL(item, request), selected=False, icon=None, extra={"id": "nav_calendar_content_%s" % key}, submenu=None, )) return results
def getMenuItems(self, context, request): results = [] unproxied = proxy.removeSecurityProxy(context.__parent__) items = [] for key, info in capi.iter_type_info(): if IScheduleContent.implementedBy(info.domain_model): name = naming.plural(key) traverser = component.getMultiAdapter((unproxied, request), IPublishTraverse) try: item = traverser.publishTraverse(request, name) items.append((name, item)) except NotFound: continue for key, item in items: if not IAlchemistContainer.providedBy(item): continue if not IScheduleContent.implementedBy(item.domain_model): continue type_info = capi.get_type_info(item.domain_model) permission = "bungeni.%s.Add" % ( type_info.workflow_key or naming.type_key("model_name", item.domain_model.__name__) ) if not checkPermission(permission, context): continue dc_adapter = IDCDescriptiveProperties(item, None) if dc_adapter: _title = dc_adapter.title else: _title = getattr(item, "title", "Unknown") results.append(dict( title=_title, description=_title, action = url.absoluteURL(item, request), selected=False, icon=None, extra={"id": "nav_calendar_content_%s" % key}, submenu=None, )) return results
def getMenuItems(self, context, request): results = [] unproxied = proxy.removeSecurityProxy(context.__parent__) try: items = unproxied.items() except AttributeError: items = [] for key, info in capi.iter_type_info(): if IScheduleContent.implementedBy(info.domain_model): name = naming.plural(key) if hasattr(unproxied, name): items.append((name, getattr(unproxied, name))) for key, item in items: if not IAlchemistContainer.providedBy(item): continue if not IScheduleContent.implementedBy(item.domain_model): continue type_info = capi.get_type_info(item.domain_model) permission = "bungeni.%s.Add" % ( type_info.workflow_key or naming.type_key("model_name", item.domain_model.__name__) ) if not checkPermission(permission, context): continue dc_adapter = IDCDescriptiveProperties(item, None) if dc_adapter: _title = dc_adapter.title else: _title = getattr(item, "title", "Unknown") results.append(dict( title=_title, description=_title, action = url.absoluteURL(item, request), selected=False, icon=None, extra={}, submenu=None )) return results
def catalyse_system_descriptors(module): """Catalyze system descriptor classes (with by-name-convention associated model class) in specified module. Called when ui.descriptor is initially imported, so before descriptors for custom types have been created (that happens on first call to localization.localize_descriptors on application created event). !+CATALYSE_SYSTEM_DESCRIPTORS(mr, feb-2013) drop this, reworking it into catalysing on first time to localize each descriptor. """ import sys import inspect from bungeni.alchemist.descriptor import IModelDescriptor from bungeni.models import domain from bungeni.capi import capi from bungeni.ui.utils import debug def descriptor_classes(): """A generator of descriptor classes in this module, preserving the order of definition. """ # dir() returns names in alphabetical order decorated = [] for key in dir(module): cls = getattr(module, key) try: assert IModelDescriptor.implementedBy(cls) # we decorate with the source code line number for the cls decorated.append((inspect.getsourcelines(cls)[1], cls)) except (TypeError, AttributeError, AssertionError): debug.log_exc(sys.exc_info(), log_handler=log.debug) # we yield each cls in order of definition for cls in [ cls for (line_num, cls) in sorted(decorated) ]: yield cls def is_model_mapped(domain_model): # try get mapper to force UnmappedClassError try: orm.class_mapper(domain_model) return True except orm.exc.UnmappedClassError: # unmapped class e.g. Address, Version return False for descriptor_model in descriptor_classes(): descriptor_name = descriptor_model.__name__ type_key = naming.type_key("descriptor_class_name", descriptor_name) # Associate each descriptor to the dedicated domain type via naming # convention, and only catalysze (descriptor, model) pairs # for which the domain type is mapped. Otherwise, ignore. domain_model = getattr(domain, naming.model_name(type_key), None) if not (domain_model and is_model_mapped(domain_model)): log.warn("Not catalysing: %s", descriptor_name) continue # type_info, register descriptor_model, domain_model ti = capi.get_type_info(type_key) utils.inisetattr(ti, "domain_model", domain_model) utils.inisetattr(ti, "descriptor_model", descriptor_model) # catalyse each (domain_model, descriptor_model) pair catalyse(ti) # !+remove? m = "\n\nDone all setup of system types... running with:\n\n%s\n\n" % ( "\n\n".join(sorted( [ "%s: %s" % (key, ti) for key, ti in capi.iter_type_info() ]) )) log.debug(m)
def display_name(cls): cls_name = naming.model_name( naming.type_key("descriptor_class_name", cls.__name__)) return naming.split_camel(cls_name) # !+unicode
def catalyse_system_descriptors(module): """Catalyze system descriptor classes (with by-name-convention associated model class) in specified module. Called when ui.descriptor is initially imported, so before descriptors for custom types have been created (that happens on first call to localization.localize_descriptors on application created event). !+CATALYSE_SYSTEM_DESCRIPTORS(mr, feb-2013) drop this, reworking it into catalysing on first time to localize each descriptor. """ import sys import inspect from bungeni.alchemist.descriptor import IModelDescriptor from bungeni.capi import capi from bungeni.ui.utils import debug def descriptor_classes(): """A generator of descriptor classes in this module, preserving the order of definition. """ # dir() returns names in alphabetical order decorated = [] for key in dir(module): cls = getattr(module, key) try: assert IModelDescriptor.implementedBy(cls) # we decorate with the source code line number for the cls decorated.append((inspect.getsourcelines(cls)[1], cls)) except (TypeError, AttributeError, AssertionError): debug.log_exc(sys.exc_info(), log_handler=log.debug) # we yield each cls in order of definition for cls in [ cls for (line_num, cls) in sorted(decorated) ]: yield cls def is_model_mapped(domain_model): # try get mapper to force UnmappedClassError try: orm.class_mapper(domain_model) return True except orm.exc.UnmappedClassError: # unmapped class e.g. Version return False for descriptor_model in descriptor_classes(): descriptor_name = descriptor_model.__name__ type_key = naming.type_key("descriptor_class_name", descriptor_name) # Associate each descriptor to the dedicated domain type via naming # convention, and only catalyse (descriptor, model) pairs # for which the domain type is mapped. Otherwise, ignore. domain_model = getattr(MODEL_MODULE, naming.model_name(type_key), None) if not (domain_model and is_model_mapped(domain_model)): log.warn("Not catalysing: %s", descriptor_name) continue # type_info, register descriptor_model, domain_model ti = capi.get_type_info(type_key) utils.inisetattr(ti, "domain_model", domain_model) utils.inisetattr(ti, "descriptor_model", descriptor_model) # catalyse each (domain_model, descriptor_model) pair catalyse(ti) # !+remove? m = "\n\nDone all setup of system types... running with:\n\n%s\n\n" % ( "\n\n".join(sorted( [ "%s: %s" % (key, ti) for key, ti in capi.iter_type_info() ]) )) log.debug(m)