diff --git a/server/__main__.py b/server/__main__.py index 8d45777c..4e82edcf 100644 --- a/server/__main__.py +++ b/server/__main__.py @@ -1,10 +1,10 @@ import argparse import logging -from .controller import odoo_server -from .constants import * +from server.controller import odoo_server +from server.constants import * -FORMAT = '(%(process)d) [%(levelname)s] %(message)s' +FORMAT = '%(asctime)s %(levelname)s: %(message)s' def add_arguments(parser): parser.description = "simple odoo server example" @@ -39,7 +39,7 @@ def main(): parser = argparse.ArgumentParser() add_arguments(parser) args = parser.parse_args() - logging.basicConfig(format=FORMAT, filename=args.log, level=logging.WARNING, filemode="w") + logging.basicConfig(format=FORMAT, datefmt='%Y-%m-%d %I:%M:%S', filename=args.log, level=logging.DEBUG, filemode="w") if "alpha" in EXTENSION_VERSION: logging.getLogger().setLevel(logging.DEBUG) diff --git a/server/controller.py b/server/controller.py index d7b0ad85..04a28cc1 100644 --- a/server/controller.py +++ b/server/controller.py @@ -47,6 +47,9 @@ def init(ls, params): ), ] )) + # TODO: launch_thread here only in the case of jupyterlab + odoo_server.launch_thread(target=Odoo.initialize, args=(ls,)) + @odoo_server.feature(SHUTDOWN) @send_error_on_traceback @@ -237,4 +240,4 @@ def on_change_config(config): ConfigurationItem( scope_uri='window', section="Odoo") - ]), callback=on_change_config) \ No newline at end of file + ]), callback=on_change_config) diff --git a/server/core/odoo.py b/server/core/odoo.py index 90fa1bd0..d58843e4 100644 --- a/server/core/odoo.py +++ b/server/core/odoo.py @@ -22,6 +22,57 @@ import time import tracemalloc +import logging + +log = logging.getLogger(__name__) + + +class Postgres(): + def __init__(self, db='postgres', autocommit=True, user=None, password=None, + host=None, port=None, as_dict=True, app=None, timeout=None): + self.conn = None + self.cr = None + + import psycopg2 + import psycopg2.extras + + connstring = "dbname=%s" % db + if host or port or user: + connstring += " host=%s" % (host or 'localhost') + if user: + connstring += " user=%s" % user + if port: + connstring += " port=%s" % port + if password: + connstring += " password=%s" % password + try: + self.conn = psycopg2.connect(connstring, application_name=app) + except TypeError: + # We still have to deal with old psycopg2 versions (eg: saas master) + self.conn = psycopg2.connect(connstring) + self.conn.autocommit = autocommit + if as_dict: + self.cr = self.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + else: + # kept as it's slightly better for performance + self.cr = self.conn.cursor() + if timeout: + self.cr.execute("SET statement_timeout TO %s", (timeout, )) + + def __enter__(self): + return self.cr + + def __exit__(self, exc_type, exc_value, exc_traceback): + self.close() + + def __del__(self): + self.close() + + def close(self): + if self.cr: + self.cr.close() + if self.conn: + self.conn.close() class Odoo(): @@ -93,7 +144,7 @@ def acquire_read(self, timeout=-1): return OdooLanguageServer.access_mode.set("read") yield Odoo.get() == self # to be sure Odoo.instance is still bound to the same instance - + self.thread_access_condition.release() OdooLanguageServer.access_mode.set("none") @@ -150,6 +201,15 @@ def initialize(ls:LanguageServer = None): Odoo.instance.grammar = parso.load_grammar() Odoo.instance.start_build_time = time.time() Odoo.instance.odooPath = odooConfig.odooPath + if hasattr(odooConfig, 'database') and os.environ.get('PGDATABASE'): + Odoo.instance.database = os.environ.get('PGDATABASE') + else: + Odoo.instance.database = False + if Odoo.instance.database: + with Postgres(Odoo.instance.database) as cr: + cr.execute("SELECT name FROM ir_module_module WHERE state = 'installed';") + Odoo.instance.installed_modules = [mod[0] for mod in cr.fetchall()] + if os.name == "nt": Odoo.instance.odooPath = Odoo.instance.odooPath[0].capitalize() + Odoo.instance.odooPath[1:] Odoo.instance.load_builtins(ls) @@ -372,6 +432,9 @@ def build_modules(self, ls): dirs = os.listdir(path) for dir in dirs: if os.path.isdir(os.path.join(path, dir)): + if Odoo.instance.database and dir not in Odoo.instance.installed_modules: + log.info('Module %s not installed, skipped', dir) + continue PythonArchBuilder(ls, addonsSymbol, os.path.join(path, dir)).load_arch(require_module=True) if self.stop_init: break diff --git a/server/odoo_language_server.py b/server/odoo_language_server.py index dec2132c..d45a3295 100644 --- a/server/odoo_language_server.py +++ b/server/odoo_language_server.py @@ -50,4 +50,4 @@ def set(instance): OdooLanguageServer.instance.set(instance) odoo_server = OdooLanguageServer() -OdooLanguageServer.set(odoo_server) \ No newline at end of file +OdooLanguageServer.set(odoo_server) diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..ca75f887 --- /dev/null +++ b/setup.py @@ -0,0 +1,16 @@ +import setuptools + + +setuptools.setup( + version='0.2.2', + name='odoo-language-server', + long_description_content_type='text/markdown', + packages=setuptools.find_packages(), + include_package_data=True, + install_requires=[ + 'lsprotocol', + 'pygls', + 'psycopg2', + ], + entry_points={'console_scripts': ['odoo-ls = server.__main__:main']}, +)