def _all_ids_(self): # type: () -> t.List[int] """Get all record IDs in the database.""" self._ensure_real() return util.sql( self._env, "SELECT id FROM {}".format(self._env[self._path]._table))
def __dir__(self): # type: () -> t.List[t.Text] if self._model not in self._env.registry: raise TypeError("Model '{}' is not installed".format(self._model)) listing = [u"_model", u"_field", u"_listing", u"_abbrev", u"fzf_"] listing.extend(filter(util.is_name, util.sql(self._env, self._listing))) return listing
def fzf_(self): # type: () -> t.Optional[BaseModel] all_ids = util.sql(self._env, "SELECT module || '.' || name FROM ir_model_data") res = fzf.fzf_single(all_ids) if not res: return None return self._env.ref(res)
def __getattr__(self, attr): # type: (t.Text) -> Addon if not util.sql(self._env, "SELECT name FROM ir_module_module WHERE name = %s", attr): raise AttributeError("No module '{}'".format(attr)) addon = Addon(self._env, attr) setattr(self, attr, addon) return addon
def do_sql(self, arg): # type: (str) -> None if self.env is None: raise TypeError("Uninitialized debugger") try: pprint.pprint(util.sql(self.env, arg)) except Exception as err: # TODO: this might also be printed by the logging print(err)
def __getitem__(self, ind): # type: (t.Union[t.Iterable[int], t.Text, int, slice]) -> t.Any if self._real is None: raise KeyError("Model '{}' does not exist".format(self._path)) if not ind: return self._real ignore_missing = False if isinstance(ind, slice) or isinstance(ind, int) and ind < 0: max_id = util.sql( self._env, 'SELECT id FROM "{}" ORDER BY id DESC LIMIT 1'.format( self._real._table), )[0] ind = range(max_id + 1)[ind] ignore_missing = True if isinstance(ind, Text): if ind in self._real._fields: return fields.FieldProxy(self._env, self._real._fields[ind]) thing = getattr(self._real, ind) if callable(thing): return methods.MethodProxy(thing, self._real, ind) return thing if isinstance(ind, abc.Iterable): assert not isinstance(ind, Text) ind = tuple(ind) if not isinstance(ind, tuple): ind = (ind, ) # Browsing a non-existent record can cause weird caching problems, so # check first real_ind = set( util.sql( self._env, 'SELECT id FROM "{}" WHERE id IN %s'.format(self._real._table), ind, )) missing = set(ind) - real_ind if missing: if ignore_missing: ind = sorted(real_ind) else: raise KeyError("Records {} do not exist".format(", ".join( map(str, missing)))) return self._real.browse(ind)
def __getattr__(self, attr): # type: (t.Text) -> DataModuleBrowser if not util.sql( self._env, "SELECT id FROM ir_model_data WHERE module = %s LIMIT 1", attr): raise AttributeError("No module '{}'".format(attr)) browser = DataModuleBrowser(self._env, attr) setattr(self, attr, browser) return browser
def __getitem__(self, key): # type: (t.Text) -> BaseModel try: return self._env.ref("{}.{}".format(self._module, key)) except ValueError as err: raise KeyError(err) except AttributeError as err: if err.args == ("environments", ) and not key.startswith("_"): # Threading issue, try to keep autocomplete working # See RecordBrowser.__getattr__ model = util.sql( self._env, "SELECT model FROM ir_model_data WHERE module = %s AND name = %s", self._module, key, ) # type: t.List[str] return self._env[model[0]] raise
def search( model, # type: BaseModel args, # type: t.Sequence[object] field_vals, # type: t.Dict[str, t.Any] ): # type: (...) -> BaseModel # if count=True, this returns an int, but that may not be worth annotating # TODO: # - inspect fields # - handle 2many relations offset = field_vals.pop("offset", 0) # type: int limit = field_vals.pop("limit", None) # type: t.Optional[int] order = field_vals.pop("order", "id") # type: t.Optional[t.Text] count = field_vals.pop("count", False) # type: bool shuf = field_vals.pop("shuf", None) # type: t.Optional[int] if not field_vals.pop("active_test", True): model = model.with_context(active_test=False) if shuf and not (args or field_vals or offset or limit or count): # Doing a search seeds the cache with IDs, which tanks performance # Odoo will compute fields on many records at once even though you # won't use them query = "SELECT id FROM {}".format(model._table) if "active" in model._fields and not model._fields["active"].related: # TODO: handle related active fields query += " WHERE active = true" all_ids = util.sql(model.env, query) shuf = min(shuf, len(all_ids)) return model.browse(random.sample(all_ids, shuf)) clauses = _parse_search_query(args, field_vals, model) result = model.search(clauses, offset=offset, limit=limit, order=order, count=count) if shuf: shuf = min(shuf, len(result)) return result.browse(random.sample(result._ids, shuf)) return result
def grep_(*args, **kwargs): # type: (object, object) -> None """grep through all installed addons. See help(odoo_repl.grep) for more information. """ argv = grep.build_grep_argv(args, kwargs, recursive=True) mods = util.sql( env, "SELECT name FROM ir_module_module WHERE state = 'installed'", ) paths = [ odoo.modules.module.get_module_path(mod, display_warning=False) for mod in mods # The `base` module is typically included inside the odoo module # and we don't want to search it twice # A more principled way to filter it out would be to check all # addons for being a subdirectory of `odoo` if mod != "base" ] paths.append(os.path.dirname(odoo.__file__)) argv.extend(os.path.realpath(path) for path in paths if path) subprocess.Popen(argv).wait()
def create_namespace( db, # type: t.Union[None, t.Text, odoo.sql_db.Cursor, odoo.api.Environment] ): # type: (...) -> t.Tuple[odoo.api.Environment, t.Dict[str, t.Any]] global xml_thread if not hasattr(odoo, "tools"): raise RuntimeError( "Odoo is not imported. You should run this from an Odoo shell.") if db is None or isinstance(db, Text): db_name = db or odoo.tools.config["db_name"] if not db_name: raise ValueError( "Can't determine database name. Run with `-- -d dbname` " "or pass it as the first argument to odoo_repl.enable().") cursor = odoo.sql_db.db_connect(db_name).cursor() atexit.register(cursor.close) if not hasattr(odoo.api.Environment._local, "environments"): odoo.api.Environment._local.environments = odoo.api.Environments() env = odoo.api.Environment(cursor, odoo.SUPERUSER_ID, {}) elif isinstance(db, odoo.sql_db.Cursor): env = odoo.api.Environment(db, odoo.SUPERUSER_ID, {}) elif isinstance(db, odoo.api.Environment): env = db else: raise TypeError(db) envproxy = EnvProxy(env) util.env = env def grep_(*args, **kwargs): # type: (object, object) -> None """grep through all installed addons. See help(odoo_repl.grep) for more information. """ argv = grep.build_grep_argv(args, kwargs, recursive=True) mods = util.sql( env, "SELECT name FROM ir_module_module WHERE state = 'installed'", ) paths = [ odoo.modules.module.get_module_path(mod, display_warning=False) for mod in mods # The `base` module is typically included inside the odoo module # and we don't want to search it twice # A more principled way to filter it out would be to check all # addons for being a subdirectory of `odoo` if mod != "base" ] paths.append(os.path.dirname(odoo.__file__)) argv.extend(os.path.realpath(path) for path in paths if path) subprocess.Popen(argv).wait() def translate(text): # type: (t.Text) -> None translations = env["ir.translation"].search( ["|", ("src", "=", text), ("value", "=", text)]) if not translations: text = "%" + text + "%" translations = env["ir.translation"].search( ["|", ("src", "ilike", text), ("value", "ilike", text)]) odoo_print(translations) def open_(): # type: () -> None util.open_browser(util.generate_url()) namespace = { "self": env.user, "odoo": odoo, "openerp": odoo, "sql": functools.partial(util.sql, env), "grep_": grep_, "open_": open_, "translate": translate, "env": envproxy, "u": shorthand.UserBrowser(env), "emp": shorthand.EmployeeBrowser(env), "ref": shorthand.DataBrowser(env), "addons": addons.AddonBrowser(env), } # type: t.Dict[str, t.Any] namespace.update({ part: models.ModelProxy(env, part) for part in envproxy._base_parts() if not hasattr(builtins, part) }) if not sources.xml_records: modules = util.sql( env, "SELECT name, demo FROM ir_module_module WHERE state = 'installed'", ) xml_thread = threading.Thread( target=lambda: sources.populate_xml_records(modules)) xml_thread.daemon = True xml_thread.start() return env, namespace
def __iter__(self): # type: () -> t.Iterator[Addon] for name in util.sql(self._env, "SELECT name FROM ir_module_module"): yield Addon(self._env, name)
def __dir__(self): # type: () -> t.List[t.Text] return util.sql(self._env, "SELECT name FROM ir_module_module")
def _ipython_key_completions_(self): # type: () -> t.List[t.Text] if self._model not in self._env.registry: raise TypeError("Model '{}' is not installed".format(self._model)) return util.sql(self._env, self._listing)
def __dir__(self): # type: () -> t.List[t.Text] return util.sql(self._env, "SELECT name FROM ir_model_data WHERE module = %s", self._module)
def __dir__(self): # type: () -> t.List[t.Text] return util.sql(self._env, "SELECT DISTINCT module FROM ir_model_data")