Skip to content

Commit

Permalink
Make installation of dependencies from manifest optional
Browse files Browse the repository at this point in the history
  • Loading branch information
katyukha committed Oct 6, 2023
1 parent 67365f2 commit 1ee73a8
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 21 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@

## Release 0.0.15 (Unreleased)

### Changed

- Installation of dependencies from manifest is now optional.
It is frequent case, when authors of module place incorrect dependencies
in manifest, thus installation of addon may fail.

### Fixes

- Fix error when running `addons install/update/uninstall` with non-existing
logfile. This was caused by attempt to determine starting point of logfile
to search for errors happened during operation.
Now this case is handled correctly.

---

## Release 0.0.14 (2023-10-04)

### Added
Expand Down
16 changes: 14 additions & 2 deletions subpackages/cli/source/odood/cli/commands/addons.d
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@ class CommandAddonsLink: OdoodCommand {
this.add(new Flag(
"r", "recursive",
"Search for addons in this directory recursively."));
this.add(new Flag(
null, "manifest-requirements",
"Install python dependencies from manifest's external dependencies"));
this.add(new Flag(
null, "ual", "Update addons list for all databases"));
this.add(new Argument(
Expand All @@ -317,7 +320,10 @@ class CommandAddonsLink: OdoodCommand {
project.addons.link(
Path(args.arg("path")),
args.flag("recursive"),
args.flag("force"));
args.flag("force"),
true, // Install py deps from requirements.txt
args.flag("manifest-requirements"),
);

if (args.flag("ual"))
foreach(dbname; project.databases.list())
Expand Down Expand Up @@ -579,6 +585,9 @@ class CommandAddonsAdd: OdoodCommand {
"If set, then Odood will automatically process " ~
"odoo_requirements.txt file inside repositories mentioned in " ~
"provided odoo_requirements.txt"));
this.add(new Flag(
null, "manifest-requirements",
"Install python dependencies from manifest's external dependencies"));
this.add(new Option(
null, "odoo-apps", "Add addon from odoo apps.").repeating);
this.add(new Option(
Expand All @@ -597,7 +606,10 @@ class CommandAddonsAdd: OdoodCommand {
project.addons.processOdooRequirements(
Path(requirements_path),
args.flag("single-branch"),
args.flag("recursive"));
args.flag("recursive"),
true, // Install python deps from requirements.txt file if exists
args.flag("manifest-requirements")
);
}

}
Expand Down
79 changes: 60 additions & 19 deletions subpackages/lib/source/odood/lib/addons/manager.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ private import odood.utils.zip: extract_zip_archive;
private import odood.utils.git: parseGitURL, gitClone;
private import odood.exception: OdoodException;

/// Install python dependencies requirements.txt by default
immutable bool DEFAULT_INSTALL_PY_REQUREMENTS = true;

/// Install python dependencies from addon manifest by default
immutable bool DEFAULT_INSTALL_MANIFEST_REQUREMENTS = true;


/// Struct that provide API to manage odoo addons for the project
struct AddonManager {
Expand Down Expand Up @@ -165,12 +171,15 @@ struct AddonManager {
* force = if set, then rewrite link to this addon
* (if it was already linked).
* py_requirements = if set, then automatically install python
* requirements for requirements.txt file or from external deps
* requirements for requirements.txt file
* manifest_requirements = if set, then automatically install
* python requirements from manifest
**/
void link(
OdooAddon addon,
in bool force=false,
in bool py_requirements=true) const {
in bool py_requirements=DEFAULT_INSTALL_PY_REQUREMENTS,
in bool manifest_requirements=DEFAULT_INSTALL_MANIFEST_REQUREMENTS) const {
auto dest = _project.directories.addons.join(addon.name);
if (!dest.exists) {
tracef("Linking addon %s (%s -> %s)",
Expand Down Expand Up @@ -205,12 +214,7 @@ struct AddonManager {
infof("Installing python requirements for addon '%s'",
addon.name);
_project.venv.installPyRequirements(dest.join("requirements.txt"));
} else if (py_requirements && addon.manifest.python_dependencies.length > 0) {
// TOOD: Handle case when python dependencies from manifest are bad:
// - not a pip package
// - python module from standard lib
// - other strage thing
// May be it have sense to check this on manifest parsing stage.
} else if (manifest_requirements && addon.manifest.python_dependencies.length > 0) {
infof("Installing python requirements for addon '%s' from manifest",
addon.name);
_project.venv.installPyPackages(addon.manifest.python_dependencies);
Expand All @@ -228,14 +232,17 @@ struct AddonManager {
* (if it was already linked).
* py_requirements = if set, then automatically install python
* requirements for requirements.txt file
* manifest_requirements = if set, then automatically install
* python requirements from manifest
**/
void link(
in Path search_path,
in bool recursive=false,
in bool force=false,
in bool py_requirements=true) const {
in bool py_requirements=DEFAULT_INSTALL_PY_REQUREMENTS,
in bool manifest_requirements=DEFAULT_INSTALL_MANIFEST_REQUREMENTS) const {
foreach(addon; scan(search_path, recursive))
link(addon, force, py_requirements);
link(addon, force, py_requirements, manifest_requirements);

if (py_requirements && search_path.join("requirements.txt").exists) {
infof("Installing python requirements from '%s'",
Expand Down Expand Up @@ -472,7 +479,10 @@ struct AddonManager {
}

/// Download from odoo apps
void downloadFromOdooApps(in string addon_name) const {
void downloadFromOdooApps(
in string addon_name,
in bool py_requirements=DEFAULT_INSTALL_PY_REQUREMENTS,
in bool manifest_requirements=DEFAULT_INSTALL_MANIFEST_REQUREMENTS) const {
auto temp_dir = createTempPath();
scope(exit) temp_dir.remove();

Expand All @@ -495,7 +505,11 @@ struct AddonManager {
} else {
infof("Copying addon %s...", addon.name);
addon.path.copyTo(_project.directories.downloads);
link(_project.directories.downloads.join(addon.name));
link(
_project.directories.downloads.join(addon.name),
false, // force
py_requirements,
manifest_requirements);
}
}
}
Expand All @@ -516,11 +530,17 @@ struct AddonManager {
* by path
* recurisve = recursively process odoo_requirements.txt in
* clonned repositories
* py_requirements = if set, then automatically install python
* requirements for requirements.txt file
* manifest_requirements = if set, then automatically install
* python requirements from manifest
**/
void processOdooRequirements(
in Path path,
in bool single_branch=false,
in bool recursive=false) {
in bool recursive=false,
in bool py_requirements=DEFAULT_INSTALL_PY_REQUREMENTS,
in bool manifest_requirements=DEFAULT_INSTALL_MANIFEST_REQUREMENTS) {
foreach(line; parseOdooRequirements(path))
// TODO: In case when only single module request,
// add only single module
Expand All @@ -534,7 +554,7 @@ struct AddonManager {
recursive);
break;
case OdooRequirementsLineType.odoo_apps:
downloadFromOdooApps(line.addon);
downloadFromOdooApps(line.addon, py_requirements, manifest_requirements);
break;
}
}
Expand All @@ -550,12 +570,18 @@ struct AddonManager {
* single_branch = if set, then clone only single branch of repo
* recursive = if set, then automatically process odoo_requirements.txt
* inside clonned repo, to recursively fetch its dependencies
* py_requirements = if set, then automatically install python
* requirements for requirements.txt file
* manifest_requirements = if set, then automatically install
* python requirements from manifest
**/
void addRepo(
in string url,
in string branch,
in bool single_branch=false,
in bool recursive=true) {
in bool recursive=true,
in bool py_requirements=DEFAULT_INSTALL_PY_REQUREMENTS,
in bool manifest_requirements=DEFAULT_INSTALL_MANIFEST_REQUREMENTS) {
import std.algorithm;
import std.string: toLower;
import std.array: array;
Expand All @@ -575,24 +601,39 @@ struct AddonManager {

// TODO: Do we need to create instance of repo here?
auto repo = new AddonRepository(_project, dest);
link(repo.path, true);
link(
repo.path,
true, // recursive
false, // force
py_requirements,
manifest_requirements);

// If there is odoo_requirements.txt file present, then we have to
// process it.
if (recursive && repo.path.join("odoo_requirements.txt").exists) {
processOdooRequirements(
repo.path.join("odoo_requirements.txt"),
single_branch,
recursive);
recursive,
py_requirements,
manifest_requirements);
}
}

/// ditto
void addRepo(
in string url,
in bool single_branch=false,
in bool recursive=true) {
addRepo(url, _project.odoo.serie.toString, single_branch, recursive);
in bool recursive=true,
in bool py_requirements=DEFAULT_INSTALL_PY_REQUREMENTS,
in bool manifest_requirements=DEFAULT_INSTALL_MANIFEST_REQUREMENTS) {
addRepo(
url,
_project.odoo.serie.toString,
single_branch,
recursive,
py_requirements,
manifest_requirements);
}

/// Get repository instance for specified path
Expand Down

0 comments on commit 1ee73a8

Please sign in to comment.