gOdoo-cli 0.1.6__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/PKG-INFO +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/pyproject.toml +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/setup.py +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/__init__.py +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/cli.py +7 -3
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/__init__.py +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/bootstrap.py +3 -52
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/launch.py +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/shell.py +1 -1
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/source_get.py +65 -21
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/git/zip_download.py +1 -1
- godoo_cli-0.2.0/src/godoo_cli/helpers/__init__.py +1 -0
- godoo_cli-0.2.0/src/godoo_cli/helpers/bootstrap.py +58 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/helpers/odoo_files.py +43 -10
- godoo_cli-0.1.6/src/godoo_cli/helpers/__init__.py → godoo_cli-0.2.0/src/godoo_cli/helpers/system.py +1 -3
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/LICENSE +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/README.md +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/__main__.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/makedev.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/rpc/__init__.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/rpc/cli.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/rpc/cli_callbacks.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/rpc/importer.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/rpc/modules.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/rpc/translations.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/commands/test.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/git/__init__.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/git/git_odoo.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/git/git_odoo_addons.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/git/git_repo.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/git/git_url.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/helpers/cli.py +0 -0
- {godoo_cli-0.1.6 → godoo_cli-0.2.0}/src/godoo_cli/helpers/odoo_manifest.py +0 -0
|
@@ -40,7 +40,7 @@ entry_points = \
|
|
|
40
40
|
|
|
41
41
|
setup_kwargs = {
|
|
42
42
|
'name': 'godoo-cli',
|
|
43
|
-
'version': '0.
|
|
43
|
+
'version': '0.2.0',
|
|
44
44
|
'description': 'Wrapper around Odoo-Bin with some convinience RPC functions.',
|
|
45
45
|
'long_description': '# gOdoo Dev Environment\n\n\n\n\n[<img src="https://raw.githubusercontent.com/OpenJKSoftware/gOdoo/main/assets/godoo-main-cli.png" width="1000"/>](image.png)\n\n**gOdoo** is short for **go Odoo**. \\\nIt is a [Vscode Devcontainer](https://code.visualstudio.com/docs/remote/containers) Environment for [Odoo](https://odoo.com/)\nwith Python CLI `godoo` convenience wrapper around `odoo-bin`.\n\nThis repository is the base source for the Python package [godoo-cli](https://pypi.org/project/godoo-cli/) and serves as\nan all batteries included development environment.\n\nMade Possible by: [WEMPE Elektronic GmbH](https://wetech.de)\n\n# gOdoo-cli\n\nPython package that provides `godoo` command line interface around `odoo-bin`.\n\nIt\'s build with [Typer](https://github.com/tiangolo/typer) to provide some convenience Wrappers for Odoo development and\nDeployment.\n\nMost flags can be configured by Env variables. \\\nUse `godoo --help` to find out more. HINT: Install tab-completion with `godoo --install-completion`\n\n# Docker\n\nThis workspace also contains Docker and Docker-Compose files. \\\n\nThey are used to provide either easy Odoo instances where the source is pulled according to\n[ODOO_MANIFEST.yml](./ODOO_MANIFEST.yml), or as a all batteries included devcontainer for VScode.\n\n## Requirements\n\n- [Docker Compose](https://github.com/docker/compose)\n- [Traefik](https://doc.traefik.io/traefik/) container running with docker provider and "traefik" named docker network.\n Example: [Traefik Devproxy](https://github.com/joshkreud/traefik_devproxy)\n- SSH Agent running. (check `echo $SSH_AUTH_SOCK`)\\\n This gets passed trough in the Buildprocess to clone Thirdparty repos.\n\n## Just wanna have a quick and easy Odoo Instance?\n\n```bash\ngit clone https://github.com/OpenJKSoftware/gOdoo\ncd godoo\n. scripts/container_requirements.sh # Check Requirements\ndocker-compose build\ndocker-compose up\n# wait......\n# wait a bit mode ...\n# just a little bit longer ..\n# There we go.\n# Odoo should be reachable on \'https://godoo.docker.localhost\' assuming you didn\'t change .env TRAEFIK_HOST_RULE or COMPOSE_PROJECT_NAME\n```\n\n# Devcontainer\n\n## Features\n\n- All batteries included [Devcontainer](https://code.visualstudio.com/docs/remote/containers) with postgres service\n Container and local DNS resolvig managed by [Traefik](https://doc.traefik.io/traefik/).\n- Easy fully working Odoo instance by `docker-compose up` with https access.\n- `godoo` CLI wrapper around Odoo. (Most flags can be configured by Environment Variables and are already preconfigured\n in the Containers. See [.env.sample](./.env.sample))\n- `odoo-bin` is added to PATH and can thus be invoked from every folder.\n- Odoo will run in Proxy_Mode behind a Traefik reverse proxy for easy access on\n `https://$COMPOSE_PROJECT_NAME.docker.localhost`\n- [Odoo Pylint plugin](https://github.com/OCA/pylint-odoo) preconfigured in vscode\n- Preinstalled vscode Extensions Highlights:\n - [SQL Tools](https://marketplace.visualstudio.com/items?itemName=mtxr.sqltools) with preconfigured connection for\n easy Database access in the Sidebar.\n - [Docker Extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) controls\n container host.\n - [Odoo Snippets](https://marketplace.visualstudio.com/items?itemName=mstuttgart.odoo-snippets)\n - [Odoo Developments](https://marketplace.visualstudio.com/items?itemName=scapigliato.vsc-odoo-development) can Grab\n Odoo Model information from a running Server\n - [Todo Tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree)\n\n## Usage\n\n1. For Docker on windows: Clone the repo into the WSL2 Filesystem for better IO performance\n2. Have [Traefik](https://github.com/traefik/traefik) Running on `docker.localhost`\n [Example](https://github.com/joshkreud/traefik_devproxy) \\\n There must be a Docker network called `traefik` that can reach traefik.\n3. Open Devcontianer:\n - If you have the Devcontainer CLI: `devcontainer open .`\n - If not open the workspace in Local Vscode. In the Command pallete search for `Reopen in container`\n4. From **within the container** start Odoo using one of the following commands:\n - You can enable godoo tab-completion by `godoo --install-completion`\n - `make` -> Loads Odoo + Workspace Addons\n - `make bare` -> Loads Odoo with ony `web` installed.\n - `make kill` -> Search for `odoo-bin` processes and kill them\n - `make reset` -> Drops DB, deletes config file and datafolder\n - The full init script is available via "`godoo`". (See --help for Options)\n5. Open Odoo `https://$COMPOSE_PROJECT_NAME.docker.localhost`\\\n For example `COMPOSE_PROJECT_NAME=godoo` --> [https://godoo.docker.localhost](https://godoo.docker.localhost)\n6. Login with `admin:admin`\n7. Profit!\n\n### Access to Odoo and Thirdparty addon Source\n\nYou can access the Odoo source by opening the VsCode workspace [full.code-workspace](full.code-workspace) from within\nthe Container. This will open a [Multi-Root Workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces).\nReally waiting for https://github.com/microsoft/vscode-remote-release/issues/3665 here.\n\n## Reset Devcontainer Data\n\nWhen you screwed up so bad its time to just start Over godoo has you covered:\n\n### Automatic Reset\n\nThere are 3 Options to reset the Dev Env.\n\n1. From **Outside** the Container run `make reset` in the project root to delete docker volumes and restart the\n container. (Vscode will prompt to reconnect if still open)\n2. From **Outside** the Container run `make reset-hard` in the project root to force rebuild the main Odoo container and\n then do the same as `make reset`\n3. From **Inside** the Container run `make reset` to drop the DB and delete varlib and the bootstrap flag, which is way\n quicker than the other options.\n\n### Manual Reset\n\n1. Close vscode\n2. Remove `app` and `db` container from docker.\n3. Remove volumes: `db, odoo_thirdparty, odoo_web, vscode_extensions`\n4. Restart Devcontainer\n\n## Python Debugging\n\n### VsCode Debugging\n\nDebugging doesn\'t reliably work with\n[Odoo Multiprocess](https://www.odoo.com/documentation/14.0/developer/misc/other/cmdline.html#multiprocessing) mode\nenabled. \\\nThe container ships with a Vscode Debug profile, that sets `--workers 0` to allow for Debugging Breakpoints. See [.vscode/launch.json](./.vscode/launch.json)\n\n### Interactive Shell\n\nUse `godoo shell` to enter an interactive shell on the Database.\n\n# Odoo Modules\n\n## Third Party Modules (manifest.yml)\n\nThe `godoo` bootstrap function, will download some modules using git. \\\nWhich Repos to download is specified in `ODOO_MANIFEST.yml` ([Default](./ODOO_MANIFEST.yml)) \\\nNot all of the cloned addons are automatically installed. \\\nInstall them via the Apps Page in Odoo using `godoo rpc modules install` or using `odoo-bin`.\\\nModules downloaded on the Odoo Marketplace can be dropped as a `.zip` archive in [./thirdparty](./thirdparty)\n',
|
|
46
46
|
'author': 'Joshua Kreuder',
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.2.0"
|
|
2
2
|
from .cli import launch_cli
|
|
@@ -9,6 +9,7 @@ from .commands import (
|
|
|
9
9
|
bootstrap_odoo,
|
|
10
10
|
get_source,
|
|
11
11
|
get_source_file,
|
|
12
|
+
install_module_dependencies,
|
|
12
13
|
launch_odoo,
|
|
13
14
|
makedec_cli_app,
|
|
14
15
|
odoo_shell,
|
|
@@ -16,7 +17,7 @@ from .commands import (
|
|
|
16
17
|
rpc_cli_app,
|
|
17
18
|
uninstall_modules,
|
|
18
19
|
)
|
|
19
|
-
from .helpers import set_logging
|
|
20
|
+
from .helpers.system import set_logging
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def main_callback(
|
|
@@ -65,8 +66,11 @@ def main_cli():
|
|
|
65
66
|
# Normal Subcommands
|
|
66
67
|
app.command("launch", help="Launch Odoo, Bootstrap if bootstrapflag is not present")(launch_odoo)
|
|
67
68
|
app.command("bootstrap", help="Bootstrap Odoo")(bootstrap_odoo)
|
|
68
|
-
app.command("get-
|
|
69
|
-
app.command("get-
|
|
69
|
+
app.command("source-get-file", help="Get Raw file from odoo git remote or specific git remote.")(get_source_file)
|
|
70
|
+
app.command("source-get-depends", help="Install dependencies from __manifest__.py in specified modules")(
|
|
71
|
+
install_module_dependencies
|
|
72
|
+
)
|
|
73
|
+
app.command("source-get", help="Download/Unzip Odoo Source and thirdparty addons.")(get_source)
|
|
70
74
|
app.command("test", help="Bootstrap or Launch odoo in Testing Mode")(odoo_test)
|
|
71
75
|
app.command("shell", help="Shell into Odoo")(odoo_shell)
|
|
72
76
|
app.command("uninstall", help="Uninstall Modules")(uninstall_modules)
|
|
@@ -3,5 +3,5 @@ from .launch import launch_odoo
|
|
|
3
3
|
from .makedev import makedec_cli_app
|
|
4
4
|
from .rpc import rpc_cli_app
|
|
5
5
|
from .shell import odoo_shell, uninstall_modules
|
|
6
|
-
from .source_get import get_source, get_source_file
|
|
6
|
+
from .source_get import get_source, get_source_file, install_module_dependencies
|
|
7
7
|
from .test import odoo_test
|
|
@@ -1,67 +1,19 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import re
|
|
3
|
-
import subprocess
|
|
4
|
-
from ast import literal_eval
|
|
5
3
|
from pathlib import Path
|
|
6
4
|
from typing import List
|
|
7
5
|
|
|
8
6
|
import typer
|
|
9
7
|
|
|
10
|
-
from ..helpers import
|
|
8
|
+
from ..helpers.bootstrap import _install_py_reqs_by_odoo_cmd
|
|
11
9
|
from ..helpers.cli import typer_retuner, typer_unpacker
|
|
12
|
-
from ..helpers.odoo_files import
|
|
10
|
+
from ..helpers.odoo_files import get_addon_paths, get_odoo_module_paths
|
|
11
|
+
from ..helpers.system import run_cmd
|
|
13
12
|
from .source_get import get_source
|
|
14
13
|
|
|
15
14
|
LOGGER = logging.getLogger(__name__)
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
def _install_py_reqs_for_modules(addon_paths: List[Path], module_names: List[str] = None):
|
|
19
|
-
"""Install Python Requirements mentioned in odoo module manifests of given modules
|
|
20
|
-
|
|
21
|
-
Parameters
|
|
22
|
-
----------
|
|
23
|
-
addon_paths : List[Path]
|
|
24
|
-
odoo-bin addons path
|
|
25
|
-
module_names : List[str], Optional
|
|
26
|
-
List of modules to filter for, by default "all available modules"
|
|
27
|
-
|
|
28
|
-
Returns
|
|
29
|
-
-------
|
|
30
|
-
CompletedProcess
|
|
31
|
-
"""
|
|
32
|
-
py_reqs = _get_python_requirements_of_modules(addon_paths=addon_paths, filter_module_names=module_names)
|
|
33
|
-
if py_reqs:
|
|
34
|
-
installed_packages = run_cmd(
|
|
35
|
-
"pip list --format json --disable-pip-version-check", check=True, shell=True, stdout=subprocess.PIPE
|
|
36
|
-
).stdout.decode("utf-8")
|
|
37
|
-
installed_packages = [m.get("name") for m in literal_eval(installed_packages)]
|
|
38
|
-
if missing_packages := [p for p in py_reqs if p not in installed_packages]:
|
|
39
|
-
LOGGER.info("Installing Python requirements: '%s'", ", ".join(missing_packages))
|
|
40
|
-
return run_cmd(f"pip install {' '.join(missing_packages)} --disable-pip-version-check", shell=True)
|
|
41
|
-
LOGGER.debug("No py Requirements to be installed")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _install_py_reqs_by_odoo_cmd(addon_paths: List[Path], odoo_bin_cmd: str):
|
|
45
|
-
"""Install Python reqs for modules mentioned in odoo-bin commandline --init or -i directives.
|
|
46
|
-
|
|
47
|
-
Parameters
|
|
48
|
-
----------
|
|
49
|
-
addon_paths : List[Path]
|
|
50
|
-
odoo-bin addons-path
|
|
51
|
-
odoo_bin_cmd : str
|
|
52
|
-
odoo-bin commandline
|
|
53
|
-
|
|
54
|
-
Returns
|
|
55
|
-
-------
|
|
56
|
-
CompletedProcess
|
|
57
|
-
"""
|
|
58
|
-
install_modules = []
|
|
59
|
-
for m in re.finditer(r'(--init|-i) "?([^ \n]+)"?', odoo_bin_cmd):
|
|
60
|
-
install_modules += m.group(2).split(",")
|
|
61
|
-
if install_modules:
|
|
62
|
-
return _install_py_reqs_for_modules(addon_paths=addon_paths, module_names=install_modules)
|
|
63
|
-
|
|
64
|
-
|
|
65
17
|
def _boostrap_command(
|
|
66
18
|
odoo_main_path: Path,
|
|
67
19
|
odoo_conf_path: Path,
|
|
@@ -202,7 +154,6 @@ def bootstrap_odoo(
|
|
|
202
154
|
addon_paths = get_addon_paths(
|
|
203
155
|
odoo_main_repo=ctx.obj.odoo_main_path,
|
|
204
156
|
workspace_addon_path=ctx.obj.workspace_addon_path,
|
|
205
|
-
zip_addon_path=thirdparty_addon_path / "custom", # !Todo Pull out into variable
|
|
206
157
|
thirdparty_addon_path=thirdparty_addon_path,
|
|
207
158
|
)
|
|
208
159
|
|
|
@@ -6,9 +6,9 @@ from typing import List
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
8
|
from ..commands.rpc.cli import rpc_callback
|
|
9
|
-
from ..helpers import run_cmd
|
|
10
9
|
from ..helpers.cli import typer_retuner, typer_unpacker
|
|
11
10
|
from ..helpers.odoo_files import get_odoo_module_paths
|
|
11
|
+
from ..helpers.system import run_cmd
|
|
12
12
|
from .bootstrap import bootstrap_odoo
|
|
13
13
|
from .makedev import makedev_config, makedev_rpc
|
|
14
14
|
from .rpc import import_to_odoo
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
"""Commands to clone Odoo and addon source code"""
|
|
1
2
|
import configparser
|
|
2
3
|
import logging
|
|
3
4
|
import shutil
|
|
4
|
-
import
|
|
5
|
+
import tempfile
|
|
5
6
|
from enum import Enum
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import List
|
|
@@ -10,10 +11,11 @@ import typer
|
|
|
10
11
|
from ruamel.yaml import YAML
|
|
11
12
|
|
|
12
13
|
from ..git import GitUrl, git_ensure_addon_repos, git_ensure_odoo_repo
|
|
13
|
-
from ..helpers import
|
|
14
|
+
from ..helpers.bootstrap import _install_py_reqs_for_modules
|
|
14
15
|
from ..helpers.cli import typer_unpacker
|
|
15
|
-
from ..helpers.odoo_files import get_addon_paths
|
|
16
|
+
from ..helpers.odoo_files import get_addon_paths, get_odoo_module_paths, get_zip_addon_path
|
|
16
17
|
from ..helpers.odoo_manifest import remove_unused_folders
|
|
18
|
+
from ..helpers.system import download_file
|
|
17
19
|
|
|
18
20
|
LOGGER = logging.getLogger(__name__)
|
|
19
21
|
|
|
@@ -25,12 +27,12 @@ class UpdateMode(str, Enum):
|
|
|
25
27
|
thirdparty = "thirdparty"
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
def
|
|
29
|
-
"""Take
|
|
30
|
+
def unpack_addon_archives(archive_folder: Path, target_addon_folder: Path, remove_excess: bool = False):
|
|
31
|
+
"""Take archive files from archive_folder and extract them into target_addon_folder.
|
|
30
32
|
|
|
31
33
|
Parameters
|
|
32
34
|
----------
|
|
33
|
-
|
|
35
|
+
archive_folder : Path
|
|
34
36
|
Where to look for zip files
|
|
35
37
|
target_addon_folder : Path
|
|
36
38
|
where to place them
|
|
@@ -38,14 +40,33 @@ def unzip_addons(zip_folder: Path, target_addon_folder: Path, remove_excess: boo
|
|
|
38
40
|
remove all and then unzip, by default False
|
|
39
41
|
"""
|
|
40
42
|
if remove_excess:
|
|
43
|
+
LOGGER.debug("Clearing out unarchive folder: %s", target_addon_folder)
|
|
41
44
|
for folder in target_addon_folder.iterdir():
|
|
42
45
|
shutil.rmtree(folder)
|
|
43
|
-
LOGGER.info("Extracting
|
|
44
|
-
for zip_file in
|
|
46
|
+
LOGGER.info("Extracting archive addons to: %s", target_addon_folder)
|
|
47
|
+
for zip_file in archive_folder.glob("*.zip"):
|
|
45
48
|
target_addon_folder.mkdir(exist_ok=True, parents=True)
|
|
46
|
-
LOGGER.info("Extracting
|
|
47
|
-
with
|
|
48
|
-
|
|
49
|
+
LOGGER.info("Extracting addon archive: %s", zip_file)
|
|
50
|
+
with tempfile.TemporaryDirectory() as td:
|
|
51
|
+
td = Path(td)
|
|
52
|
+
shutil.unpack_archive(zip_file, td)
|
|
53
|
+
# We can have zip files with one or more modules.
|
|
54
|
+
# Either the first folder contains multiple or its a module by itself
|
|
55
|
+
# So first get the real modules form the zip root or one level down and then move them to subpaths
|
|
56
|
+
zip_module_paths = get_odoo_module_paths([td] + list(td.glob("*/")))
|
|
57
|
+
if not zip_module_paths:
|
|
58
|
+
LOGGER.warning("Could not find valid modules in thirdparty zip: %s", zip_file)
|
|
59
|
+
continue
|
|
60
|
+
LOGGER.debug(
|
|
61
|
+
"Found modules in Zipfile:\n%s",
|
|
62
|
+
"\n".join([str(f.relative_to(td)) for f in zip_module_paths]),
|
|
63
|
+
)
|
|
64
|
+
target_folder = target_addon_folder / ("single_mods" if len(zip_module_paths) == 1 else zip_file.stem)
|
|
65
|
+
target_folder.mkdir(exist_ok=True)
|
|
66
|
+
for m in zip_module_paths:
|
|
67
|
+
module_target = target_folder / m.stem
|
|
68
|
+
shutil.rmtree(module_target, ignore_errors=True)
|
|
69
|
+
shutil.move(m, module_target)
|
|
49
70
|
|
|
50
71
|
|
|
51
72
|
def update_odoo_conf_addon_paths(odoo_conf: Path, addon_paths: List[Path]):
|
|
@@ -67,6 +88,30 @@ def update_odoo_conf_addon_paths(odoo_conf: Path, addon_paths: List[Path]):
|
|
|
67
88
|
config.write(odoo_conf.open("w"))
|
|
68
89
|
|
|
69
90
|
|
|
91
|
+
@typer_unpacker
|
|
92
|
+
def install_module_dependencies(
|
|
93
|
+
ctx: typer.Context,
|
|
94
|
+
thirdparty_addon_path: Path = typer.Option(
|
|
95
|
+
...,
|
|
96
|
+
envvar="ODOO_THIRDPARTY_LOCATION",
|
|
97
|
+
help="Root folder of the Thirdparty addon repos",
|
|
98
|
+
),
|
|
99
|
+
module_list: List[str] = typer.Argument(
|
|
100
|
+
...,
|
|
101
|
+
help="Modules to check for dependencies (can use all for all available addons)",
|
|
102
|
+
),
|
|
103
|
+
):
|
|
104
|
+
odoo_addon_paths = get_addon_paths(
|
|
105
|
+
odoo_main_repo=ctx.obj.odoo_main_path,
|
|
106
|
+
workspace_addon_path=ctx.obj.workspace_addon_path,
|
|
107
|
+
thirdparty_addon_path=thirdparty_addon_path,
|
|
108
|
+
)
|
|
109
|
+
if len(module_list) == 1 and module_list[0] == "all":
|
|
110
|
+
search_addon_paths = [p for p in odoo_addon_paths if ctx.obj.odoo_main_path not in p.parents]
|
|
111
|
+
module_list = [p.stem for p in get_odoo_module_paths(search_addon_paths)]
|
|
112
|
+
_install_py_reqs_for_modules(odoo_addon_paths, module_list)
|
|
113
|
+
|
|
114
|
+
|
|
70
115
|
@typer_unpacker
|
|
71
116
|
def get_source_file(
|
|
72
117
|
manifest_yml: Path = typer.Option(
|
|
@@ -101,6 +146,7 @@ def get_source_file(
|
|
|
101
146
|
@typer_unpacker
|
|
102
147
|
def get_source(
|
|
103
148
|
ctx: typer.Context,
|
|
149
|
+
update_mode: UpdateMode = typer.Argument(UpdateMode.all, help="What to Update"),
|
|
104
150
|
manifest_yml: Path = typer.Option(
|
|
105
151
|
..., envvar="ODOO_MANIFEST", help="Git.yml file, that specified what to download with wich prefix"
|
|
106
152
|
),
|
|
@@ -110,7 +156,6 @@ def get_source(
|
|
|
110
156
|
thirdparty_zip_source: Path = typer.Option(
|
|
111
157
|
..., envvar="ODOO_THIRDPARTY_ZIP_LOCATION", help="Source folder, where to look for Addon zips"
|
|
112
158
|
),
|
|
113
|
-
update_mode: UpdateMode = typer.Option(UpdateMode.all, help="What to Update"),
|
|
114
159
|
add_compare_comments: bool = typer.Option(
|
|
115
160
|
False, help="Wether to add github.com three dot compare links as comments."
|
|
116
161
|
),
|
|
@@ -124,10 +169,10 @@ def get_source(
|
|
|
124
169
|
):
|
|
125
170
|
"""Update Odoo Source and Thirdparty source."""
|
|
126
171
|
LOGGER.info("Updating Source Repos")
|
|
127
|
-
zip_addon_path = thirdparty_addon_path
|
|
172
|
+
zip_addon_path = get_zip_addon_path(thirdparty_addon_path)
|
|
128
173
|
|
|
129
174
|
if update_mode in ["all", "zip"]:
|
|
130
|
-
|
|
175
|
+
unpack_addon_archives(thirdparty_zip_source, zip_addon_path, remove_excess=remove_unspecified_addons)
|
|
131
176
|
|
|
132
177
|
if update_mode in ["all", "odoo"]:
|
|
133
178
|
git_ensure_odoo_repo(
|
|
@@ -145,18 +190,17 @@ def get_source(
|
|
|
145
190
|
generate_yml_compare_comments=add_compare_comments,
|
|
146
191
|
download_archive=ctx.obj.source_download_archive,
|
|
147
192
|
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
193
|
+
if remove_unspecified_addons:
|
|
194
|
+
remove_unused_folders(
|
|
195
|
+
thirdparty_addon_path=thirdparty_addon_path,
|
|
196
|
+
thirdparty_repos=git_repos.get("thirdparty", []),
|
|
197
|
+
keep_folders=[zip_addon_path],
|
|
198
|
+
)
|
|
154
199
|
|
|
155
200
|
if (conf_path := ctx.obj.odoo_conf_path).exists():
|
|
156
201
|
odoo_addon_paths = get_addon_paths(
|
|
157
202
|
odoo_main_repo=ctx.obj.odoo_main_path,
|
|
158
203
|
workspace_addon_path=ctx.obj.workspace_addon_path,
|
|
159
|
-
zip_addon_path=zip_addon_path,
|
|
160
204
|
thirdparty_addon_path=thirdparty_addon_path,
|
|
161
205
|
)
|
|
162
206
|
update_odoo_conf_addon_paths(odoo_conf=conf_path, addon_paths=odoo_addon_paths)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Provides Various Helper Functions for Odoo"""
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
from ast import literal_eval
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
from .odoo_files import _get_python_requirements_of_modules
|
|
9
|
+
from .system import run_cmd
|
|
10
|
+
|
|
11
|
+
LOGGER = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _install_py_reqs_for_modules(addon_paths: List[Path], module_names: List[str] = None):
|
|
15
|
+
"""Install Python Requirements mentioned in odoo module manifests of given modules
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
addon_paths : List[Path]
|
|
20
|
+
odoo-bin addons path
|
|
21
|
+
module_names : List[str], Optional
|
|
22
|
+
List of modules to filter for, by default "all available modules"
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
CompletedProcess
|
|
27
|
+
"""
|
|
28
|
+
py_reqs = _get_python_requirements_of_modules(addon_paths=addon_paths, filter_module_names=module_names)
|
|
29
|
+
if py_reqs:
|
|
30
|
+
installed_packages = run_cmd(
|
|
31
|
+
"pip list --format json --disable-pip-version-check", check=True, shell=True, stdout=subprocess.PIPE
|
|
32
|
+
).stdout.decode("utf-8")
|
|
33
|
+
installed_packages = [m.get("name") for m in literal_eval(installed_packages)]
|
|
34
|
+
if missing_packages := [p for p in py_reqs if p not in installed_packages]:
|
|
35
|
+
LOGGER.info("Installing Python requirements: '%s'", ", ".join(missing_packages))
|
|
36
|
+
return run_cmd(f"pip install {' '.join(missing_packages)} --disable-pip-version-check", shell=True)
|
|
37
|
+
LOGGER.debug("No py Requirements to be installed")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _install_py_reqs_by_odoo_cmd(addon_paths: List[Path], odoo_bin_cmd: str):
|
|
41
|
+
"""Install Python reqs for modules mentioned in odoo-bin commandline --init or -i directives.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
addon_paths : List[Path]
|
|
46
|
+
odoo-bin addons-path
|
|
47
|
+
odoo_bin_cmd : str
|
|
48
|
+
odoo-bin commandline
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
CompletedProcess
|
|
53
|
+
"""
|
|
54
|
+
install_modules = []
|
|
55
|
+
for m in re.finditer(r'(--init|-i) "?([^ \n]+)"?', odoo_bin_cmd):
|
|
56
|
+
install_modules += m.group(2).split(",")
|
|
57
|
+
if install_modules:
|
|
58
|
+
return _install_py_reqs_for_modules(addon_paths=addon_paths, module_names=install_modules)
|
|
@@ -9,6 +9,10 @@ from git import Repo
|
|
|
9
9
|
LOGGER = logging.getLogger(__name__)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def get_zip_addon_path(thirdparty_path: Path) -> Path:
|
|
13
|
+
return thirdparty_path / "custom"
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
def get_odoo_module_paths(search_folders: Union[List[Path], Path]) -> List[Path]:
|
|
13
17
|
"""List all Valid odoo module names in one or many Odoo addons folder.
|
|
14
18
|
|
|
@@ -101,7 +105,6 @@ def get_depends_of_module(
|
|
|
101
105
|
return []
|
|
102
106
|
already_done_modules.append(module_to_check.absolute())
|
|
103
107
|
|
|
104
|
-
LOGGER.debug("Loading Manifest: %s", manifest_path.absolute())
|
|
105
108
|
manifest = literal_eval(manifest_path.read_text())
|
|
106
109
|
module_depends = manifest.get("depends", [])
|
|
107
110
|
sub_depends = []
|
|
@@ -122,7 +125,6 @@ def get_depends_of_module(
|
|
|
122
125
|
def get_addon_paths(
|
|
123
126
|
odoo_main_repo: Path,
|
|
124
127
|
workspace_addon_path: Path,
|
|
125
|
-
zip_addon_path: Path,
|
|
126
128
|
thirdparty_addon_path: Path,
|
|
127
129
|
) -> List[Path]:
|
|
128
130
|
"""Get Odoo Addon Paths for odoo.conf.
|
|
@@ -133,8 +135,6 @@ def get_addon_paths(
|
|
|
133
135
|
Path to main odoo repo
|
|
134
136
|
workspace_addon_path : Path
|
|
135
137
|
Path to workspace addons
|
|
136
|
-
zip_addon_path : Path
|
|
137
|
-
path to zip addons
|
|
138
138
|
thirdparty_addon_path : Path
|
|
139
139
|
path to git cloned addon repos
|
|
140
140
|
|
|
@@ -146,6 +146,7 @@ def get_addon_paths(
|
|
|
146
146
|
odoo_addon_paths = [odoo_main_repo / "addons"]
|
|
147
147
|
if get_odoo_module_paths(workspace_addon_path):
|
|
148
148
|
odoo_addon_paths.append(workspace_addon_path)
|
|
149
|
+
zip_addon_path = get_zip_addon_path(thirdparty_addon_path)
|
|
149
150
|
zip_addon_repos = [f for f in zip_addon_path.iterdir() if f.is_dir() and get_odoo_module_paths(f)]
|
|
150
151
|
odoo_addon_paths += zip_addon_repos
|
|
151
152
|
git_thirdparty_addon_repos = [
|
|
@@ -155,6 +156,27 @@ def get_addon_paths(
|
|
|
155
156
|
return odoo_addon_paths
|
|
156
157
|
|
|
157
158
|
|
|
159
|
+
def _get_odoo_main_path(addon_paths: List[Path]) -> Path:
|
|
160
|
+
"""Get Odoo main path by location of odoo-bin from addon folders.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
addon_paths : List[Path]
|
|
165
|
+
List of possible paths
|
|
166
|
+
|
|
167
|
+
Returns
|
|
168
|
+
-------
|
|
169
|
+
Path
|
|
170
|
+
Path with odoo-bin and main addons folder
|
|
171
|
+
"""
|
|
172
|
+
for path in addon_paths:
|
|
173
|
+
# The main odoo addon path is odoo/addons.
|
|
174
|
+
# so one up should be the launch script
|
|
175
|
+
bin_path = path.parent / "odoo-bin"
|
|
176
|
+
if bin_path.exists() and bin_path.is_file():
|
|
177
|
+
return path
|
|
178
|
+
|
|
179
|
+
|
|
158
180
|
def _get_python_requirements_of_modules(addon_paths: List[Path], filter_module_names: List[str] = None):
|
|
159
181
|
"""Install python requirements mentioned in module manifests
|
|
160
182
|
|
|
@@ -170,31 +192,42 @@ def _get_python_requirements_of_modules(addon_paths: List[Path], filter_module_n
|
|
|
170
192
|
|
|
171
193
|
if not filter_module_names:
|
|
172
194
|
filter_module_names = available_module_names
|
|
173
|
-
filter_module_names = [f for f in filter_module_names if f
|
|
174
|
-
LOGGER.info("Checking python requirements of Modules: %s", ", ".join(sorted(filter_module_names)))
|
|
195
|
+
filter_module_names = [f for f in filter_module_names if f != "base"]
|
|
175
196
|
|
|
176
|
-
|
|
177
|
-
|
|
197
|
+
LOGGER.info("Checking python requirements of Modules:\n%s", "\n".join(sorted(filter_module_names)))
|
|
198
|
+
if unavailable_modules := set(filter_module_names).difference(available_module_names):
|
|
199
|
+
LOGGER.warning("Could not find __manifest__ for:\n%s", "\n".join(unavailable_modules))
|
|
200
|
+
LOGGER.debug("Search Paths:\n%s", "\n".join(map(str, addon_paths)))
|
|
178
201
|
|
|
179
202
|
check_modules = [mp for mp in available_modules if mp.stem in filter_module_names]
|
|
203
|
+
|
|
204
|
+
if odoo_main_path := _get_odoo_main_path(addon_paths):
|
|
205
|
+
# When the Odoo main path is in the supplied path, exclude those modules.
|
|
206
|
+
# Odoos base requirements are set in their requirements.txt
|
|
207
|
+
LOGGER.debug("Py install: Excluding Odoo main Modules in: '%s'", odoo_main_path)
|
|
208
|
+
check_modules = [mp for mp in check_modules if odoo_main_path not in mp.parents]
|
|
209
|
+
|
|
180
210
|
check_modules_dependencies = []
|
|
181
211
|
for module in check_modules:
|
|
182
212
|
check_modules_dependencies += get_depends_of_module(
|
|
183
213
|
available_modules, module, already_done_modules=check_modules_dependencies
|
|
184
214
|
)
|
|
185
215
|
LOGGER.debug(
|
|
186
|
-
"adding
|
|
216
|
+
"adding children of requested modules to check list:\n%s",
|
|
217
|
+
"\n".join(sorted([p.stem for p in check_modules_dependencies])),
|
|
187
218
|
)
|
|
188
219
|
|
|
189
220
|
check_modules += check_modules_dependencies
|
|
190
221
|
|
|
222
|
+
check_modules = set(check_modules)
|
|
223
|
+
|
|
191
224
|
if not check_modules:
|
|
192
225
|
LOGGER.debug("No Modules provided to check for python Requirements")
|
|
193
226
|
return
|
|
194
227
|
python_depends = []
|
|
195
228
|
for module_path in check_modules:
|
|
229
|
+
LOGGER.debug("Checking for External Depends: %s", module_path)
|
|
196
230
|
manifest_path = module_path / "__manifest__.py"
|
|
197
|
-
LOGGER.debug("Loading Manifest: %s", manifest_path.absolute())
|
|
198
231
|
manifest = literal_eval(manifest_path.read_text())
|
|
199
232
|
if module_depends := manifest.get("external_dependencies", {}).get("python"):
|
|
200
233
|
python_depends += module_depends
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|