Ejemplo n.º 1
0
def format_source(source):
    # type: (Source) -> t.Text
    module, fname, lnum = source
    if config.clickable_filenames:
        # This can also be written as file://{hostname}/{fname}.
        # But specifying the hostname is not terribly useful, and it breaks
        # some things (e.g. curl, though curling a local file is silly anyway.)
        fname = color.linkify(fname, "file://" + fname)
    if lnum is not None:
        return "{}: {}:{}".format(color.module(module), fname, lnum)
    else:
        return "{}: {}".format(color.module(module), fname)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
def _color_state(module):
    # type: (odoo.models.IrModuleModule) -> t.Text
    if module.state == "installed":
        return color.module(module.name)
    elif module.state in ("uninstalled", "uninstallable"):
        return color.red.bold(module.name)
    else:
        return color.yellow.bold(module.name)
Ejemplo n.º 4
0
def gitsource(thing):
    # type: (sources.Sourceable) -> None
    for source in sources.find_source(thing):
        try:
            fmt = format_source(source)
        except GitSourceError as exc:
            fmt = "{}: {}".format(color.module(source.module),
                                  color.missing(str(exc)))
        print(fmt)
Ejemplo n.º 5
0
def format_source(source):
    # type: (sources.Source) -> t.Text
    module, fname, lnum = source
    fname = to_url(fname)
    if lnum is not None:
        fname += "#L{}".format(lnum)
    if config.clickable_filenames:
        fname = color.linkify(fname, fname)
    return "{}: {}".format(color.module(module), fname)
Ejemplo n.º 6
0
 def methods_(self):
     # type: () -> None
     self._ensure_real()
     for cls in type(self._real).__bases__:
         meths = [(name, attr) for name, attr in sorted(vars(cls).items())
                  if util.loosely_callable(attr) if name != "pool"]
         if meths:
             print()
             print(color.module(util.module(cls)))
             for name, meth in meths:
                 print(
                     color.method(name) +
                     methods._func_signature(util.unpack_function(meth)))
Ejemplo n.º 7
0
def model_repr(obj):
    # type: (t.Union[ModelProxy, BaseModel]) -> t.Text
    """Summarize a model's fields."""
    if isinstance(obj, ModelProxy) and obj._real is None:
        return repr(obj)
    obj = util.unwrap(obj)

    field_names = []
    delegated = []
    for field in sorted(obj._fields):
        if field in FIELD_BLACKLIST:
            continue
        if getattr(obj._fields[field], "related", False):
            delegated.append(obj._fields[field])
            continue
        field_names.append(field)
    max_len = max(len(f) for f in field_names) if field_names else 0
    parts = []

    original_module = obj._module
    for parent in type(obj).__bases__:
        if getattr(parent, "_name", None) == obj._name:
            original_module = getattr(parent, "_module", original_module)

    parts.append(color.header(obj._name))
    if obj._transient:
        parts[-1] += " (transient)"
    if getattr(obj, "_abstract", False):
        parts[-1] += " (abstract)"
    elif not obj._auto:
        parts[-1] += " (no automatic table)"
    if getattr(obj, "_description", False) and obj._description != obj._name:
        parts.append(color.display_name(obj._description))
    if getattr(obj, "_inherits", False):
        for model_name, field_name in obj._inherits.items():
            parts.append("Inherits from {} through {}".format(
                color.model(model_name), color.field(field_name)))
    inherits = _find_inheritance(obj)
    if inherits:
        # Giving this a very similar message to the one for _inherits feels dirty
        # But then _inherit is already very similar to _inherits so maybe it's ok
        parts.append("Inherits from {}".format(", ".join(
            color.model(inherit) for inherit in sorted(inherits))))
    docs = list(
        sources.find_docs((util.module(cls), cls)
                          for cls in type(obj).__bases__
                          if getattr(cls, "_name", obj._name) == obj._name))
    parts.extend(sources.format_docs(docs))

    src = sources.find_source(obj)

    by_module = collections.defaultdict(list)
    for field in field_names:
        f_obj = obj._fields[field]
        rep = format_single_field(f_obj, max_len=max_len)
        f_module = sources.find_field_module(f_obj) or original_module
        by_module[f_module].append(rep)

    ordered_modules = [original_module]
    for src_item in reversed(src):
        if src_item.module not in ordered_modules:
            ordered_modules.append(src_item.module)
    for module in by_module:
        if module not in ordered_modules:
            ordered_modules.append(module)

    for module in ordered_modules:
        if module not in by_module:
            continue
        parts.append("")
        parts.append("{}:".format(color.module(module)))
        parts.extend(by_module[module])

    if delegated:
        buckets = collections.defaultdict(
            list)  # type: t.DefaultDict[t.Tuple[t.Text, ...], t.List[t.Text]]
        for f_obj in delegated:
            assert f_obj.related
            buckets[tuple(f_obj.related[:-1])].append(
                color.field(f_obj.name) if f_obj.related[-1] == f_obj.name else
                "{} (.{})".format(color.field(f_obj.name), f_obj.related[-1]))
        parts.append("")
        for related_field, field_names in buckets.items():
            # TODO: figure out name of model of real field
            parts.append("Delegated to {}: {}".format(
                color.yellow.bold(".".join(related_field)),
                ", ".join(field_names)))
    parts.append("")
    parts.extend(sources.format_sources(src))
    return "\n".join(parts)
Ejemplo n.º 8
0
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)