odoo_17.0.1/odoo/cli/shell.py

125 lines
3.9 KiB
Python
Raw Permalink Normal View History

# Part of Odoo. See LICENSE file for full copyright and licensing details.
import code
import logging
import os
import signal
import sys
from pathlib import Path
import odoo
from odoo.tools import config
from . import Command
_logger = logging.getLogger(__name__)
"""
Shell exit behaviors
====================
Legend:
stop = The REPL main loop stop.
raise = Exception raised.
loop = Stay in REPL.
Shell | ^D | exit() | quit() | sys.exit() | raise SystemExit()
----------------------------------------------------------------------
python | stop | raise | raise | raise | raise
ipython | stop | stop | stop | loop | loop
ptpython | stop | raise | raise | raise | raise
bpython | stop | stop | stop | stop | stop
"""
def raise_keyboard_interrupt(*a):
raise KeyboardInterrupt()
class Console(code.InteractiveConsole):
def __init__(self, locals=None, filename="<console>"):
code.InteractiveConsole.__init__(self, locals, filename)
try:
import readline
import rlcompleter
except ImportError:
print('readline or rlcompleter not available, autocomplete disabled.')
else:
readline.set_completer(rlcompleter.Completer(locals).complete)
readline.parse_and_bind("tab: complete")
class Shell(Command):
"""Start odoo in an interactive shell"""
supported_shells = ['ipython', 'ptpython', 'bpython', 'python']
def init(self, args):
config.parser.prog = f'{Path(sys.argv[0]).name} {self.name}'
config.parse_config(args)
odoo.cli.server.report_configuration()
odoo.service.server.start(preload=[], stop=True)
signal.signal(signal.SIGINT, raise_keyboard_interrupt)
def console(self, local_vars):
if not os.isatty(sys.stdin.fileno()):
local_vars['__name__'] = '__main__'
exec(sys.stdin.read(), local_vars)
else:
if 'env' not in local_vars:
print('No environment set, use `%s shell -d dbname` to get one.' % sys.argv[0])
for i in sorted(local_vars):
print('%s: %s' % (i, local_vars[i]))
preferred_interface = config.options.get('shell_interface')
if preferred_interface:
shells_to_try = [preferred_interface, 'python']
else:
shells_to_try = self.supported_shells
for shell in shells_to_try:
try:
return getattr(self, shell)(local_vars)
except ImportError:
pass
except Exception:
_logger.warning("Could not start '%s' shell." % shell)
_logger.debug("Shell error:", exc_info=True)
def ipython(self, local_vars):
from IPython import start_ipython
start_ipython(argv=[], user_ns=local_vars)
def ptpython(self, local_vars):
from ptpython.repl import embed
embed({}, local_vars)
def bpython(self, local_vars):
from bpython import embed
embed(local_vars)
def python(self, local_vars):
Console(locals=local_vars).interact()
def shell(self, dbname):
local_vars = {
'openerp': odoo,
'odoo': odoo,
}
if dbname:
registry = odoo.registry(dbname)
with registry.cursor() as cr:
uid = odoo.SUPERUSER_ID
ctx = odoo.api.Environment(cr, uid, {})['res.users'].context_get()
env = odoo.api.Environment(cr, uid, ctx)
local_vars['env'] = env
local_vars['self'] = env.user
self.console(local_vars)
cr.rollback()
else:
self.console(local_vars)
def run(self, args):
self.init(args)
self.shell(config['db_name'])
return 0