bl-odoo 0.3.0__tar.gz → 0.3.2__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.
bl_odoo-0.3.2/PKG-INFO ADDED
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: bl-odoo
3
+ Version: 0.3.2
4
+ Summary: A command-line tool for managing Odoo dependencies.
5
+ Author-email: Your Name <your.email@example.com>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pyyaml>=6.0.3
11
+ Requires-Dist: rich
12
+ Requires-Dist: typer
13
+ Dynamic: license-file
14
+
15
+ # bl
16
+
17
+ ## Why BL
18
+
19
+ Because `ak` is slow and `bl` is fast
20
+
21
+ Because `ak` crashes if anything goes wrong
22
+
23
+ Because `ak` error are impossible to find
24
+
25
+ ## Install
26
+
27
+ `pipx install bl-odoo`
28
+
29
+ ## Usage
30
+
31
+ ### Build
32
+
33
+ ```bl build -c <path_to_spec.yaml> -z <path_to_frozen.yaml> -j <concurrency>```
34
+
35
+ #### Params
36
+ * `path_to_spec.yaml` should be the path to your spec (default: spec.yaml)
37
+ * `path_to_frozen.yaml` should be the path to your spec (default: frozen.yaml)
38
+ * `concurrency` number of module clone simultaneously (default: 28)
39
+
40
+ #### How it looks
41
+ <img width="1683" height="756" alt="bl_build" src="https://github.com/user-attachments/assets/22fc1565-3a54-4f57-9b85-a11263b9b536" />
42
+
43
+ ### Freeze
44
+
45
+ ```bl freeze -c <path_to_spec.yaml> -z <path_to_frozen.yaml> -j <concurrency>```
46
+
47
+ #### Params
48
+ * `path_to_spec.yaml` should be the path to your spec (default: spec.yaml)
49
+ * `path_to_frozen.yaml` should be the path to your spec (default: frozen.yaml)
50
+ * `concurrency` number of module clone simultaneously (default: 28)
51
+
52
+ ## Odoo is taking a really long time to clone
53
+
54
+ Yes !
55
+
56
+ You can add a locales entry to your odoo repo in `spec.yaml` like so:
57
+ ```
58
+ odoo:
59
+ modules:
60
+ - account
61
+ ...
62
+ remotes:
63
+ odoo: https://github.com/odoo/odoo
64
+ merges:
65
+ - odoo 14.0
66
+ locales:
67
+ - fr
68
+ - en
69
+ ```
70
+ It will only download the french and english translation instead of all of them
71
+ - without locales: 849MB and 40 seconds fresh build
72
+ - with locales fr, en: 169MB and 27 seconds fresh build
73
+
74
+ ## Benchmarks
75
+
76
+ ### Ak benchmarks
77
+ #### Fresh install
78
+ <img width="1462" height="347" alt="ak_bench_cold" src="https://github.com/user-attachments/assets/e29cd3d9-831c-43c1-8f29-e040ebee5740" />
79
+
80
+ #### Already cloned once
81
+ <img width="1419" height="356" alt="ak_bench_hot" src="https://github.com/user-attachments/assets/47b5756e-efe1-4272-82b7-e160f73af1be" />
82
+
83
+ ### Bl benchmarks
84
+ #### Fresh install
85
+ <img width="1335" height="343" alt="bl_bench_cold" src="https://github.com/user-attachments/assets/a64ba1c4-17bd-4017-acfd-5749df505f50" />
86
+
87
+ #### Already cloned once
88
+ <img width="1373" height="342" alt="bl_bench_hot" src="https://github.com/user-attachments/assets/b11e60c2-368b-496c-bc88-f5a765f44bfe" />
89
+
90
+ ### Results
91
+ |Type| AK | BL |
92
+ |----|----|----|
93
+ |Cold| ~100s | 2 - 10x faster |
94
+ |Hot| 3-20s | 2 - 10x faster |
95
+
@@ -0,0 +1,81 @@
1
+ # bl
2
+
3
+ ## Why BL
4
+
5
+ Because `ak` is slow and `bl` is fast
6
+
7
+ Because `ak` crashes if anything goes wrong
8
+
9
+ Because `ak` error are impossible to find
10
+
11
+ ## Install
12
+
13
+ `pipx install bl-odoo`
14
+
15
+ ## Usage
16
+
17
+ ### Build
18
+
19
+ ```bl build -c <path_to_spec.yaml> -z <path_to_frozen.yaml> -j <concurrency>```
20
+
21
+ #### Params
22
+ * `path_to_spec.yaml` should be the path to your spec (default: spec.yaml)
23
+ * `path_to_frozen.yaml` should be the path to your spec (default: frozen.yaml)
24
+ * `concurrency` number of module clone simultaneously (default: 28)
25
+
26
+ #### How it looks
27
+ <img width="1683" height="756" alt="bl_build" src="https://github.com/user-attachments/assets/22fc1565-3a54-4f57-9b85-a11263b9b536" />
28
+
29
+ ### Freeze
30
+
31
+ ```bl freeze -c <path_to_spec.yaml> -z <path_to_frozen.yaml> -j <concurrency>```
32
+
33
+ #### Params
34
+ * `path_to_spec.yaml` should be the path to your spec (default: spec.yaml)
35
+ * `path_to_frozen.yaml` should be the path to your spec (default: frozen.yaml)
36
+ * `concurrency` number of module clone simultaneously (default: 28)
37
+
38
+ ## Odoo is taking a really long time to clone
39
+
40
+ Yes !
41
+
42
+ You can add a locales entry to your odoo repo in `spec.yaml` like so:
43
+ ```
44
+ odoo:
45
+ modules:
46
+ - account
47
+ ...
48
+ remotes:
49
+ odoo: https://github.com/odoo/odoo
50
+ merges:
51
+ - odoo 14.0
52
+ locales:
53
+ - fr
54
+ - en
55
+ ```
56
+ It will only download the french and english translation instead of all of them
57
+ - without locales: 849MB and 40 seconds fresh build
58
+ - with locales fr, en: 169MB and 27 seconds fresh build
59
+
60
+ ## Benchmarks
61
+
62
+ ### Ak benchmarks
63
+ #### Fresh install
64
+ <img width="1462" height="347" alt="ak_bench_cold" src="https://github.com/user-attachments/assets/e29cd3d9-831c-43c1-8f29-e040ebee5740" />
65
+
66
+ #### Already cloned once
67
+ <img width="1419" height="356" alt="ak_bench_hot" src="https://github.com/user-attachments/assets/47b5756e-efe1-4272-82b7-e160f73af1be" />
68
+
69
+ ### Bl benchmarks
70
+ #### Fresh install
71
+ <img width="1335" height="343" alt="bl_bench_cold" src="https://github.com/user-attachments/assets/a64ba1c4-17bd-4017-acfd-5749df505f50" />
72
+
73
+ #### Already cloned once
74
+ <img width="1373" height="342" alt="bl_bench_hot" src="https://github.com/user-attachments/assets/b11e60c2-368b-496c-bc88-f5a765f44bfe" />
75
+
76
+ ### Results
77
+ |Type| AK | BL |
78
+ |----|----|----|
79
+ |Cold| ~100s | 2 - 10x faster |
80
+ |Hot| 3-20s | 2 - 10x faster |
81
+
@@ -12,15 +12,19 @@ def run():
12
12
  parser = argparse.ArgumentParser(
13
13
  description="Process a project specification.", formatter_class=argparse.ArgumentDefaultsHelpFormatter
14
14
  )
15
- parser.add_argument(
16
- "-f", "--freeze", const=True, default=None, nargs="?", type=Path, help="Freeze the current state of modules"
17
- )
18
- parser.add_argument(
15
+
16
+ parent_parser = argparse.ArgumentParser(add_help=False)
17
+ parent_parser.add_argument(
19
18
  "-c", "--config", type=Path, help="Path to the project specification file.", default="spec.yaml"
20
19
  )
21
- parser.add_argument("-z", "--frozen", type=Path, help="Path to the frozen specification file.")
22
- parser.add_argument("-j", "--concurrency", type=int, default=28, help="Number of concurrent tasks.")
23
- parser.add_argument("-w", "--workdir", type=Path, help="Working directory. Defaults to config directory.")
20
+ parent_parser.add_argument("-z", "--frozen", type=Path, help="Path to the frozen specification file.")
21
+ parent_parser.add_argument("-j", "--concurrency", type=int, default=28, help="Number of concurrent tasks.")
22
+ parent_parser.add_argument("-w", "--workdir", type=Path, help="Working directory. Defaults to config directory.")
23
+
24
+ sub = parser.add_subparsers(help="subcommand help", dest="command")
25
+ build = sub.add_parser("build", parents=[parent_parser], help="build help")
26
+ freeze = sub.add_parser("freeze", parents=[parent_parser], help="freeze help")
27
+
24
28
  args = parser.parse_args()
25
29
 
26
30
  project_spec = load_spec_file(args.config, args.frozen, args.workdir)
@@ -28,9 +32,9 @@ def run():
28
32
  sys.exit(1)
29
33
 
30
34
  try:
31
- if args.freeze:
32
- asyncio.run(freeze_project(project_spec, args.freeze, concurrency=args.concurrency))
33
- else:
35
+ if args.command == "freeze":
36
+ asyncio.run(freeze_project(project_spec, args.frozen, concurrency=args.concurrency))
37
+ elif args.command == "build":
34
38
  asyncio.run(process_project(project_spec, concurrency=args.concurrency))
35
39
  except Exception:
36
40
  sys.exit(1)
@@ -40,7 +40,7 @@ async def freeze_spec(
40
40
  async def freeze_project(project_spec: ProjectSpec, freeze_file: Path | bool, concurrency: int):
41
41
  frz_semaphore = asyncio.Semaphore(concurrency)
42
42
  workdir = project_spec.workdir
43
- freeze_file_name = freeze_file if freeze_file is not True else "frozen.yaml"
43
+ freeze_file_name = freeze_file if freeze_file else "frozen.yaml"
44
44
  freeze_file_path = workdir / freeze_file_name
45
45
 
46
46
  task_count_progress = Progress(
@@ -49,14 +49,14 @@ async def freeze_project(project_spec: ProjectSpec, freeze_file: Path | bool, co
49
49
  MofNCompleteColumn(),
50
50
  )
51
51
  count_task = task_count_progress.add_task(
52
- f"Freezing modules into {freeze_file_path}", total=len(project_spec.specs)
52
+ f"Freezing modules into {freeze_file_path}", total=len(project_spec.repos)
53
53
  )
54
54
 
55
55
  freeze_data = {}
56
56
 
57
57
  with Live(task_count_progress, console=console, refresh_per_second=10):
58
58
  task_list = []
59
- for name, spec in project_spec.specs.items():
59
+ for name, spec in project_spec.repos.items():
60
60
  task_list.append(
61
61
  freeze_spec(
62
62
  frz_semaphore,
@@ -71,7 +71,6 @@ async def freeze_project(project_spec: ProjectSpec, freeze_file: Path | bool, co
71
71
  for item in freeze_list:
72
72
  freeze_data.update(item)
73
73
 
74
- console.print(yaml.dump(freeze_data, default_flow_style=False))
75
74
  with open(freeze_file_path, "w") as freeze_stream:
76
75
  yaml.dump(freeze_data, freeze_stream, default_flow_style=False)
77
76
 
@@ -3,7 +3,7 @@ import warnings
3
3
  from dataclasses import dataclass
4
4
  from enum import Enum
5
5
  from pathlib import Path
6
- from typing import Any, Dict, List, Optional
6
+ from typing import Any, Dict, List, Optional, Type
7
7
 
8
8
  import yaml
9
9
 
@@ -69,6 +69,13 @@ def parse_remote_refspec_from_parts(parts: List[str], frozen_repo: Dict[str, Dic
69
69
  return RefspecInfo(remote_key, ref_spec, ref_type, ref_name)
70
70
 
71
71
 
72
+ def get_with_syntax_check(name, data, key: str, type: Type):
73
+ result = data.get(key, type())
74
+ if not isinstance(result, type):
75
+ raise Exception(f"Key {key} not of proper syntax should be {str(type)} in {name} description")
76
+ return result
77
+
78
+
72
79
  def load_spec_file(config: Path, frozen: Path, workdir: Path) -> Optional[ProjectSpec]:
73
80
  """
74
81
  Loads and parses the project specification from a YAML file.
@@ -115,14 +122,14 @@ def load_spec_file(config: Path, frozen: Path, workdir: Path) -> Optional[Projec
115
122
 
116
123
  repos: Dict[str, RepoInfo] = {}
117
124
  for repo_name, repo_data in data.items():
118
- modules = repo_data.get("modules", [])
119
- src = repo_data.get("src")
120
- remotes = repo_data.get("remotes") or {}
121
- merges = repo_data.get("merges") or []
122
- shell_commands = repo_data.get("shell_command_after") or None
123
- patch_globs_to_apply = repo_data.get("patch_globs") or None
124
- target_folder = repo_data.get("target_folder") or None
125
- locales = repo_data.get("locales", [])
125
+ modules = get_with_syntax_check(repo_name, repo_data, "modules", list)
126
+ src = get_with_syntax_check(repo_name, repo_data, "src", str)
127
+ remotes = get_with_syntax_check(repo_name, repo_data, "remotes", dict)
128
+ merges = get_with_syntax_check(repo_name, repo_data, "merges", list)
129
+ shell_commands = get_with_syntax_check(repo_name, repo_data, "shell_command_after", list)
130
+ patch_globs_to_apply = get_with_syntax_check(repo_name, repo_data, "patch_globs", list)
131
+ target_folder = get_with_syntax_check(repo_name, repo_data, "target_folder", str)
132
+ locales = get_with_syntax_check(repo_name, repo_data, "locales", list)
126
133
 
127
134
  frozen_repo = frozen_mapping.get(repo_name, {})
128
135
 
@@ -4,6 +4,7 @@ import warnings
4
4
  from pathlib import Path
5
5
  from typing import Dict, List
6
6
 
7
+ from rich import progress
7
8
  from rich.console import Console
8
9
  from rich.live import Live
9
10
  from rich.progress import BarColumn, MofNCompleteColumn, Progress, SpinnerColumn, TaskID, TextColumn
@@ -14,14 +14,14 @@ english_env["LANG"] = "en_US.UTF-8"
14
14
 
15
15
  def get_module_path(workdir: Path, module_name: str, module_spec: RepoInfo) -> Path:
16
16
  """Returns the path to the module directory."""
17
- if module_name == "odoo" and module_spec.target_folder is None:
17
+ if module_name == "odoo" and not module_spec.target_folder:
18
18
  warnings.warn(
19
19
  "importing 'odoo' without a 'target_folder' "
20
20
  + "property is deprecated. Use target_folder: 'src/' in spec.yaml.",
21
21
  DeprecationWarning,
22
22
  )
23
23
  return workdir / "src/"
24
- elif module_spec.target_folder is not None:
24
+ elif module_spec.target_folder:
25
25
  return workdir / module_spec.target_folder
26
26
  else:
27
27
  return workdir / "external-src" / module_name
@@ -29,13 +29,15 @@ def get_module_path(workdir: Path, module_name: str, module_spec: RepoInfo) -> P
29
29
 
30
30
  def get_local_ref(origin: RefspecInfo) -> str:
31
31
  """Generates a local reference name for a given origin."""
32
- return f"loc-{origin.ref_name or origin.refspec}"
32
+ return f"{origin.ref_name or origin.refspec}"
33
33
 
34
34
 
35
35
  async def run_git(*args: str, cwd: Optional[Path] = None) -> tuple[int, str, str]:
36
36
  """Executes a git command asynchronously."""
37
37
  proc = await asyncio.create_subprocess_exec(
38
38
  "git",
39
+ "--git-dir",
40
+ ".git/",
39
41
  *args,
40
42
  stdout=asyncio.subprocess.PIPE,
41
43
  stderr=asyncio.subprocess.PIPE,
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: bl-odoo
3
+ Version: 0.3.2
4
+ Summary: A command-line tool for managing Odoo dependencies.
5
+ Author-email: Your Name <your.email@example.com>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pyyaml>=6.0.3
11
+ Requires-Dist: rich
12
+ Requires-Dist: typer
13
+ Dynamic: license-file
14
+
15
+ # bl
16
+
17
+ ## Why BL
18
+
19
+ Because `ak` is slow and `bl` is fast
20
+
21
+ Because `ak` crashes if anything goes wrong
22
+
23
+ Because `ak` error are impossible to find
24
+
25
+ ## Install
26
+
27
+ `pipx install bl-odoo`
28
+
29
+ ## Usage
30
+
31
+ ### Build
32
+
33
+ ```bl build -c <path_to_spec.yaml> -z <path_to_frozen.yaml> -j <concurrency>```
34
+
35
+ #### Params
36
+ * `path_to_spec.yaml` should be the path to your spec (default: spec.yaml)
37
+ * `path_to_frozen.yaml` should be the path to your spec (default: frozen.yaml)
38
+ * `concurrency` number of module clone simultaneously (default: 28)
39
+
40
+ #### How it looks
41
+ <img width="1683" height="756" alt="bl_build" src="https://github.com/user-attachments/assets/22fc1565-3a54-4f57-9b85-a11263b9b536" />
42
+
43
+ ### Freeze
44
+
45
+ ```bl freeze -c <path_to_spec.yaml> -z <path_to_frozen.yaml> -j <concurrency>```
46
+
47
+ #### Params
48
+ * `path_to_spec.yaml` should be the path to your spec (default: spec.yaml)
49
+ * `path_to_frozen.yaml` should be the path to your spec (default: frozen.yaml)
50
+ * `concurrency` number of module clone simultaneously (default: 28)
51
+
52
+ ## Odoo is taking a really long time to clone
53
+
54
+ Yes !
55
+
56
+ You can add a locales entry to your odoo repo in `spec.yaml` like so:
57
+ ```
58
+ odoo:
59
+ modules:
60
+ - account
61
+ ...
62
+ remotes:
63
+ odoo: https://github.com/odoo/odoo
64
+ merges:
65
+ - odoo 14.0
66
+ locales:
67
+ - fr
68
+ - en
69
+ ```
70
+ It will only download the french and english translation instead of all of them
71
+ - without locales: 849MB and 40 seconds fresh build
72
+ - with locales fr, en: 169MB and 27 seconds fresh build
73
+
74
+ ## Benchmarks
75
+
76
+ ### Ak benchmarks
77
+ #### Fresh install
78
+ <img width="1462" height="347" alt="ak_bench_cold" src="https://github.com/user-attachments/assets/e29cd3d9-831c-43c1-8f29-e040ebee5740" />
79
+
80
+ #### Already cloned once
81
+ <img width="1419" height="356" alt="ak_bench_hot" src="https://github.com/user-attachments/assets/47b5756e-efe1-4272-82b7-e160f73af1be" />
82
+
83
+ ### Bl benchmarks
84
+ #### Fresh install
85
+ <img width="1335" height="343" alt="bl_bench_cold" src="https://github.com/user-attachments/assets/a64ba1c4-17bd-4017-acfd-5749df505f50" />
86
+
87
+ #### Already cloned once
88
+ <img width="1373" height="342" alt="bl_bench_hot" src="https://github.com/user-attachments/assets/b11e60c2-368b-496c-bc88-f5a765f44bfe" />
89
+
90
+ ### Results
91
+ |Type| AK | BL |
92
+ |----|----|----|
93
+ |Cold| ~100s | 2 - 10x faster |
94
+ |Hot| 3-20s | 2 - 10x faster |
95
+
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bl-odoo"
3
- version = "0.3.0"
3
+ version = "0.3.2"
4
4
  description = "A command-line tool for managing Odoo dependencies."
5
5
  authors = [
6
6
  { name="Your Name", email="your.email@example.com" },
bl_odoo-0.3.0/PKG-INFO DELETED
@@ -1,17 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: bl-odoo
3
- Version: 0.3.0
4
- Summary: A command-line tool for managing Odoo dependencies.
5
- Author-email: Your Name <your.email@example.com>
6
- License-Expression: MIT
7
- Requires-Python: >=3.9
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Requires-Dist: pyyaml>=6.0.3
11
- Requires-Dist: rich
12
- Requires-Dist: typer
13
- Dynamic: license-file
14
-
15
- # bl
16
-
17
- A new Python project.
bl_odoo-0.3.0/README.md DELETED
@@ -1,3 +0,0 @@
1
- # bl
2
-
3
- A new Python project.
@@ -1,17 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: bl-odoo
3
- Version: 0.3.0
4
- Summary: A command-line tool for managing Odoo dependencies.
5
- Author-email: Your Name <your.email@example.com>
6
- License-Expression: MIT
7
- Requires-Python: >=3.9
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Requires-Dist: pyyaml>=6.0.3
11
- Requires-Dist: rich
12
- Requires-Dist: typer
13
- Dynamic: license-file
14
-
15
- # bl
16
-
17
- A new Python project.
File without changes
File without changes
File without changes
File without changes