def documentTemplates(self, locale): templates = [] templates_path = capi.get_path_for("reporting", "templates", "templates.xml" ) if os.path.exists(templates_path): template_config = etree.fromstring(open(templates_path).read()) for template in template_config.iter(tag="template"): template_file_name = template.get("file") template_language = template.get("language", capi.default_language ) location = capi.get_path_for("reporting", "templates", template_file_name ) if os.path.exists(location): if (locale.id.language != template_language): continue template_dict = dict( title = template.get("name"), language = template.get("language"), location = base64.encodestring(template_file_name) ) templates.append(template_dict) else: log.error("Template does not exist. No file found at %s.", location ) return templates
def write_to_custom(where, file_name, contents): """ Helper api to write to bungeni_custom """ import os from bungeni.capi import capi path = capi.get_path_for(where, ".auto") if not os.path.exists(path): os.makedirs(path) open(capi.get_path_for(path, file_name), "w").write(contents)
def forms_localization_check_reload(event): """Called once from forms_localization_init() and (if in DEVMODE) once_per_request on IBeforeTraverseEvent events (ui.publication). !+ note: switching descriptor on a type config requires restart! """ # a cache of descriptor elems, to be able to update "re-used" descriptors DESC_ELEMS_MODIFIED_SINCE = {} # "sys" descriptors, if PATH_UI_FORMS_SYSTEM is modified (or not yet loaded) if capi.is_modified_since(PATH_UI_FORMS_SYSTEM): descriptor_doc = capi.schema.validate_file_rng("descriptor", PATH_UI_FORMS_SYSTEM) Field._roles[:] = roles.SYSTEM_ROLES + roles.CUSTOM_ROLES # reset global "constant" ROLES_DEFAULT global ROLES_DEFAULT ROLES_DEFAULT = " ".join(Field._roles) for edescriptor in descriptor_doc.findall("descriptor"): type_key = xas(edescriptor, "name") descriptor_cls = localize_descriptor(type_key, edescriptor) DESC_ELEMS_MODIFIED_SINCE[type_key] = edescriptor for type_key, ti in capi.iter_type_info(scope="custom"): # only check "dedicated" descriptor files if ti.descriptor_key == type_key: # ok, check if dedicated descriptor file has been modified (or not yet loaded) #!+get_descriptor_elem file_path = capi.get_path_for("forms", "%s.xml" % (type_key)) if capi.is_modified_since(file_path): descriptor_elem = capi.schema.validate_file_rng("descriptor", file_path) descriptor_cls = localize_descriptor(type_key, descriptor_elem, scope="custom") DESC_ELEMS_MODIFIED_SINCE[type_key] = descriptor_elem else: # re-using another descriptor... if ti.descriptor_key in DESC_ELEMS_MODIFIED_SINCE: descriptor_elem = DESC_ELEMS_MODIFIED_SINCE[ti.descriptor_key] descriptor_cls = localize_descriptor(type_key, descriptor_elem, scope="custom") DESC_ELEMS_MODIFIED_SINCE.clear()
def load_notification_config(file_name, domain_class): """Loads the notification configuration for each document """ notifications_utility = component.getUtility(INotificationsUtility) path = capi.get_path_for("notifications") file_path = os.path.join(path, file_name) notification = capi.schema.validate_file_rng("notifications", file_path) item_type = file_name.split(".")[0] notifications_utility.register_item_type(domain_class, item_type) for notify in notification.iterchildren("notify"): roles = capi.schema.qualified_roles(notify.get("roles")) for role in roles: assert component.queryUtility(IRole, role, None), \ "Notifications configuration error : " \ "Invalid role - %s. file: %s, state : %s" % ( role, file_name) if notify.get("onstate"): states = notify.get("onstate").split() for state in states: notifications_utility.set_transition_based_notification( domain_class, state, roles) elif notify.get("afterstate"): states = notify.get("afterstate").split() time = notify.get("time") for state in states: notifications_utility.set_time_based_notification( domain_class, state, roles, time) else: raise ValueError("Please specify either onstate or afterstate") # Register subscriber for domain class component.provideHandler(queue_notification, adapts=(domain_class, IWorkflowTransitionEvent))
def load_workspace(file_name, domain_class, workflow): """Loads the workspace configuration for each documemnt. """ workspace_utility = component.getUtility(IWorkspaceTabsUtility) path = capi.get_path_for("workspace") file_path = os.path.join(path, file_name) workspace = capi.schema.validate_file_rng("workspace", file_path) item_type = file_name.split(".")[0] workspace_utility.register_item_type(domain_class, item_type) for state in workspace.iterchildren(tag="state"): # Raises invalid state error if there is no such state defined in the # workflow workflow.get_state(state.get("id")) for tab in state.iterchildren(tag="tab"): assert tab.get("id") in capi.workspace_tabs, ( "Workspace configuration error : " "Invalid tab - %s. file: %s, state : %s" % (tab.get("id"), file_name, state.get("id")) ) if tab.get("roles"): roles = capi.schema.qualified_roles(tab.get("roles")) for role in roles: assert component.queryUtility(IRole, role, None), ( "Workspace configuration error : " "Invalid role - %s. file: %s, state : %s" % (role, file_name, state.get("id")) ) workspace_utility.set_content(role, tab.get("id"), domain_class, state.get("id"))
def register_custom_types(): """Extend TYPE_REGISTRY with the declarations from bungeni_custom/types.xml. This is called prior to loading of the workflows for these custom types. Returns (type_key, TI) for the newly created TI instance. """ def parse_elem(type_elem): type_key = misc.xml_attr_str(type_elem, "name") workflow_key = misc.xml_attr_str(type_elem, "workflow", default=type_key) archetype_key = type_elem.tag # !+archetype? move to types? return type_key, workflow_key, archetype_key def enabled_elems(elems): for elem in elems: if misc.xml_attr_bool(elem, "enabled", default=True): yield elem # load XML file etypes = etree.fromstring(misc.read_file(capi.get_path_for("types.xml"))) # register enabled types - ignoring not enabled types from bungeni.alchemist import type_info for edoc in enabled_elems(etypes.iterchildren("doc")): type_key, ti = type_info.register_new_custom_type(*parse_elem(edoc)) # group/member types for egroup in enabled_elems(etypes.iterchildren("group")): type_key, ti = type_info.register_new_custom_type(*parse_elem(egroup)) for emember in enabled_elems(egroup.iterchildren("member")): type_key, ti = type_info.register_new_custom_type( *parse_elem(emember))
def register_custom_types(): """Extend TYPE_REGISTRY with the declarations from bungeni_custom/types.xml. This is called prior to loading of the workflows for these custom types. Returns (type_key, TI) for the newly created TI instance. """ xas, xab = misc.xml_attr_str, misc.xml_attr_bool tag_archetype_key_mapping = { "doc": "doc", "event": "event", "group": "group", "member": "group_member" } def parse_elem(type_elem): type_key = xas(type_elem, "name") workflow_key = xas(type_elem, "workflow") descriptor_key = xas(type_elem, "descriptor") sys_archetype_key = tag_archetype_key_mapping[type_elem.tag] custom_archetype_key = xas(type_elem, "archetype") label = xas(type_elem, "label", None) container_label = xas(type_elem, "container_label", None) return (type_key, sys_archetype_key, custom_archetype_key, workflow_key, descriptor_key, label, container_label) def enabled_elems(elems): for elem in elems: if xab(elem, "enabled", default=True): yield elem # load types.xml file_path = capi.get_path_for("types.xml") etypes = capi.schema.validate_file_rng("types", file_path) # register enabled types - ignoring not enabled types from bungeni.alchemist import type_info # custom "event" types (must be loaded prior to custom "doc" types) for etype in enabled_elems(etypes.iterchildren("event")): type_key, ti = type_info.register_new_custom_type(*parse_elem(etype)) # custom "doc" types for etype in enabled_elems(etypes.iterchildren("doc")): type_key, ti = type_info.register_new_custom_type(*parse_elem(etype)) # group/member types for egroup in enabled_elems(etypes.iterchildren("group")): group_type_key, ti = type_info.register_new_custom_type(*parse_elem(egroup)) ti.domain_model.privilege_extent = xas(egroup, "privilege_extent", "group") for emember in enabled_elems(egroup.iterchildren("member")): type_key, ti = type_info.register_new_custom_type(*parse_elem(emember)) ti.within_type_key = group_type_key # SYSTEM WIDE settings (set on class attributes on capi) capi.__class__.bicameral = xab(etypes, "bicameral") capi.__class__.country_code = xas(etypes, "country_code") capi.__class__.legislature_type_key = xas(etypes, "legislature_type") capi.__class__.chamber_type_key = xas(etypes, "chamber_type") # sanity checks for tk in (capi.chamber_type_key, capi.legislature_type_key): ti = capi.get_type_info(tk) # KeyError assert ti.sys_archetype_key == "group", \ "Value %r specified for %r must be a %r" % (tk, attr, "group")
def register_custom_types(): """Extend TYPE_REGISTRY with the declarations from bungeni_custom/types.xml. This is called prior to loading of the workflows for these custom types. Returns (type_key, TI) for the newly created TI instance. """ def parse_elem(type_elem): type_key = misc.xml_attr_str(type_elem, "name") workflow_key = misc.xml_attr_str(type_elem, "workflow", default=type_key) archetype_key = type_elem.tag # !+archetype? move to types? return type_key, workflow_key, archetype_key def enabled_elems(elems): for elem in elems: if misc.xml_attr_bool(elem, "enabled", default=True): yield elem # load XML file etypes = etree.fromstring(misc.read_file(capi.get_path_for("types.xml"))) # register enabled types - ignoring not enabled types from bungeni.alchemist import type_info for edoc in enabled_elems(etypes.iterchildren("doc")): type_key, ti = type_info.register_new_custom_type(*parse_elem(edoc)) # group/member types for egroup in enabled_elems(etypes.iterchildren("group")): type_key, ti = type_info.register_new_custom_type(*parse_elem(egroup)) for emember in enabled_elems(egroup.iterchildren("member")): type_key, ti = type_info.register_new_custom_type(*parse_elem(emember))
def load_workspace(file_name, domain_class, workflow): """Loads the workspace configuration for each documemnt. """ workspace_utility = component.getUtility(IWorkspaceTabsUtility) path = capi.get_path_for("workspace") file_path = os.path.join(path, file_name) workspace = capi.schema.validate_file_rng("workspace", file_path) item_type = file_name.split(".")[0] workspace_utility.register_item_type(domain_class, item_type) for state in workspace.iterchildren(tag="state"): # Raises invalid state error if there is no such state defined in the # workflow workflow.get_state(state.get("id")) for tab in state.iterchildren(tag="tab"): assert tab.get("id") in capi.workspace_tabs, \ "Workspace configuration error : " \ "Invalid tab - %s. file: %s, state : %s" % ( tab.get("id"), file_name, state.get("id")) if tab.get("roles"): roles = capi.schema.qualified_roles(tab.get("roles")) for role in roles: assert component.queryUtility(IRole, role, None), \ "Workspace configuration error : " \ "Invalid role - %s. file: %s, state : %s" % ( role, file_name, state.get("id")) workspace_utility.set_content(role, tab.get("id"), domain_class, state.get("id"))
def write_to_custom(where, file_name, contents): """ Helper api to write to bungeni_custom """ from bungeni.capi import capi filepath = capi.get_path_for(where, file_name) open(filepath, "w").write(contents)
def check_reload_descriptor_file(type_key, is_init): """Check if a singel file has been modified and needs reloading. """ #!+get_descriptor_elem file_path = capi.get_path_for("forms", "%s.xml" % (type_key)) if capi.is_modified_since(file_path): descriptor_doc = capi.schema.validate_file_rng("descriptor", file_path) assert xas(descriptor_doc, "name") == type_key, type_key descriptor_cls = localize_descriptor(descriptor_doc, is_init, scope="custom")
def load(file_key, workflow_name, path_custom_workflows=capi.get_path_for("workflows")): """ (type_key:str, file_key:str, workflow_name:str, path_custom_workflows:str) -> Workflow Loads the workflow XML definition file, returning the correspondingly setup Workflow instance. Called by workflows.adapters.load_workflow. """ file_path = os.path.join(path_custom_workflows, "%s.xml" % (file_key)) workflow_doc = capi.schema.validate_file_rng("workflow", file_path) return _load(workflow_name, workflow_doc)
def get_template(file_name): path = capi.get_path_for("email", "templates") file_path = os.path.join(path, file_name) if os.path.exists(file_path): template_file = open(file_path) file_string = template_file.read() template = etree.fromstring(file_string) template_file.close() return template else: raise EmailError("Email template %s does not exist" % file_name)
def setupTemplate(self): """Check if a template was provided in the request as url/form parameter. """ template_encoded = self.request.form.get("template", "") if template_encoded != "": template_file_name = base64.decodestring(template_encoded) template_path = capi.get_path_for("reporting", "templates", template_file_name) if os.path.exists(template_path): self.oo_template_file = template_path
def apply_customization_ui(): """Called from ui.app.on_wsgi_application_created_event -- must be called AFTER custom types have been catalysed. """ # combine config string and execute it zcml = ZCML_SLUG.format(ui_zcml_decls="".join([ zd for zd in UI_ZC_DECLS ])) # log zcml directives to a dedicated file (before executing), for easier debugging misc.check_overwrite_file(capi.get_path_for("workflows/.auto/ui.zcml"), '<?xml version="1.0"?>\n<!-- !! AUTO-GENERATED !! DO NOT MODIFY !! -->' + zcml) # execute the zcml log.debug("Executing UI feature configuration:\n%s", zcml) xmlconfig.string(zcml)
def load(file_key, workflow_name, path_custom_workflows=capi.get_path_for("workflows") ): """ (type_key:str, file_key:str, workflow_name:str, path_custom_workflows:str) -> Workflow Loads the workflow XML definition file, returning the correspondingly setup Workflow instance. Called by workflows.adapters.load_workflow. """ file_path = os.path.join(path_custom_workflows, "%s.xml" % (file_key)) workflow_doc = capi.schema.validate_file_rng("workflow", file_path) return _load(workflow_name, workflow_doc)
def load_workspace(file_name, domain_class, workflow): """Loads the workspace configuration for each document. """ # !+LEGISLATURE_SETUP on first run on an emtpy database, no groups exists # and so all these tests will fail -- as a partial workaround, only execute # these tests if one Legislature instance is in existence... if Session().query(domain.Legislature).all(): # !+GROUP_NAMES_VALIDATION from bungeni.models.utils import get_group_conceptual_active for conceptual_name in workflow.get_feature("workspace").get_param( "group_names"): try: get_group_conceptual_active(conceptual_name) except orm.exc.NoResultFound: raise Exception( "Workflow %r feature %r parameter %r contains " "invalid value %r -- no active group with such a conceptual_name " "found in the database." % (workflow.name, "workspace", "group_names", conceptual_name)) # !+/GROUP_NAMES_VALIDATION workspace_utility = component.getUtility(IWorkspaceTabsUtility) path = capi.get_path_for("workspace") file_path = os.path.join(path, file_name) workspace = capi.schema.validate_file_rng("workspace", file_path) type_key = file_name.split(".")[0] workspace_utility.register_domain_type(domain_class, type_key) # to bookkeep that every workflow state is workspace-declared workflow_state_ids = set(workflow._states_by_id.keys()) for state in workspace.iterchildren(tag="state"): state_id = state.get("id") workflow.get_state(state_id) # InvalidStateError if no such state assert state_id in workflow_state_ids, \ "configuration file workspace/%s - duplicate declaration found for state: %r" % ( file_name, state_id) workflow_state_ids.remove(state_id) for tab in state.iterchildren(tag="tab"): tab_name = tab.get("id") # !+ assert tab_name in capi.workspace_tabs, \ "configuration file workspace/%s - invalid tab: %r [state: %r]" % ( file_name, tab_name, state_id) tab_roles = tab.get("roles") if tab_roles: roles = capi.schema.qualified_roles(tab_roles.split()) for role in roles: assert component.queryUtility(IRole, role, None), \ "configuration file workspace/%s - invalid role: %r [state: %r]" % ( file_name, role, state_id) workspace_utility.set_content(role, tab_name, domain_class, state_id) assert not workflow_state_ids, \ "configuration file workspace/%s - no declaration found for states: %s" % ( file_name, list(workflow_state_ids))
def setupTemplate(self): """Check if a template was provided in the request as url/form parameter. """ template_encoded = self.request.form.get("template", "") if template_encoded != "": template_file_name = base64.decodestring(template_encoded) template_path = capi.get_path_for("reporting", "templates", template_file_name ) if os.path.exists(template_path): self.oo_template_file = template_path
def set_get_gettext(): """Set this callable as the z3evoque.get_gettext global function to return a gettext bound onto an i18n domain and a language. This function is to be defined and called by the application - get_gettext itself should have the parameters (i18n_domain, language). """ from bungeni.capi import capi _i18n_domain_localedirs = { "bungeni": capi.get_path_for("translations", "bungeni"), } _untranslated = [] def _get_gettext(i18n_domain, language): """Get a _() i18n gettext function bound to domain and language. !+ There is probably a better way to do this; the following "obvious" way does not work: zope.i18nmessageid.MessageFactory(i18n_domain) """ import gettext try: t = gettext.translation( i18n_domain, localedir=_i18n_domain_localedirs[i18n_domain], languages=[language]) except (IOError, ): cls, exc, tb = sys.exc_info() if language != "en": log.error(""" [%s] %s [lang=%s] -> trying with [lang=%s]""" % (cls.__name__, exc, language, "en")) return _get_gettext(i18n_domain, "en") else: log.error(""" [%s] %s [lang=%s]""" % (cls.__name__, exc, language)) raise exc # wrap t.gettext to intercept and log possibly untranslated msgids def _gt(msgid): try: msgstr = t.gettext(msgid) return msgstr finally: if msgid == msgstr and msgid not in _untranslated: _untranslated.append(msgid) log.warn('i18n NOT LOCALIZED [%s, %s] "%s"' % (i18n_domain, language, msgid)) return _gt global get_gettext get_gettext = _get_gettext
def get_mask(context): # assert IBungeniParliamentaryContent.providedBy(context) # !+IBungeniParliamentaryContent(mr, nov-2011) only context typed # interfaces.IBungeniParliamentaryContent should ever get here! # But for this case, all we need is that context defines a type: m = "PI context [%s] for get_mask must specify a type attr" % (context) assert hasattr(context, "type"), m path = capi.get_path_for("registry") config = ConfigParser() config.readfp(open(os.path.join(path, "config.ini"))) try: return config.get("types", context.type) except NoOptionError: return None
def load_workspace(file_name, domain_class, workflow): """Loads the workspace configuration for each document. """ # !+LEGISLATURE_SETUP on first run on an emtpy database, no groups exists # and so all these tests will fail -- as a partial workaround, only execute # these tests if one Legislature instance is in existence... if Session().query(domain.Legislature).all(): # !+GROUP_NAMES_VALIDATION from bungeni.models.utils import get_group_conceptual_active for conceptual_name in workflow.get_feature("workspace").get_param("group_names"): try: get_group_conceptual_active(conceptual_name) except orm.exc.NoResultFound: raise Exception("Workflow %r feature %r parameter %r contains " "invalid value %r -- no active group with such a conceptual_name " "found in the database." % ( workflow.name, "workspace", "group_names", conceptual_name)) # !+/GROUP_NAMES_VALIDATION workspace_utility = component.getUtility(IWorkspaceTabsUtility) path = capi.get_path_for("workspace") file_path = os.path.join(path, file_name) workspace = capi.schema.validate_file_rng("workspace", file_path) type_key = file_name.split(".")[0] workspace_utility.register_domain_type(domain_class, type_key) # to bookkeep that every workflow state is workspace-declared workflow_state_ids = set(workflow._states_by_id.keys()) for state in workspace.iterchildren(tag="state"): state_id = state.get("id") workflow.get_state(state_id) # InvalidStateError if no such state assert state_id in workflow_state_ids, \ "configuration file workspace/%s - duplicate declaration found for state: %r" % ( file_name, state_id) workflow_state_ids.remove(state_id) for tab in state.iterchildren(tag="tab"): tab_name = tab.get("id") # !+ assert tab_name in capi.workspace_tabs, \ "configuration file workspace/%s - invalid tab: %r [state: %r]" % ( file_name, tab_name, state_id) tab_roles = tab.get("roles") if tab_roles: roles = capi.schema.qualified_roles(tab_roles.split()) for role in roles: assert component.queryUtility(IRole, role, None), \ "configuration file workspace/%s - invalid role: %r [state: %r]" % ( file_name, role, state_id) workspace_utility.set_content( role, tab_name, domain_class, state_id) assert not workflow_state_ids, \ "configuration file workspace/%s - no declaration found for states: %s" % ( file_name, list(workflow_state_ids))
def documentTemplates(self, locale): templates = [] templates_path = capi.get_path_for("reporting", "templates", "templates.xml") if os.path.exists(templates_path): template_config = etree.fromstring(open(templates_path).read()) for template in template_config.iter(tag="template"): template_file_name = template.get("file") template_language = template.get("language", capi.default_language) location = capi.get_path_for("reporting", "templates", template_file_name) if os.path.exists(location): if (locale.id.language != template_language): continue template_dict = dict( title=template.get("name"), language=template.get("language"), location=base64.encodestring(template_file_name)) templates.append(template_dict) else: log.error("Template does not exist. No file found at %s.", location) return templates
def set_get_gettext(): """Set this callable as the z3evoque.get_gettext global function to return a gettext bound onto an i18n domain and a language. This function is to be defined and called by the application - get_gettext itself should have the parameters (i18n_domain, language). """ from bungeni.capi import capi _i18n_domain_localedirs = { "bungeni": capi.get_path_for("translations", "bungeni"), } _untranslated = [] def _get_gettext(i18n_domain, language): """Get a _() i18n gettext function bound to domain and language. !+ There is probably a better way to do this; the following "obvious" way does not work: zope.i18nmessageid.MessageFactory(i18n_domain) """ import gettext try: t = gettext.translation(i18n_domain, localedir=_i18n_domain_localedirs[i18n_domain], languages=[language]) except (IOError,): cls, exc, tb = sys.exc_info() if language != "en": log.error(""" [%s] %s [lang=%s] -> trying with [lang=%s]""", cls.__name__, exc, language, "en") return _get_gettext(i18n_domain, "en") else: log.error(""" [%s] %s [lang=%s]""", cls.__name__, exc, language) raise exc # wrap t.gettext to intercept and log possibly untranslated msgids def _gt(msgid): try: msgstr = t.ugettext(msgid) return msgstr finally: if msgid == msgstr and msgid not in _untranslated: _untranslated.append(msgid) log.warn('i18n NOT LOCALIZED [%s, %s] "%s"', i18n_domain, language, msgid) return _gt global get_gettext get_gettext = _get_gettext
def zcml_check_regenerate(): """Called after all XML workflows have been loaded (see adapers.py). """ #!+permissions.zcml(mr, aug-2011) bypass writing to disk? filepath = capi.get_path_for(os.path.join("workflows/.auto/", ZCML_FILENAME)) # read current file try: persisted = open(filepath, "r").read().decode("utf-8") except IOError: persisted = u"" # regenerate, compare, and re-write if needed regenerated = ZCML_BOILERPLATE % ("\n".join(ZCML_LINES)) if persisted != regenerated: if not os.path.exists(os.path.dirname(filepath)): os.makedirs(os.path.dirname(filepath)) log.warn("CHANGES to file:\n%s", misc.unified_diff(persisted, regenerated, filepath, "NEW")) open(filepath, "w").write(regenerated.encode("utf-8"))
def load_custom_roles(): file_path = capi.get_path_for("roles.xml") roles_config = capi.schema.validate_file_rng("roles", file_path) gsm = zope.component.getGlobalSiteManager() custom_roles = [] for role_config in roles_config.iterchildren(tag="role"): role_id = "bungeni.%s" % (role_config.get("id")) custom_roles.append(role_id) role = Role(role_id, role_config.get("title")) role_annt = interfaces.ISubRoleAnnotations(role) gsm.registerUtility(role, IRole, role_id) for sub_role_config in role_config.iterchildren(tag="subrole"): sub_role_id = "bungeni.%s" % (sub_role_config.get("id")) custom_roles.append(sub_role_id) sub_role = Role(sub_role_id, sub_role_config.get("title")) sub_role_annt = interfaces.ISubRoleAnnotations(sub_role) sub_role_annt.is_sub_role = True sub_role_annt.parent = role role_annt.sub_roles.append(sub_role_id) gsm.registerUtility(sub_role, IRole, sub_role_id) CUSTOM_ROLES[:] = sorted(custom_roles)
def load_workspace(file_name, domain_class): """Loads the workspace configuration for each documemnt. """ workspace_utility = component.getUtility(IWorkspaceTabsUtility) path = capi.get_path_for("workspace") file_path = os.path.join(path, file_name) item_type = file_name.split(".")[0] workspace_utility.register_item_type(domain_class, item_type) workspace = etree.fromstring(open(file_path).read()) for state in workspace.iterchildren(tag="state"): for tab in state.iterchildren(tag="tab"): assert tab.get("id") in capi.workspace_tabs, \ "Workspace configuration error : " \ "Invalid tab - %s. file: %s, state : %s" % ( tab.get("id"), file_name, state.get("id")) if tab.get("roles"): roles = tab.get("roles").split() for role in roles: assert component.queryUtility(IRole, role, None), \ "Workspace configuration error : " \ "Invalid role - %s. file: %s, state : %s" % ( role, file_name, state.get("id")) workspace_utility.set_content(role, tab.get("id"), domain_class, state.get("id"))
Field, show, hide, #norm_sorted, ) from bungeni.models import roles from bungeni.ui.descriptor import field from bungeni.capi import capi from bungeni.utils import naming, misc xas, xab, xai = misc.xml_attr_str, misc.xml_attr_bool, misc.xml_attr_int # constants import bungeni.ui.descriptor.descriptor as DESCRIPTOR_MODULE PATH_UI_FORMS_SYSTEM = capi.get_path_for("forms", "ui.xml") ROLES_DEFAULT = " ".join(Field._roles) #### # Load and apply forms localization -- # Localize descriptors from {bungeni_custom}/forms/. def is_descriptor(cls): try: return IModelDescriptor.implementedBy(cls) except (TypeError, AttributeError): return False ''' try: return issubclass(cls, ModelDescriptor):
show, hide, #norm_sorted, ) from bungeni.models import roles from bungeni.ui.descriptor import field from bungeni.capi import capi from bungeni.utils import naming, misc xas, xab, xai = misc.xml_attr_str, misc.xml_attr_bool, misc.xml_attr_int # constants from bungeni.ui.descriptor import descriptor as DESCRIPTOR_MODULE PATH_UI_FORMS_SYSTEM = capi.get_path_for("forms", "ui.xml") ROLES_DEFAULT = " ".join(Field._roles) #### # Load and apply forms localization -- # Localize descriptors from {bungeni_custom}/forms/. def is_descriptor(cls): try: return IModelDescriptor.implementedBy(cls) except (TypeError, AttributeError): return False ''' try: return issubclass(cls, ModelDescriptor):
def register_custom_types(): """Extend TYPE_REGISTRY with the declarations from bungeni_custom/types.xml. This is called prior to loading of the workflows for these custom types. Returns (type_key, TI) for the newly created TI instance. """ xas, xab = misc.xml_attr_str, misc.xml_attr_bool tag_archetype_key_mapping = { "doc": "doc", "event": "event", "group": "group", "member": "group_member" } def parse_elem(type_elem): type_key = xas(type_elem, "name") workflow_key = xas(type_elem, "workflow") descriptor_key = xas(type_elem, "descriptor") sys_archetype_key = tag_archetype_key_mapping[type_elem.tag] custom_archetype_key = xas(type_elem, "archetype") label = xas(type_elem, "label", None) container_label = xas(type_elem, "container_label", None) return (type_key, sys_archetype_key, custom_archetype_key, workflow_key, descriptor_key, label, container_label) def enabled_elems(elems): for elem in elems: if xab(elem, "enabled", default=True): yield elem # load types.xml file_path = capi.get_path_for("types.xml") etypes = capi.schema.validate_file_rng("types", file_path) # register enabled types - ignoring not enabled types from bungeni.alchemist import type_info # custom "event" types (must be loaded prior to custom "doc" types) for etype in enabled_elems(etypes.iterchildren("event")): type_key, ti = type_info.register_new_custom_type(*parse_elem(etype)) # custom "doc" types for etype in enabled_elems(etypes.iterchildren("doc")): type_key, ti = type_info.register_new_custom_type(*parse_elem(etype)) # group/member types for egroup in enabled_elems(etypes.iterchildren("group")): group_type_key, ti = type_info.register_new_custom_type( *parse_elem(egroup)) ti.domain_model.privilege_extent = xas(egroup, "privilege_extent", "group") for emember in enabled_elems(egroup.iterchildren("member")): type_key, ti = type_info.register_new_custom_type( *parse_elem(emember)) ti.within_type_key = group_type_key # SYSTEM WIDE settings (set on class attributes on capi) capi.__class__.bicameral = xab(etypes, "bicameral") capi.__class__.country_code = xas(etypes, "country_code") capi.__class__.legislature_type_key = xas(etypes, "legislature_type") capi.__class__.chamber_type_key = xas(etypes, "chamber_type") # sanity checks for tk in (capi.chamber_type_key, capi.legislature_type_key): ti = capi.get_type_info(tk) # KeyError assert ti.sys_archetype_key == "group", \ "Value %r specified for %r must be a %r" % (tk, attr, "group")
def zcml_check_regenerate(): """For debug purposes; called after loading of all XML workflows (adapers.py). """ misc.check_overwrite_file( capi.get_path_for(os.path.join("workflows/.auto/", ZCML_FILENAME)), ZCML_BOILERPLATE % ("\n".join(ZCML_LINES)))
def setUp(self): # register translations #import zope.i18n.zcml #zope.i18n.zcml.registerTranslations(getConfigContext(), # capi.get_path_for("translations", "bungeni")) # !+ZCML_PYTHON(mr, apr-2011) above registerTranslations() in python # does not work, as subsequent utility lookup fails. We workaround it # by executing the following parametrized bit of ZCML: from zope.configuration import xmlconfig xmlconfig.string(""" <configure xmlns="http://namespaces.zope.org/zope" xmlns:i18n="http://namespaces.zope.org/i18n"> <include package="zope.i18n" file="meta.zcml" /> <i18n:registerTranslations directory="%s" /> </configure> """ % (capi.get_path_for("translations", "bungeni"))) sm = site.LocalSiteManager(self.context) self.context.setSiteManager(sm) from bungeni.core import language from bungeni.ui import z3evoque z3evoque.set_get_gettext() z3evoque.setup_evoque() z3evoque.domain.set_on_globals("devmode", common.has_feature("devmode")) z3evoque.domain.set_on_globals("absoluteURL", url.absoluteURL) z3evoque.domain.set_on_globals("get_section_name", url.get_section_name) z3evoque.domain.set_on_globals("get_base_direction", language.get_base_direction) z3evoque.domain.set_on_globals("is_rtl", language.is_rtl) # !+ where is the view name for the app root (slash) set? # CONVENTION: the action of each site top-section is made to point # directly the primary sub-section (the INDEX) that it contains. # EXCEPTION: the "/", when logged in, is redirected to "/workspace/pi" self.context["bungeni"] = AkomaNtosoSection( title=_(u"Bungeni"), description=_(u"Current parliamentary activity"), default_name="bung", # !+NAMING(mr, jul-2011) bung?!? ) # top-level sections workspace = self.context["workspace"] = WorkspaceSection( title=_("section_workspace", default=u"Workspace"), description=_(u"Current parliamentary activity"), default_name="my-documents", ) alsoProvides(workspace, interfaces.ISearchableSection) workspace["my-documents"] = WorkspaceSection( title=_("section_workspace_documents", default=u"my documents"), description=_(u"my documents workspace section"), default_name="inbox", marker=interfaces.IWorkspaceDocuments, ) for tab in capi.workspace_tabs: workspace["my-documents"][tab] = WorkspaceContainer( tab_type=tab, title=_("section_workspace_%s" % tab, default=tab), marker=interfaces.IWorkspaceTab) ws_uc = workspace["under-consideration"] = WorkspaceSection( title=_(u"under consideration"), description=_(u"documents under consideration"), default_name="documents", marker=interfaces.IWorkspaceUnderConsideration) ws_uc["documents"] = WorkspaceUnderConsiderationContainer( name="documents", title=_(u"under consideration"), description=_(u"documents under consideration"), marker=interfaces.IWorkspaceTrackedDocuments) ws_uc["tracked-documents"] = WorkspaceTrackedDocumentsContainer( name="tracked documents", title=_(u"tracked documents"), description=_(u"tracked documents")) ws_sched = workspace["scheduling"] = Section( title=_("section_scheduling", default=u"Scheduling"), description=_(u"Workspace Scheduling"), default_name="index", marker=interfaces.IWorkspaceScheduling) ws_sched["committees"] = QueryContent( container_getter(get_chamber_for_context, "committees"), title=_("section_scheduling_committees", default=u"Committees"), #!+marker=interfaces.ICommitteeAddContext, description=_(u"Committee schedules")) ws_sched["documents"] = WorkspaceSchedulableContainer( name=_(u"schedulable items"), title=_(u"schedulable items"), description=_(u"documents available for scheduling")) ws_sched["sittings"] = QueryContent( container_getter(get_chamber_for_context, "sittings"), title=_("section_scheduling_sittings", default=u"Sittings"), description=_(u"Plenary Sittings")) ws_sched["sessions"] = QueryContent( container_getter(get_chamber_for_context, "sessions"), title=_("section_scheduling_sessions", default=u"Sessions"), description=_(u"Plenary Sessions")) ws_sched["venues"] = QueryContent(container_getter( get_chamber_for_context, "venues"), title=_("section_scheduling_venues", default=u"Venues"), description=_(u"Venues")) ws_sched["agendaitems"] = QueryContent( container_getter(get_chamber_for_context, "agendaitems"), title=_("section_scheduling_agenda_items", default=u"Agenda items"), #marker=interfaces.IAgendaItemAddContext, description=_(u"Manage agenda items")) ws_sched["publications"] = QueryContent( container_getter(get_chamber_for_context, "publications"), title=_("section_scheduling_publications", default=u"Publications"), description=_(u"Publications")) workspace["groups"] = WorkspaceSection( title=_("section_groups", default=u"Groups"), description=_(u"Bungeni Groups"), default_name="my-groups", marker=interfaces.IWorkspaceGroups) workspace["groups"]["my-groups"] = WorkspaceGroupsContainer( name="my-groups", title=_(u"My Groups"), description=_(u"Groups that the user is a member of")) #!+TIMING #!+AUTO CONTAINERS SCHEDULING(mb, April-2012) # type_info missing container name for type_key, ti in capi.iter_type_info(): if model_interfaces.IScheduleContent.implementedBy( ti.domain_model): container_property_name = naming.plural(type_key) container_class_name = naming.container_class_name(type_key) if not ws_sched.has_key(container_property_name): ws_sched[container_property_name] = \ getattr(domain, container_class_name)() to_locatable_container(ti.domain_model, ws_sched[container_property_name]) ########## # Admin User Interface # Administration section #!+SECURITY(miano. nov-2010) Admin section now uses AdminSection # container that is identical to Section, only difference is that # traversing though it requires zope.ManageSite permission as defined # in core/configure.zcml admin = self.context["admin"] = AdminSection( title=_(u"Administration"), description=_(u"Manage bungeni settings"), default_name="admin-index", marker=model_interfaces.IBungeniAdmin) content = admin["content"] = Section( title=_(u"Content"), description=_(u"browse bungeni content"), marker=model_interfaces.IBungeniAdmin, default_name="browse-admin") alsoProvides(content, interfaces.ISearchableSection) admin["email-settings"] = Section( title=_(u"email settings"), description=_(u"manage email settings"), marker=model_interfaces.IBungeniAdmin, default_name="email-settings") admin["search-settings"] = Section( title=_(u"search settings"), description=_(u"manage bungeni email settings"), marker=model_interfaces.IBungeniAdmin, default_name="search-settings") admin["registry-settings"] = Section( title=_(u"registry settings"), description=_(u"manage registry settings"), marker=model_interfaces.IBungeniAdmin, default_name="registry-settings") admin["serialization-manager"] = Section( title=_(u"serialization manager"), description=_(u"batch serialization of content"), marker=model_interfaces.IBungeniAdmin, default_name="serialization-manager") content[u"parliaments"] = domain.ParliamentContainer() to_locatable_container(domain.Parliament, content[u"parliaments"]) content[u"governments"] = domain.GovernmentContainer() to_locatable_container(domain.Government, content[u"governments"]) content[u"joint-committees"] = domain.JointCommitteeContainer() to_locatable_container(domain.JointCommittee, content["joint-committees"]) content[u"users"] = domain.UserContainer() to_locatable_container(domain.User, content[u"users"]) api = self.context[u"api"] = APISection( title=_(u"Bungeni API"), description=_(u"Bungeni REST API"), default_name="index", ) api[u"workspace"] = copy.deepcopy(workspace) api[u"users"] = copy.deepcopy(content[u"users"]) self.context["oauth"] = OAuthSection( title=_(u"Bungeni OAuth API"), description=_(u"Bungeni OAuth API"), default_name="index", ) admin[u"applications"] = domain.OAuthApplicationContainer() to_locatable_container(domain.OAuthApplication, admin[u"applications"])
def setUp(self): # register translations #import zope.i18n.zcml #zope.i18n.zcml.registerTranslations(getConfigContext(), # capi.get_path_for("translations", "bungeni")) # !+ZCML_PYTHON(mr, apr-2011) above registerTranslations() in python # does not work, as subsequent utility lookup fails. We workaround it # by executing the following parametrized bit of ZCML: from zope.configuration import xmlconfig xmlconfig.string(""" <configure xmlns="http://namespaces.zope.org/zope" xmlns:i18n="http://namespaces.zope.org/i18n"> <include package="zope.i18n" file="meta.zcml" /> <i18n:registerTranslations directory="%s" /> </configure> """ % (capi.get_path_for("translations", "bungeni"))) sm = site.LocalSiteManager(self.context) self.context.setSiteManager(sm) from bungeni.core import language from bungeni.ui import z3evoque z3evoque.set_get_gettext() z3evoque.setup_evoque() z3evoque.domain.set_on_globals("devmode", common.has_feature("devmode")) z3evoque.domain.set_on_globals("absoluteURL", url.absoluteURL) z3evoque.domain.set_on_globals("get_section_name", url.get_section_name) z3evoque.domain.set_on_globals("get_base_direction", language.get_base_direction) z3evoque.domain.set_on_globals("is_rtl", language.is_rtl) # !+ where is the view name for the app root (slash) set? # CONVENTION: the action of each site top-section is made to point # directly the primary sub-section (the INDEX) that it contains. # EXCEPTION: the "/", when logged in, is redirected to "/workspace/pi" self.context["bungeni"] = AkomaNtosoSection( title=_(u"Bungeni"), description=_(u"Current parliamentary activity"), default_name="bung", # !+NAMING(mr, jul-2011) bung?!? ) # top-level sections workspace = self.context["workspace"] = WorkspaceSection( title=_("section_workspace", default=u"Workspace"), description=_(u"Current parliamentary activity"), default_name="my-documents", ) alsoProvides(workspace, interfaces.ISearchableSection) workspace["my-documents"] = WorkspaceSection( title=_("section_workspace_documents", default=u"my documents"), description=_(u"my documents workspace section"), default_name="inbox", marker=interfaces.IWorkspaceDocuments, ) for tab in capi.workspace_tabs: workspace["my-documents"][tab] = WorkspaceContainer( tab_type=tab, title=_("section_workspace_%s" % tab, default=tab), marker=interfaces.IWorkspaceTab ) ws_uc = workspace["under-consideration"] = WorkspaceSection( title=_(u"under consideration"), description=_(u"documents under consideration"), default_name="documents", marker=interfaces.IWorkspaceUnderConsideration) ws_uc["documents"] = WorkspaceUnderConsiderationContainer( name="documents", title=_(u"under consideration"), description=_(u"documents under consideration"), marker=interfaces.IWorkspaceTrackedDocuments) ws_uc["tracked-documents"] = WorkspaceTrackedDocumentsContainer( name="tracked documents", title=_(u"tracked documents"), description=_(u"tracked documents")) ws_sched = workspace["scheduling"] = Section( title=_("section_scheduling", default=u"Scheduling"), description=_(u"Workspace Scheduling"), default_name="index", marker=interfaces.IWorkspaceScheduling) ws_sched["committees"] = QueryContent( container_getter(get_chamber_for_context, "committees"), title=_("section_scheduling_committees", default=u"Committees"), #!+marker=interfaces.ICommitteeAddContext, description=_(u"Committee schedules")) ws_sched["documents"] = WorkspaceSchedulableContainer( name=_(u"schedulable items"), title=_(u"schedulable items"), description=_(u"documents available for scheduling")) ws_sched["sittings"] = QueryContent( container_getter(get_chamber_for_context, "sittings"), title=_("section_scheduling_sittings", default=u"Sittings"), description=_(u"Plenary Sittings")) ws_sched["sessions"] = QueryContent( container_getter(get_chamber_for_context, "sessions"), title=_("section_scheduling_sessions", default=u"Sessions"), description=_(u"Plenary Sessions")) ws_sched["venues"] = QueryContent( container_getter(get_chamber_for_context, "venues"), title=_("section_scheduling_venues", default=u"Venues"), description=_(u"Venues")) ws_sched["agendaitems"] = QueryContent( container_getter(get_chamber_for_context, "agendaitems"), title=_("section_scheduling_agenda_items", default=u"Agenda items"), #marker=interfaces.IAgendaItemAddContext, description=_(u"Manage agenda items")) ws_sched["publications"] = QueryContent( container_getter(get_chamber_for_context, "publications"), title=_("section_scheduling_publications", default=u"Publications"), description=_(u"Publications")) workspace["groups"] = WorkspaceSection( title=_("section_groups", default=u"Groups"), description=_(u"Bungeni Groups"), default_name="my-groups", marker=interfaces.IWorkspaceGroups) workspace["groups"]["my-groups"] = WorkspaceGroupsContainer( name="my-groups", title=_(u"My Groups"), description=_(u"Groups that the user is a member of")) #!+TIMING #!+AUTO CONTAINERS SCHEDULING(mb, April-2012) # type_info missing container name for type_key, ti in capi.iter_type_info(): if model_interfaces.IScheduleContent.implementedBy(ti.domain_model): container_property_name = naming.plural(type_key) container_class_name = naming.container_class_name(type_key) if not ws_sched.has_key(container_property_name): ws_sched[container_property_name] = \ getattr(domain, container_class_name)() to_locatable_container( ti.domain_model, ws_sched[container_property_name]) ########## # Admin User Interface # Administration section #!+SECURITY(miano. nov-2010) Admin section now uses AdminSection # container that is identical to Section, only difference is that # traversing though it requires zope.ManageSite permission as defined # in core/configure.zcml admin = self.context["admin"] = AdminSection( title=_(u"Administration"), description=_(u"Manage bungeni settings"), default_name="admin-index", marker=model_interfaces.IBungeniAdmin) content = admin["content"] = Section( title=_(u"Content"), description=_(u"browse bungeni content"), marker=model_interfaces.IBungeniAdmin, default_name="browse-admin") alsoProvides(content, interfaces.ISearchableSection) admin["email-settings"] = Section( title=_(u"email settings"), description=_(u"manage email settings"), marker=model_interfaces.IBungeniAdmin, default_name="email-settings") admin["search-settings"] = Section( title=_(u"search settings"), description=_(u"manage bungeni email settings"), marker=model_interfaces.IBungeniAdmin, default_name="search-settings") admin["registry-settings"] = Section( title=_(u"registry settings"), description=_(u"manage registry settings"), marker=model_interfaces.IBungeniAdmin, default_name="registry-settings") admin["serialization-manager"] = Section( title=_(u"serialization manager"), description=_(u"batch serialization of content"), marker=model_interfaces.IBungeniAdmin, default_name="serialization-manager") content[u"parliaments"] = domain.ParliamentContainer() to_locatable_container(domain.Parliament, content[u"parliaments"]) content[u"governments"] = domain.GovernmentContainer() to_locatable_container(domain.Government, content[u"governments"]) content[u"joint-committees"] = domain.JointCommitteeContainer() to_locatable_container(domain.JointCommittee, content["joint-committees"]) content[u"users"] = domain.UserContainer() to_locatable_container(domain.User, content[u"users"]) api = self.context[u"api"] = APISection( title=_(u"Bungeni API"), description=_(u"Bungeni REST API"), default_name="index", ) api[u"workspace"] = copy.deepcopy(workspace) api[u"users"] = copy.deepcopy(content[u"users"]) self.context["oauth"] = OAuthSection( title=_(u"Bungeni OAuth API"), description=_(u"Bungeni OAuth API"), default_name="index", ) admin[u"applications"] = domain.OAuthApplicationContainer() to_locatable_container(domain.OAuthApplication, admin[u"applications"])