def from_cls(cls, src_cls): # type: (t.Type[BaseModel]) -> Source return cls( util.module(src_cls), getsourcefile(src_cls), inspect.getsourcelines(src_cls)[1], )
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)))
def find_method_source(method): # type: (odoo_repl.methods.MethodProxy) -> t.List[Source] res = [] for cls in type(method.model).__mro__[1:]: if method.name in vars(cls): func = util.unpack_function(vars(cls)[method.name]) res.append( Source( util.module(cls), getsourcefile(func), inspect.getsourcelines(func)[1], ) ) return res
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 find_field_source(field): # type: (Field) -> t.List[Source] res = [] for cls in type(util.env[field.model_name]).__mro__: if field.name in getattr(cls, "_columns", ()) or field.name in vars(cls): if cls.__module__ in {"odoo.api", "openerp.api"}: continue fname = getsourcefile(cls) lines, lnum = inspect.getsourcelines(cls) for line in lines: match = RE_FIELD.match(line) if match and match.group(1) == field.name: break lnum += 1 else: lnum = None # type: ignore res.append(Source(util.module(cls), fname, lnum)) return res
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 _get_method_docs(model, name): # type: (BaseModel, str) -> t.Iterable[t.Tuple[str, t.Text]] return sources.find_docs((util.module(cls), vars(cls)[name]) for cls in type(model).__mro__ if name in vars(cls))
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)