def __new__(cls, context, request, view, manager): chain = _get_context_chain(context) chain.pop() # bungeni_app top_section = chain.pop() if not chain: return # we require the tree to begin with a container object if not IReadContainer.providedBy(chain[-1]): return # remove any views from navigation tree if not(IAlchemistContent.providedBy(chain[0]) or IAlchemistContainer.providedBy(chain[0]) or ISection.providedBy(chain[0]) ): chain.pop(0) subcontext = chain[-1] if (len(chain) > 1 or IReadContainer.providedBy(subcontext) and not IAlchemistContainer.providedBy(subcontext) and len(subcontext) ): inst = object.__new__(cls, context, request, view, manager) inst.chain = chain inst.top_section_url = url.absoluteURL(top_section, request) inst.id_prefix = "nav" return inst
def _get_title_from_context(context): title = None if IAlchemistContent.providedBy(context): if IDCDescriptiveProperties.providedBy(context): title = context.title else: props = IDCDescriptiveProperties(context, None) if props is not None: title = props.title else: """ !+ AttributeError: 'GroupAddress' object has no attribute 'short_name': File "/home/undesa/bungeni/cap_installs/bungeni_install/bungeni/releases/20100305100101/src/bungeni.main/bungeni/ui/viewlets/navigation.py", line 59, in _get_title_from_context #title = context.short_name So, we temporarily default the above to the context.__class__.__name__: """ title = getattr(context, "title", context.__class__.__name__) elif IWorkspaceContainer.providedBy(context): # WorkspaceContainer._class is not set (and not unique) and it breaks the # connection between Container -> ContentClass title = context.__name__ elif IAlchemistContainer.providedBy(context): domain_model = context._class try: descriptor = utils.get_descriptor(domain_model) except KeyError, e: log.warn("TYPE_INFO: no descriptor for model %s " "[container=%s] [error=%s]" % (domain_model, context, e)) descriptor = None name = "" if descriptor: name = getattr(descriptor, "container_name", None) if name is None: name = getattr(descriptor, "display_name", None) if not name: name = getattr(context, "__name__", None) title = name
def __new__(cls, context, request, view, manager): chain = _get_context_chain(context) chain.pop() # bungeni_app top_section = chain.pop() if not chain: return # we require the tree to begin with a container object if not IReadContainer.providedBy(chain[-1]): return # remove any views from navigation tree if not (IAlchemistContent.providedBy(chain[0]) or IAlchemistContainer.providedBy(chain[0]) or ISection.providedBy(chain[0])): chain.pop(0) subcontext = chain[-1] if (len(chain) > 1 or IReadContainer.providedBy(subcontext) and not IAlchemistContainer.providedBy(subcontext) and len(subcontext)): inst = object.__new__(cls, context, request, view, manager) inst.chain = chain inst.top_section_url = url.absoluteURL(top_section, request) inst.id_prefix = "nav" return inst
def _get_title_from_context(context): title = None if IAlchemistContent.providedBy(context): if IDCDescriptiveProperties.providedBy(context): title = context.title else: props = IDCDescriptiveProperties(context, None) if props is not None: title = props.title else: ''' !+ AttributeError: 'GroupAddress' object has no attribute 'short_name': File "/home/undesa/bungeni/cap_installs/bungeni_install/bungeni/releases/20100305100101/src/bungeni.main/bungeni/ui/viewlets/navigation.py", line 59, in _get_title_from_context #title = context.short_name So, we temporarily default the above to the context.__class__.__name__: ''' title = getattr(context, "short_name", context.__class__.__name__) elif IAlchemistContainer.providedBy(context): domain_model = context._class try: descriptor = queryModelDescriptor(domain_model) except: descriptor = None name = "" if descriptor: name = getattr(descriptor, 'container_name', None) if name is None: name = getattr(descriptor, 'display_name', None) if not name: name = getattr(context, '__name__', None) title = name elif ILocation.providedBy(context) and \ IDCDescriptiveProperties.providedBy(context): title = context.title return title
def filterFields(context, form_fields): omit_names = [] if IAlchemistContent.providedBy(context): md = utils.get_descriptor(context.__class__) for field in form_fields: # field:zope.formlib.form.FormField try: can_write = security.canWrite(context, field.__name__) can_read = security.canAccess(context, field.__name__) except AttributeError: log.warn('filterFields: item [%s] has no field named "%s"', context, field.__name__) can_write = can_read = False if can_write: continue if can_read: field.for_display = True field.custom_widget = md.get(field.__name__).view_widget else: omit_names.append(field.__name__) elif not IAlchemistContainer.providedBy(context): ctx = getattr(context, "context", None) if ctx: filterFields(ctx, form_fields) else: raise NotImplementedError return form_fields.omit(*omit_names)
def domain_model(self): unproxied = removeSecurityProxy(self.context) if IAlchemistContainer.providedBy(unproxied): return unproxied.domain_model elif IAlchemistContent.providedBy(unproxied): return unproxied.__class__ else: raise AttributeError("Could not find domain model for context: %s", unproxied)
def form_name(self): # play nice w/ containers or content views, or content domain_model = getattr(self.context, "domain_model", None) if domain_model is None: domain_model = getattr(self, "domain_model", None) if (domain_model is None and IAlchemistContent.providedBy(self.context)): domain_model = self.context.__class__ if domain_model is None: return self.mode.title() return "%s %s" % (self.mode.title(), domain_model.__name__)
def cascade_modifications(obj): """Cascade modify events on an object to the direct parent. !+NAMING(mr, nov-2012) why cascade (implies down?!) instead of bubble (up, usually)? Plus, we are not cascading *modifications* anyway, we are just notifying of such... ! !+EVENT_CONSUMER_ISSUE(mr, nov-2012) why fire new events off the ancestor if the descendent has presumably already fired off its own modified event? If anything it should be a new specialized type of event, with a pointer to the original trigger object (descendent that was modified), so that the consumer can know it is a "derived" event and maybe act accordingly... as it is, all modified event handlers registerd will execute, e.g. auditing of the change if the ancestor is auditable, but the change had already been audited on the originator modified descendent object. """ if not ILocation.providedBy(obj): return if IAlchemistContainer.providedBy(obj.__parent__): if IAlchemistContent.providedBy(obj.__parent__.__parent__): notify(ObjectModifiedEvent(obj.__parent__.__parent__)) elif IAlchemistContent.providedBy(obj.__parent__): notify(ObjectModifiedEvent(obj.__parent__))
def __call__(self, context): if IAlchemistContent.providedBy(context): ctx = context elif IAlchemistContainer.providedBy(context): domain_model = removeSecurityProxy(context.domain_model) ctx = domain_model() workflow = interfaces.IWorkflow(ctx) items = [] for status in workflow.states.keys(): items.append(SimpleTerm(status, status, _(workflow.get_state(status).title))) return SimpleVocabulary(items)
def form_name(self): parent = self.context.__parent__ if IAlchemistContainer.providedBy(parent): descriptor = queryModelDescriptor(parent.domain_model) elif IAlchemistContent.providedBy(self.context): descriptor = queryModelDescriptor(self.context.__class__) else: raise RuntimeError("Unsupported object: %s." % repr(self.context)) if descriptor: name = getattr(descriptor, "display_name", None) if name is None: name = self.context.__class__.__name__ return name
def form_name(self): parent = self.context.__parent__ # DESCRIPTOR(miano, June 2011) This originally first checked the parent's # descriptor then the item's descriptor. Why??? # This was causing an error in the display pages of items in the # workspace since the workspace containers have no descriptor # defined for them. if IAlchemistContent.providedBy(self.context): descriptor = utils.get_descriptor(self.context.__class__) elif IAlchemistContainer.providedBy(parent): descriptor = utils.get_descriptor(parent.domain_model) else: raise RuntimeError("Unsupported object: %s." % repr(self.context)) if descriptor: name = getattr(descriptor, "display_name", None) if name is None: name = self.context.__class__.__name__ return name
def form_name(self): parent = self.context.__parent__ #DESCRIPTOR(miano, June 2011) This originally first checked the parent's #descriptor then the item's descriptor. Why??? #This was causing an error in the display pages of items in the #workspace since the workspace containers have no descriptor #defined for them. if IAlchemistContent.providedBy(self.context): descriptor = queryModelDescriptor(self.context.__class__) elif IAlchemistContainer.providedBy(parent): descriptor = queryModelDescriptor(parent.domain_model) else: raise RuntimeError("Unsupported object: %s." % repr(self.context)) if descriptor: name = getattr(descriptor, "display_name", None) if name is None: name = self.context.__class__.__name__ return name
def _get_title_from_context(context): title = None if IAlchemistContent.providedBy(context): if IDCDescriptiveProperties.providedBy(context): title = context.title else: props = IDCDescriptiveProperties(context, None) if props is not None: title = props.title else: ''' !+ AttributeError: 'GroupAddress' object has no attribute 'short_name': File "/home/undesa/bungeni/cap_installs/bungeni_install/bungeni/releases/20100305100101/src/bungeni.main/bungeni/ui/viewlets/navigation.py", line 59, in _get_title_from_context #title = context.short_name So, we temporarily default the above to the context.__class__.__name__: ''' title = getattr(context, "title", context.__class__.__name__) elif IWorkspaceContainer.providedBy(context): # WorkspaceContainer._class is not set (and not unique) and it breaks the # connection between Container -> ContentClass title = context.__name__ elif IAlchemistContainer.providedBy(context): domain_model = context._class try: descriptor = utils.get_descriptor(domain_model) except KeyError, e: log.warn("TYPE_INFO: no descriptor for model %s " "[container=%s] [error=%s]" % ( domain_model, context, e)) descriptor = None name = "" if descriptor: name = getattr(descriptor, "container_name", None) if name is None: name = getattr(descriptor, "display_name", None) if not name: name = getattr(context, "__name__", None) title = name
def filterFields(context, form_fields): omit_names = [] if IAlchemistContent.providedBy(context): md = queryModelDescriptor(context.__class__) for field in form_fields: try: can_write = security.canWrite(context, field.__name__) can_read = security.canAccess(context, field.__name__) except AttributeError: can_write = can_read = False if can_write: continue if can_read: field.for_display = True field.custom_widget = md.get(field.__name__).view_widget else: omit_names.append(field.__name__) elif not IAlchemistContainer.providedBy(context): ctx = getattr(context, "context", None) if ctx: filterFields(ctx, form_fields) else: raise NotImplementedError return form_fields.omit(*omit_names)
try: if prop_type == domain.vp.Binary: fname=PersistFiles.store_file(obj, parent, prop_name, root_key) if fname: result[prop_name] = dict(saved_file=fname) else: result[prop_name] = getattr(obj, prop_name) extended_props.append(prop_name) except zope.security.interfaces.NoInteraction: log.error("Extended property %s requires an interaction.", prop_name) # any additional attributes - this allows us to capture any derived attributes seen_keys.extend(include + exclude + extended_props) if IAlchemistContent.providedBy(obj): try: domain_schema = utils.get_derived_table_schema(type(obj)) known_names = [ k for k, d in domain_schema.namesAndDescriptions(all=True) ] extra_properties = set(known_names).difference(set(seen_keys)) seen_keys.extend(extra_properties) for prop_name in extra_properties: try: result[prop_name] = getattr(obj, prop_name) except zope.security.interfaces.NoInteraction: log.error("Attribute %s requires an interaction.", prop_name) except KeyError: log.warn("Could not find table schema for %s", obj) # any other properties defined on class
value=value, displayAs=display_name ) continue result[property.key] = value for prop_name, prop_type in obj.__class__.extended_properties: try: result[prop_name] = getattr(obj, prop_name) except zope.security.interfaces.NoInteraction: log.error("Extended property %s requires an interaction.", prop_name) # any additional attributes - this allows us to capture any derived attributes if IAlchemistContent.providedBy(obj): seen_keys = ( [ prop.key for prop in mapper.iterate_properties ] + include + exclude) try: domain_schema = utils.get_derived_table_schema(type(obj)) known_names = [ k for k, d in domain_schema.namesAndDescriptions(all=True) ] extra_properties = set(known_names).difference(set(seen_keys)) for prop_name in extra_properties: try: result[prop_name] = getattr(obj, prop_name) except zope.security.interfaces.NoInteraction: log.error("Attribute %s requires an interaction.", prop_name) except KeyError:
def obj2dict(obj, depth, parent=None, include=[], exclude=[], lang=None): """ Returns dictionary representation of a domain object. """ if lang is None: lang = getattr(obj, "language", capi.default_language) result = {} obj = removeSecurityProxy(obj) descriptor = None if IAlchemistContent.providedBy(obj): try: descriptor = utils.get_descriptor(obj) except KeyError: log.error("Could not get descriptor for IAlchemistContent %r", obj) # Get additional attributes for name in include: value = getattr(obj, name, None) if value is None: continue if not name.endswith("s"): name += "s" if isinstance(value, collections.Iterable): res = [] # !+ allowance for non-container-api-conformant alchemist containers if IAlchemistContainer.providedBy(value): value = value.values() for item in value: i = obj2dict(item, 0, lang=lang) if name == "versions": permissions = get_head_object_state_rpm(item).permissions i["permissions"] = get_permissions_dict(permissions) res.append(i) result[name] = res else: result[name] = value # Get mapped attributes mapper = class_mapper(obj.__class__) for property in mapper.iterate_properties: if property.key in exclude: continue value = getattr(obj, property.key) if value == parent: continue if value is None: continue if isinstance(property, RelationshipProperty) and depth > 0: if isinstance(value, collections.Iterable): result[property.key] = [] for item in value: result[property.key].append(obj2dict(item, 1, parent=obj, include=[], exclude=exclude + ["changes"], lang=lang )) else: result[property.key] = obj2dict(value, depth-1, parent=obj, include=[], exclude=exclude + ["changes"], lang=lang ) else: if isinstance(property, RelationshipProperty): continue elif isinstance(property, ColumnProperty): columns = property.columns if len(columns) == 1: if is_column_binary(columns[0]): continue if descriptor: columns = property.columns is_foreign = False if len(columns) == 1: if len(columns[0].foreign_keys): is_foreign = True if (not is_foreign) and (property.key in descriptor.keys()): field = descriptor.get(property.key) if (field and field.property and (field.property.__class__ == zope.schema.Choice)): factory = (field.property.vocabulary or field.property.source ) if factory is None: vocab_name = getattr(field.property, "vocabularyName", None) factory = zope.component.getUtility( zope.schema.interfaces.IVocabularyFactory, vocab_name ) #!+VOCABULARIES(mb, Aug-2012)some vocabularies # expect an interaction to generate values # todo - update these vocabularies to work # with no request e.g. in notification threads display_name = None try: vocabulary = factory(obj) term = vocabulary.getTerm(value) if lang: if hasattr(factory, "vdex"): display_name = ( factory.vdex.getTermCaption( factory.getTermById(value), lang )) else: display_name = translate( (term.title or term.value), target_language=lang, domain="bungeni" ) else: display_name = term.title or term.value except NoInteraction: log.error("This vocabulary %s expects an" "interaction to generate terms.", factory ) #try to use dc adapter lookup try: _prop = mapper.get_property_by_column( property.columns[0]) _prop_value = getattr(obj, _prop.key) dc = IDCDescriptiveProperties( _prop_value, None) if dc: display_name = ( IDCDescriptiveProperties( _prop_value).title ) except KeyError: log.warn("No display text found for %s" " on object %s. Unmapped in orm.", property.key, obj ) except Exception, e: log.error("Could not instantiate" " vocabulary %s. Exception: %s", factory, e ) finally: #fallback we cannot look up vocabularies/dc if display_name is None: log.error(value) display_name = unicode(value, errors="escape") result[property.key] = dict( name=property.key, value=value, displayAs=display_name ) continue
def expand(self, chain, include_siblings=True): if len(chain) == 0: return () context = chain.pop() items = [] if IApplication.providedBy(context): items.extend(self.expand(chain)) elif IAlchemistContent.providedBy(context): _url = url.absoluteURL(context, self.request) selected = len(chain) == 0 if chain: nodes = self.expand(chain) else: containers = utils.get_managed_containers(context) nodes = [] self.expand_containers(nodes, containers, _url, chain, None) items.append({ "id": self.get_nav_entry_id(_url), "label": IDCDescriptiveProperties(context).title, "url": _url, "current": True, "selected": selected, "kind": "content", "nodes": nodes, }) elif IAlchemistContainer.providedBy(context): # loop through all managed containers of the parent # object, and include the present container as the # "current" node. parent = context.__parent__ assert parent is not None _url = url.absoluteURL(parent, self.request) # append managed containers as child nodes if include_siblings is True: if IApplication.providedBy(parent): containers = [ (name, parent[name]) for name in location.model_to_container_name_mapping.values() if name in parent ] elif IReadContainer.providedBy(parent): containers = list(parent.items()) else: containers = utils.get_managed_containers(parent) else: containers = [(context.__name__, context)] self.expand_containers(items, containers, _url, chain, context) elif ILocation.providedBy(context): # e.g. bungeni.core.content.Section, DisplayForm _url = url.absoluteURL(context, self.request) selected = len(chain) == 0 if selected and IReadContainer.providedBy(context): nodes = [] try: self.expand_containers( nodes, context.items(), _url, chain, context) except: pass else: nodes = self.expand(chain) _title = getattr(context, "title", None) or \ getattr(context, "page_title", "!+BungeniBrowserView.title") items.append({ "id": self.get_nav_entry_id(_url), # !+BungeniBrowserView.title "label": _title, #IDCDescriptiveProperties(context).title, "url": _url, "current": True, "selected": selected, "kind": "location", "nodes": nodes, }) elif IReadContainer.providedBy(context): #!+NavigationTreeViewlet-EXPAND-IReadContainer(mr, oct-2012) does this ever execute?! raise Exception("!+NavigationTreeViewlet-EXPAND-IReadContainer [%s]" % context) items.extend(self.expand(chain)) return items
def expand(self, chain, include_siblings=True): if len(chain) == 0: return () context = chain.pop() items = [] if IApplication.providedBy(context): items.extend(self.expand(chain)) elif IAlchemistContent.providedBy(context): _url = url.absoluteURL(context, self.request) if IDCDescriptiveProperties.providedBy(context): title = context.title else: props = IDCDescriptiveProperties(context, None) if props is not None: title = props.title else: title = context.short_name selected = len(chain) == 0 if chain: nodes = self.expand(chain) else: kls = context.__class__ containers = [(key, getattr(context, key)) for key, value in kls.__dict__.items() if isinstance(value, ManagedContainerDescriptor)] nodes = [] self.expand_containers(nodes, containers, _url, chain, None) items.append({ 'title': title, 'url': _url, 'current': True, 'selected': selected, 'kind': 'content', 'nodes': nodes, }) elif IAlchemistContainer.providedBy(context): # loop through all managed containers of the parent # object, and include the present container as the # 'current' node. parent = context.__parent__ assert parent is not None _url = url.absoluteURL(parent, self.request) # append managed containers as child nodes kls = type(proxy.removeSecurityProxy(parent)) if include_siblings is True: if IApplication.providedBy(parent): containers = [ (name, parent[name]) for name in location.model_to_container_name_mapping.values() if name in parent ] elif IReadContainer.providedBy(parent): containers = list(parent.items()) else: containers = [ (key, getattr(parent, key)) for key, value in kls.__dict__.items() if isinstance(value, ManagedContainerDescriptor) ] else: containers = [(context.__name__, context)] self.expand_containers(items, containers, _url, chain, context) elif ILocation.providedBy(context): _url = url.absoluteURL(context, self.request) #props = IDCDescriptiveProperties.providedBy(context) and \ # context or IDCDescriptiveProperties(context) if IDCDescriptiveProperties.providedBy(context): props = IDCDescriptiveProperties(context) else: props = context props = proxy.removeSecurityProxy(props) selected = len(chain) == 0 if selected and IReadContainer.providedBy(context): nodes = [] try: self.expand_containers(nodes, context.items(), _url, chain, context) except: pass else: nodes = self.expand(chain) i_id = getattr(props, 'id', 'N/A') items.append({ 'title': getattr(props, 'title', i_id), 'url': _url, 'current': True, 'selected': selected, 'kind': 'location', 'nodes': nodes, }) elif IReadContainer.providedBy(context): items.extend(self.expand(chain)) return items
def obj2dict(obj, depth, parent=None, include=[], exclude=[], lang=None, root_key=None): """ Returns dictionary representation of a domain object. """ if lang is None: lang = getattr(obj, "language", capi.default_language) result = {} obj = zope.security.proxy.removeSecurityProxy(obj) descriptor = None if IAlchemistContent.providedBy(obj): try: descriptor = utils.get_descriptor(obj) except KeyError: log.error("Could not get descriptor for IAlchemistContent %r", obj) if parent is not None and IWorkflowed.providedBy(obj): permissions = get_object_state_rpm(obj).permissions result["permissions"] = get_permissions_dict(permissions) result["tags"] = IStateController(obj).get_state().tags # Get additional attributes for name in include: value = getattr(obj, name, None) if value is None: continue if not name.endswith("s"): name += "s" if isinstance(value, collections.Iterable): res = [] # !+ allowance for non-container-api-conformant alchemist containers if IAlchemistContainer.providedBy(value): value = value.values() for item in value: i = obj2dict(item, 0, lang=lang, root_key=root_key) res.append(i) result[name] = res else: result[name] = value # Get mapped attributes mapper = class_mapper(obj.__class__) for property in mapper.iterate_properties: if property.key in exclude: continue value = getattr(obj, property.key) if value == parent: continue if value is None: continue if isinstance(property, RelationshipProperty) and depth > 0: if isinstance(value, collections.Iterable): result[property.key] = [] for item in value: result[property.key].append( obj2dict(item, 1, parent=obj, include=[], exclude=exclude + INNER_EXCLUDES, lang=lang, root_key=root_key)) else: result[property.key] = obj2dict(value, depth - 1, parent=obj, include=[], exclude=exclude + INNER_EXCLUDES, lang=lang, root_key=root_key) else: if isinstance(property, RelationshipProperty): continue elif isinstance(property, ColumnProperty): columns = property.columns if len(columns) == 1: if is_column_binary(columns[0]): if (parent and interfaces.ISerializable.providedBy(obj)): #skip serialization of binary fields #that have already been serialized elsewhere continue #save files result[columns[0].key] = dict( saved_file=PersistFiles.store_file( obj, columns[0], root_key)) continue if descriptor: columns = property.columns is_foreign = False if len(columns) == 1: if len(columns[0].foreign_keys): is_foreign = True if (not is_foreign) and (property.key in descriptor.keys()): field = descriptor.get(property.key) if (field and field.property and (schema.interfaces.IChoice.providedBy(field.property) or IVocabularyTextField.providedBy(field.property))): factory = (field.property.vocabulary or field.property.source) if factory is None: vocab_name = getattr(field.property, "vocabularyName", None) factory = zope.component.getUtility( schema.interfaces.IVocabularyFactory, vocab_name) # !+VOCABULARIES(mb, aug-2012)some vocabularies # expect an interaction to generate values # todo - update these vocabularies to work # with no request e.g. in notification threads display_name = None try: vocabulary = factory(obj) #handle vdex hierarchical terms if ITreeVocabulary.providedBy(factory): values = value.splitlines() term_values = [] for val in values: term_values.append( dict(name=property.key, value=val, displayAs=factory.vdex. getTermCaption( factory.getTermById(val), lang))) result[property.key] = term_values continue term = vocabulary.getTerm(value) if lang: if hasattr(factory, "vdex"): display_name = ( factory.vdex.getTermCaption( factory.getTermById(value), lang)) else: display_name = translate( (term.title or term.value), target_language=lang, domain="bungeni") else: display_name = term.title or term.value except zope.security.interfaces.NoInteraction: log.error( "This vocabulary %s expects an" "interaction to generate terms.", factory) # try to use dc adapter lookup try: _prop = mapper.get_property_by_column( property.columns[0]) _prop_value = getattr(obj, _prop.key) dc = IDCDescriptiveProperties( _prop_value, None) if dc: display_name = (IDCDescriptiveProperties( _prop_value).title) except KeyError: log.warn( "No display text found for %s" " on object %s. Unmapped in orm.", property.key, obj) except Exception, e: log.error( "Could not instantiate" " vocabulary %s. Exception: %s", factory, e) finally: # fallback we cannot look up vocabularies/dc if display_name is None: if not isinstance(value, unicode): display_name = unicode(value) if display_name is not None: result[property.key] = dict(name=property.key, value=value, displayAs=display_name) continue
def expand(self, chain, include_siblings=True): if len(chain) == 0: return () context = chain.pop() items = [] if IApplication.providedBy(context): items.extend(self.expand(chain)) elif IAlchemistContent.providedBy(context): _url = url.absoluteURL(context, self.request) selected = len(chain) == 0 if chain: nodes = self.expand(chain) else: containers = utils.get_managed_containers(context) nodes = [] self.expand_containers(nodes, containers, _url, chain, None) items.append({ "id": self.get_nav_entry_id(_url), "label": IDCDescriptiveProperties(context).title, "url": _url, "current": True, "selected": selected, "kind": "content", "nodes": nodes, }) elif IAlchemistContainer.providedBy(context): # loop through all managed containers of the parent # object, and include the present container as the # "current" node. parent = context.__parent__ assert parent is not None _url = url.absoluteURL(parent, self.request) # append managed containers as child nodes if include_siblings is True: if IApplication.providedBy(parent): containers = [ (name, parent[name]) for name in location.model_to_container_name_mapping.values() if name in parent ] elif IReadContainer.providedBy(parent): containers = list(parent.items()) else: containers = utils.get_managed_containers(parent) else: containers = [(context.__name__, context)] self.expand_containers(items, containers, _url, chain, context) elif ILocation.providedBy(context): # e.g. bungeni.core.content.Section, DisplayForm _url = url.absoluteURL(context, self.request) selected = len(chain) == 0 if selected and IReadContainer.providedBy(context): nodes = [] try: self.expand_containers(nodes, context.items(), _url, chain, context) except: pass else: nodes = self.expand(chain) _title = getattr(context, "title", None) or \ getattr(context, "page_title", "!+BungeniBrowserView.title") items.append({ "id": self.get_nav_entry_id(_url), # !+BungeniBrowserView.title "label": _title, #IDCDescriptiveProperties(context).title, "url": _url, "current": True, "selected": selected, "kind": "location", "nodes": nodes, }) elif IReadContainer.providedBy(context): #!+NavigationTreeViewlet-EXPAND-IReadContainer(mr, oct-2012) does this ever execute?! raise Exception( "!+NavigationTreeViewlet-EXPAND-IReadContainer [%s]" % context) items.extend(self.expand(chain)) return items
def expand(self, chain, include_siblings=True): if len(chain) == 0: return () context = chain.pop() items = [] if IApplication.providedBy(context): items.extend(self.expand(chain)) elif IAlchemistContent.providedBy(context): _url = url.absoluteURL(context, self.request) if IDCDescriptiveProperties.providedBy(context): title = context.title else: props = IDCDescriptiveProperties(context, None) if props is not None: title = props.title else: title = context.short_name selected = len(chain) == 0 if chain: nodes = self.expand(chain) else: kls = context.__class__ containers = [ (key, getattr(context, key)) for key, value in kls.__dict__.items() if isinstance(value, ManagedContainerDescriptor)] nodes = [] self.expand_containers(nodes, containers, _url, chain, None) items.append( {'title': title, 'url': _url, 'current': True, 'selected': selected, 'kind': 'content', 'nodes': nodes, }) elif IAlchemistContainer.providedBy(context): # loop through all managed containers of the parent # object, and include the present container as the # 'current' node. parent = context.__parent__ assert parent is not None _url = url.absoluteURL(parent, self.request) # append managed containers as child nodes kls = type(proxy.removeSecurityProxy(parent)) if include_siblings is True: if IApplication.providedBy(parent): containers = [ (name, parent[name]) for name in location.model_to_container_name_mapping.values() if name in parent ] elif IReadContainer.providedBy(parent): containers = list(parent.items()) else: containers = [ (key, getattr(parent, key)) for key, value in kls.__dict__.items() if isinstance(value, ManagedContainerDescriptor)] else: containers = [(context.__name__, context)] self.expand_containers(items, containers, _url, chain, context) elif ILocation.providedBy(context): _url = url.absoluteURL(context, self.request) #props = IDCDescriptiveProperties.providedBy(context) and \ # context or IDCDescriptiveProperties(context) if IDCDescriptiveProperties.providedBy(context): props = IDCDescriptiveProperties(context) else: props = context props = proxy.removeSecurityProxy(props) selected = len(chain) == 0 if selected and IReadContainer.providedBy(context): nodes = [] try: self.expand_containers( nodes, context.items(), _url, chain, context) except: pass else: nodes = self.expand(chain) i_id = getattr(props, 'id','N/A') items.append( {'title': getattr(props, 'title', i_id), 'url': _url, 'current': True, 'selected': selected, 'kind': 'location', 'nodes': nodes, }) elif IReadContainer.providedBy(context): items.extend(self.expand(chain)) return items
def obj2dict(obj, depth, parent=None, include=[], exclude=[], lang=None, root_key=None): """ Returns dictionary representation of a domain object. """ if lang is None: lang = getattr(obj, "language", capi.default_language) result = {} obj = zope.security.proxy.removeSecurityProxy(obj) descriptor = None if IAlchemistContent.providedBy(obj): try: descriptor = utils.get_descriptor(obj) except KeyError: log.error("Could not get descriptor for IAlchemistContent %r", obj) if parent is not None and IWorkflowed.providedBy(obj): permissions = get_object_state_rpm(obj).permissions result["permissions"] = get_permissions_dict(permissions) result["tags"] = IStateController(obj).get_state().tags # Get additional attributes for name in include: value = getattr(obj, name, None) if value is None: continue if not name.endswith("s"): name += "s" if isinstance(value, collections.Iterable): res = [] # !+ allowance for non-container-api-conformant alchemist containers if IAlchemistContainer.providedBy(value): value = value.values() for item in value: i = obj2dict(item, 0, lang=lang, root_key=root_key) res.append(i) result[name] = res else: result[name] = value # Get mapped attributes mapper = class_mapper(obj.__class__) for property in mapper.iterate_properties: if property.key in exclude: continue value = getattr(obj, property.key) if value == parent: continue if value is None: continue if isinstance(property, RelationshipProperty) and depth > 0: if isinstance(value, collections.Iterable): result[property.key] = [] for item in value: result[property.key].append(obj2dict(item, 1, parent=obj, include=[], exclude=exclude + INNER_EXCLUDES, lang=lang, root_key=root_key )) else: result[property.key] = obj2dict(value, depth-1, parent=obj, include=[], exclude=exclude + INNER_EXCLUDES, lang=lang, root_key=root_key ) else: if isinstance(property, RelationshipProperty): continue elif isinstance(property, ColumnProperty): columns = property.columns if len(columns) == 1: if is_column_binary(columns[0]): if (parent and interfaces.ISerializable.providedBy(obj)): #skip serialization of binary fields #that have already been serialized elsewhere continue #save files result[columns[0].key] = dict( saved_file=PersistFiles.store_file( obj, columns[0], root_key ) ) continue if descriptor: columns = property.columns is_foreign = False if len(columns) == 1: if len(columns[0].foreign_keys): is_foreign = True if (not is_foreign) and (property.key in descriptor.keys()): field = descriptor.get(property.key) if (field and field.property and (schema.interfaces.IChoice.providedBy(field.property) or IVocabularyTextField.providedBy(field.property)) ): factory = (field.property.vocabulary or field.property.source ) if factory is None: vocab_name = getattr(field.property, "vocabularyName", None) factory = zope.component.getUtility( schema.interfaces.IVocabularyFactory, vocab_name ) # !+VOCABULARIES(mb, aug-2012)some vocabularies # expect an interaction to generate values # todo - update these vocabularies to work # with no request e.g. in notification threads display_name = None try: vocabulary = factory(obj) #handle vdex hierarchical terms if ITreeVocabulary.providedBy(factory): values = value.splitlines() term_values = [] for val in values: term_values.append(dict( name=property.key, value=val, displayAs=factory.vdex.getTermCaption( factory.getTermById(val), lang ) )) result[property.key] = term_values continue term = vocabulary.getTerm(value) if lang: if hasattr(factory, "vdex"): display_name = ( factory.vdex.getTermCaption( factory.getTermById(value), lang )) else: display_name = translate( (term.title or term.value), target_language=lang, domain="bungeni" ) else: display_name = term.title or term.value except zope.security.interfaces.NoInteraction: log.error("This vocabulary %s expects an" "interaction to generate terms.", factory ) # try to use dc adapter lookup try: _prop = mapper.get_property_by_column( property.columns[0]) _prop_value = getattr(obj, _prop.key) dc = IDCDescriptiveProperties( _prop_value, None) if dc: display_name = ( IDCDescriptiveProperties( _prop_value).title ) except KeyError: log.warn("No display text found for %s" " on object %s. Unmapped in orm.", property.key, obj ) except Exception, e: log.error("Could not instantiate" " vocabulary %s. Exception: %s", factory, e ) finally: # fallback we cannot look up vocabularies/dc if display_name is None: if not isinstance(value, unicode): display_name = unicode(value) if display_name is not None: result[property.key] = dict( name=property.key, value=value, displayAs=display_name ) continue
def obj2dict(obj, depth, parent=None, include=[], exclude=[], lang=None): """ Returns dictionary representation of a domain object. """ if lang is None: lang = getattr(obj, "language", capi.default_language) result = {} obj = removeSecurityProxy(obj) descriptor = None if IAlchemistContent.providedBy(obj): try: descriptor = utils.get_descriptor(obj) except KeyError: log.error("Could not get descriptor for IAlchemistContent %r", obj) # Get additional attributes for name in include: value = getattr(obj, name, None) if value is None: continue if not name.endswith("s"): name += "s" if isinstance(value, collections.Iterable): res = [] # !+ allowance for non-container-api-conformant alchemist containers if IAlchemistContainer.providedBy(value): value = value.values() for item in value: i = obj2dict(item, 0, lang=lang) if name == "versions": permissions = get_head_object_state_rpm(item).permissions i["permissions"] = get_permissions_dict(permissions) res.append(i) result[name] = res else: result[name] = value # Get mapped attributes mapper = class_mapper(obj.__class__) for property in mapper.iterate_properties: if property.key in exclude: continue value = getattr(obj, property.key) if value == parent: continue if value is None: continue if isinstance(property, RelationshipProperty) and depth > 0: if isinstance(value, collections.Iterable): result[property.key] = [] for item in value: result[property.key].append( obj2dict(item, 1, parent=obj, include=[], exclude=exclude + ["changes"], lang=lang)) else: result[property.key] = obj2dict(value, depth - 1, parent=obj, include=[], exclude=exclude + ["changes"], lang=lang) else: if isinstance(property, RelationshipProperty): continue elif isinstance(property, ColumnProperty): columns = property.columns if len(columns) == 1: if is_column_binary(columns[0]): continue if descriptor: columns = property.columns is_foreign = False if len(columns) == 1: if len(columns[0].foreign_keys): is_foreign = True if (not is_foreign) and (property.key in descriptor.keys()): field = descriptor.get(property.key) if (field and field.property and (field.property.__class__ == zope.schema.Choice)): factory = (field.property.vocabulary or field.property.source) if factory is None: vocab_name = getattr(field.property, "vocabularyName", None) factory = zope.component.getUtility( zope.schema.interfaces.IVocabularyFactory, vocab_name) #!+VOCABULARIES(mb, Aug-2012)some vocabularies # expect an interaction to generate values # todo - update these vocabularies to work # with no request e.g. in notification threads display_name = None try: vocabulary = factory(obj) term = vocabulary.getTerm(value) if lang: if hasattr(factory, "vdex"): display_name = ( factory.vdex.getTermCaption( factory.getTermById(value), lang)) else: display_name = translate( (term.title or term.value), target_language=lang, domain="bungeni") else: display_name = term.title or term.value except NoInteraction: log.error( "This vocabulary %s expects an" "interaction to generate terms.", factory) #try to use dc adapter lookup try: _prop = mapper.get_property_by_column( property.columns[0]) _prop_value = getattr(obj, _prop.key) dc = IDCDescriptiveProperties( _prop_value, None) if dc: display_name = (IDCDescriptiveProperties( _prop_value).title) except KeyError: log.warn( "No display text found for %s" " on object %s. Unmapped in orm.", property.key, obj) except Exception, e: log.error( "Could not instantiate" " vocabulary %s. Exception: %s", factory, e) finally: #fallback we cannot look up vocabularies/dc if display_name is None: log.error(value) display_name = unicode(value, errors="escape") result[property.key] = dict(name=property.key, value=value, displayAs=display_name) continue
def obj2dict(obj, depth, parent=None, include=[], exclude=[], lang=None, root_key=None): """ Returns dictionary representation of a domain object. """ if lang is None: lang = getattr(obj, "language", capi.default_language) result = {} obj = zope.security.proxy.removeSecurityProxy(obj) descriptor = None if IAlchemistContent.providedBy(obj): try: descriptor = utils.get_descriptor(obj) except KeyError: log.error("Could not get descriptor for IAlchemistContent %r", obj) if parent is not None and IWorkflowed.providedBy(obj): permissions = get_object_state_rpm(obj).permissions result["permissions"] = get_permissions_dict(permissions) result["tags"] = IStateController(obj).get_state().tags # Get additional attributes for name in include: value = getattr(obj, name, None) if value is None: continue if not name.endswith("s"): name += "s" if isinstance(value, collections.Iterable): res = [] # !+ allowance for non-container-api-conformant alchemist containers if IAlchemistContainer.providedBy(value): value = value.values() for item in value: i = obj2dict(item, 0, lang=lang, root_key=root_key) res.append(i) result[name] = res else: result[name] = value # Get mapped attributes seen_keys = [] mapper = class_mapper(obj.__class__) for mproperty in mapper.iterate_properties: if mproperty.key.startswith("_vp"): #skip vertical props continue if mproperty.key in exclude: continue seen_keys.append(mproperty.key) value = getattr(obj, mproperty.key) if value == parent: continue if value is None: continue if isinstance(mproperty, RelationshipProperty) and depth > 0: if isinstance(value, collections.Iterable): result[mproperty.key] = [] for item in value: # !+DEPTH(ah, 2014-09-19) depth was set to 1 here, this causes # a very deep branching for upper level groups like legislature and chamber # and legislature times out occasionally. Doesnt seem neccessary to go depth=1 # for child objects, because they get serialized independently anyway, changing # depth to depth-1 so all dependent objects are iterated 1 level lower than the # parent. # UPDATE(ah, 2014-11-03) Item Schedule is an exceptional case of an object # whose context is within a parent container but is not visible outside of the sitting # it is not a type defined in types.xml and does not have its own # wokflow so we need to handle that in a unique way # we don't decrement the depth and instead process it as is active_depth = depth if item.__class__.__name__ == "ItemSchedule": active_depth = depth else: active_depth = depth-1 result[mproperty.key].append( obj2dict( item, active_depth, parent=obj, include=["owner", "item_schedule", "item_schedule_discussion"], exclude=exclude + INNER_EXCLUDES, lang=lang, root_key=root_key ) ) else: result[mproperty.key] = obj2dict(value, depth-1, parent=obj, include=["owner"], exclude=exclude + INNER_EXCLUDES, lang=lang, root_key=root_key ) else: if isinstance(mproperty, RelationshipProperty): continue elif isinstance(mproperty, ColumnProperty): columns = mproperty.columns if len(columns) == 1: if is_column_binary(columns[0]): fname = PersistFiles.store_file(obj, parent, columns[0].key, root_key) if fname: result[columns[0].key] = dict(saved_file=fname) continue if descriptor: columns = mproperty.columns is_foreign = False if len(columns) == 1: if len(columns[0].foreign_keys): is_foreign = True if (not is_foreign) and (mproperty.key in descriptor.keys()): field = descriptor.get(mproperty.key) if (field and field.property and (schema.interfaces.IChoice.providedBy(field.property) or IVocabularyTextField.providedBy(field.property)) ): factory = field.property.vocabulary or field.property.source if factory is None: vocab_name = getattr(field.property, "vocabularyName", None) factory = get_vocabulary(vocab_name) # !+VOCABULARIES(mb, aug-2012)some vocabularies # expect an interaction to generate values # todo - update these vocabularies to work # with no request e.g. in notification threads display_name = None try: vocabulary = factory(obj) # handle vdex hierarchical terms if ITreeVocabulary.providedBy(factory): values = value.splitlines() term_values = [] for val in values: term_values.append(dict( name=mproperty.key, value=val, displayAs=factory.getTermCaption( factory.getTermById(val), lang=lang))) result[mproperty.key] = term_values continue term = vocabulary.getTerm(value) if lang: if hasattr(factory, "getTermCaption"): display_name = factory.getTermCaption( factory.getTermById(value), lang=lang) else: display_name = translate( term.title or term.value, target_language=lang, domain="bungeni") else: display_name = term.title or term.value except zope.security.interfaces.NoInteraction: log.error("This vocabulary %s expects an interaction " "to generate terms.", factory) # try to use dc adapter lookup try: _prop = mapper.get_property_by_column( mproperty.columns[0]) _prop_value = getattr(obj, _prop.key) dc = IDCDescriptiveProperties(_prop_value, None) if dc: display_name = IDCDescriptiveProperties( _prop_value).title except KeyError: log.warn("No display text found for %s on " "object %s. Unmapped in orm.", property.key, obj) except Exception, e: log.error("Could not instantiate vocabulary %s. " "Exception: %s", factory, e) finally: # fallback we cannot look up vocabularies/dc if display_name is None: if not isinstance(value, unicode): display_name = unicode(value) if display_name is not None: result[mproperty.key] = dict( name=mproperty.key, value=value, displayAs=display_name) continue