def format_docs(docs, ignore_modules=()): # type: (t.Iterable[t.Tuple[str, t.Text]], t.Container[str]) -> t.Iterable[t.Text] docs = list(docs) for module, doc in docs: if module in ignore_modules: continue doc = color.highlight(doc, "rst") if len(docs) == 1: yield doc elif "\n" in doc: yield "{}:".format(color.module(module)) yield doc else: yield "{}: {}".format(color.module(module), doc)
def source_(record, location=None, context=False): # type: (BaseModel, t.Optional[t.Text], bool) -> None import lxml.etree for rec in record: for rec_id in reversed(util.xml_ids(rec)): for definition in sources.xml_records[rec_id]: if location is not None and definition.module != location: continue elem = definition.elem.getroottree( ) if context else definition.elem print(sources.format_source(definition.to_source())) src = lxml.etree.tostring(elem, encoding="unicode") print(color.highlight(src, "xml"), end="\n\n")
def view_( self, view_type="form", # type: t.Text user=None, # type: t.Union[None, t.Text, int, odoo.models.ResUsers] view_id=None, # type: t.Union[None, t.Text, odoo.models.IrUiView, int] ): # type: (...) -> None """Build up and print a view.""" assert self._real is not None model = self._real if user is not None: # TODO: handle viewing as group model = util.with_user(model, _to_user(self._env, user)) View = model.env["ir.ui.view"] if isinstance(view_id, Text): view_id = cast("odoo.models.IrUiView", self._env.ref(view_id)) if isinstance(view_id, BaseModel): if view_id._name != "ir.ui.view": raise TypeError("view_id must be ir.ui.view") assert isinstance(view_id.id, int) view_id = view_id.id if view_id is None: view_id = View.default_view(model._name, view_type) if not view_id: raise RuntimeError("No {} view found for {}".format( view_type, model._name)) if odoo.release.version_info < (10, 0): form = View.read_combined(view_id)["arch"] else: form = View.browse(view_id).read_combined()["arch"] try: import lxml.etree except ImportError: pass else: form = lxml.etree.tostring( lxml.etree.fromstring( form, lxml.etree.XMLParser(remove_blank_text=True)), pretty_print=True, encoding="unicode", ).replace(" ", "\n") print(color.highlight(form, "xml"))
def source_(self, location=None): # type: (t.Optional[t.Text]) -> None assert self._real is not None first = True for cls in type(self._real).__bases__: name = getattr(cls, "_name", None) or getattr( cls, "_inherit", None) if location is not None and util.module(cls) != location: continue if location is None and name != self._real._name: continue if not first: print() else: first = False print(sources.format_source(sources.Source.from_cls(cls))) print(color.highlight(inspect.getsource(cls)))
def source_(self, location=None): # type: (t.Optional[t.Text]) -> None first = True for cls in type(self.model).__mro__[1:]: module = util.module(cls) if location is not None and location != module: continue if self.name in vars(cls): func = util.unpack_function(vars(cls)[self.name]) fname = sources.getsourcefile(func) lines, lnum = inspect.getsourcelines(func) if not first: print() else: first = False print( sources.format_source(sources.Source(module, fname, lnum))) print(color.highlight("".join(lines)))
def rule_repr(rule): # type: (odoo.models.IrRule) -> t.Text parts = [] parts.append(color.record_header(rule)) parts.append(color.display_name(rule.display_name)) groups = ", ".join( color.record(group.name) + util.xml_id_tag(group) for group in rule.groups) if not groups: parts.append( color.green.bold("Everyone") if rule["global"] else color.red. bold("No-one")) else: parts.append(groups) parts.append(_crud_format(rule)) if rule.domain_force not in { None, False, "[]", "[(1, '=', 1)]", '[(1, "=", 1)]' }: assert rule.domain_force parts.append( color.highlight(_domain_format(rule.env, rule.domain_force))) parts.extend(sources.format_sources(sources.find_source(rule))) return "\n".join(parts)
def addon_repr(addon): # type: (Addon) -> t.Text # TODO: A lot of the most interesting information is at the top so you have # to scroll up # Ideas: # - Put it at the bottom instead # - Don't show the README by default try: addon.manifest except RuntimeError: return repr(addon) defined_models = (addon._env["ir.model"].browse( addon._env["ir.model.data"].search([ ("model", "=", "ir.model"), ("module", "=", addon._module) ]).mapped("res_id")).mapped("model")) state = addon.record.state if (state == "installed" and addon.record.installed_version != addon.manifest.version): state += " (out of date)" if state == "installed": state = color.green.bold(state.capitalize()) elif not state: state = color.yellow.bold("???") elif state in ("uninstallable", "uninstalled"): state = color.red.bold(state.capitalize()) else: state = color.yellow.bold(state.capitalize()) description = addon.manifest.description if isinstance(addon.manifest.author, Text): author = addon.manifest.author else: author = ", ".join(addon.manifest.author) parts = [] parts.append("{} {} by {}".format(color.module(addon._module), addon.manifest.version, author)) parts.append(util.link_for_record(addon.record)) parts.append(addon.path) parts.append(state) parts.append(color.display_name(addon.manifest.name)) parts.append(addon.manifest.summary) def format_depends(pretext, modules): # type: (t.Text, odoo.models.IrModuleModule) -> None if modules: names = map(_color_state, sorted(modules, key=lambda mod: mod.name)) parts.append("{}: {}".format(pretext, ", ".join(names))) # TODO: Indirect dependencies are a bit noisy, when/how do we show them? direct, _indirect = addon._get_depends() format_depends("Depends", direct) # format_depends("Indirectly depends", indirect) r_direct, _r_indirect = addon._get_rdepends() format_depends("Dependents", r_direct) # format_depends("Indirect dependents", r_indirect) if defined_models: parts.append("Defines: {}".format(", ".join( map(color.model, defined_models)))) if description: parts.append("") # rst2ansi might be better here # (https://pypi.org/project/rst2ansi/) parts.append(color.highlight(description, "rst")) return "\n".join(parts)