-
-
Notifications
You must be signed in to change notification settings - Fork 193
/
utils.py
137 lines (104 loc) · 4.83 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Copyright 2021 Camptocamp SA (http://www.camptocamp.com)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
# @author Simone Orsi <[email protected]>
import logging
import os
from functools import wraps
from odoo.modules.module import get_manifest
from odoo.tools.config import config as odoo_config
from odoo.addons.base_rest.controllers.main import _PseudoCollection
from odoo.addons.component.core import WorkContext, _component_databases
_logger = logging.getLogger(__name__)
def ensure_model(model_name):
"""Decorator to ensure data method is called w/ the right recordset."""
def _ensure_model(func):
@wraps(func)
def wrapped(*args, **kwargs):
# 1st arg is `self`
record = args[1]
if record is not None:
assert (
record._name == model_name
), f"Expected model: {model_name}. Got: {record._name}"
return func(*args, **kwargs)
return wrapped
return _ensure_model
APP_VERSIONS = {}
def get_version(module_name, module_path=None):
"""Return module version straight from manifest."""
global APP_VERSIONS
if APP_VERSIONS.get(module_name):
return APP_VERSIONS[module_name]
try:
info = get_manifest(module_name, mod_path=module_path)
APP_VERSIONS[module_name] = info["version"]
return APP_VERSIONS[module_name]
except Exception:
return "dev"
APP_VERSION = get_version("shopfloor_mobile_base")
def _get_running_env():
"""Retrieve current system environment.
Expected key `RUNNING_ENV` is compliant w/ `server_environment` naming
but is not depending on it.
Additionally, as specific key for Shopfloor is supported.
You don't need `server_environment` module to have this feature.
"""
for key in ("SHOPFLOOR_RUNNING_ENV", "RUNNING_ENV"):
if os.getenv(key):
return os.getenv(key)
if odoo_config.options.get(key.lower()):
return odoo_config.get(key.lower())
return "prod"
RUNNING_ENV = _get_running_env()
def register_new_services(env, *component_classes, apps=None):
"""Enforce registration of new services straight from their classes.
At some stage (eg: a post install hook) the component registry
might not be fully loaded and the components might be not fully "ready".
For this reason, not all the inherited properties
are granted to be available (eg: _collection)
and they won't be available for `components_registry.lookup` call.
This is why, to ensure that the new services endpoints
are registered in any case we prepare their classes "manually" here
and pass them over to sf.app._get_services.
In this way, if their endpoint_route rows are not there
they will be generated on the fly,
Please, note that this func is very low level
and must be used only in particular situations (such as install hooks).
"""
if odoo_config["test_enable"]:
# When installing modules for tests, there's nothing to do.
# Moreover, it can lead to weird service behavior
# because the classes will be decorated
# but when they are not fully ready.
return
components = load_components_without_registry(env, *component_classes)
if not components:
return
apps = apps or env["shopfloor.app"].search([])
apps.with_context(sf_service_components=components)._register_controllers()
def load_components_without_registry(env, *component_classes):
"""Prepare components' instances w/o real registry lookup."""
collection = _PseudoCollection("shopfloor.app", env)
rest_service = env["rest.service.registration"]
if not _component_databases.get(env.cr.dbname):
# no registry ready yet (eg: install via cmd line, tests, etc)
_logger.info("component registry not ready yet")
return []
work = WorkContext(model_name=rest_service._name, collection=collection)
return [comp(work) for comp in component_classes]
def purge_endpoints(env, service_usage, endpoint=None):
"""Remove stale services' endpoints routes.
When scenario are removed (eg: module uninstalled)
their routes must be cleaned up.
You can use this function to easily clean them for all apps.
Motivation: registered routes for a given app are taken
from the endpoint_route table via `route_group`.
As the table is populated dynamically with registered components
when a component is removed there's no direct update to the table.
Hence, is the responsibility of the dev to take care of the cleanup.
"""
apps = env["shopfloor.app"].search([])
for app in apps:
route = app.api_url_for_service(service_usage, endpoint=endpoint)
route = route + ("/" if not endpoint else "")
env.cr.execute("DELETE FROM endpoint_route WHERE route like %s", (f"{route}%",))