Skip to content

Commit ef83faf

Browse files
authored
feat(poly sync): suggest adding available bases, and used components, to empty projects (#369)
* refactor(projects): separate project creation prompt from adding bricks to a project * feat(poly sync): interactively add bricks for empty projects * fix(interactive): sort possible bases by closest match * fix(unused bricks): look for unused in projects only * bump CLI to 1.34.0 * bump Poetry plugin to 1.41.0
1 parent f12acdd commit ef83faf

File tree

5 files changed

+75
-32
lines changed

5 files changed

+75
-32
lines changed

components/polylith/commands/sync.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,42 @@
11
from pathlib import Path
2+
from typing import Union
23

3-
from polylith import sync
4+
from polylith import info, project, sync
5+
6+
7+
def is_project_without_bricks(project_data: dict) -> bool:
8+
bases = project_data["bases"]
9+
components = project_data["components"]
10+
11+
return not bases and not components
12+
13+
14+
def choose_base(root: Path, ns: str, project_data: dict) -> Union[str, None]:
15+
possible_bases = info.find_unused_bases(root, ns)
16+
17+
if not possible_bases:
18+
return None
19+
20+
return project.interactive.choose_base_for_project(
21+
root, ns, project_data["name"], possible_bases
22+
)
23+
24+
25+
def calculate_brick_diff(root: Path, ns: str, project_data: dict) -> dict:
26+
if info.is_project(project_data) and is_project_without_bricks(project_data):
27+
base = choose_base(root, ns, project_data)
28+
29+
if base:
30+
return sync.calculate_needed_bricks(root, ns, project_data, base)
31+
32+
return sync.calculate_diff(root, ns, project_data)
433

534

635
def run(root: Path, ns: str, project_data: dict, options: dict):
736
is_quiet = options["quiet"]
837
is_verbose = options["verbose"]
938

10-
diff = sync.calculate_diff(root, ns, project_data)
39+
diff = calculate_brick_diff(root, ns, project_data)
1140

1241
sync.update_project(root, ns, diff)
1342

components/polylith/info/collect.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import difflib
21
from pathlib import Path
32
from typing import List, Set
43

54
from polylith.bricks import base, component
5+
from polylith.info.report import is_project
66
from polylith.project import get_packages_for_projects, parse_package_paths
77

88

@@ -60,14 +60,8 @@ def find_unused_bases(root: Path, ns: str) -> Set[str]:
6060
projects_data = get_projects_data(root, ns)
6161

6262
bases = get_bases(root, ns)
63-
bases_in_projects = set().union(*[p["bases"] for p in projects_data])
6463

65-
return set(bases).difference(bases_in_projects)
66-
67-
68-
def sort_bases_by_closest_match(bases: Set[str], name: str) -> List[str]:
69-
closest = difflib.get_close_matches(name, bases, cutoff=0.3)
64+
bases_per_project = [p["bases"] for p in projects_data if is_project(p)]
65+
bases_in_projects = set().union(*bases_per_project)
7066

71-
rest = sorted([b for b in bases if b not in closest])
72-
73-
return closest + rest
67+
return set(bases).difference(bases_in_projects)

components/polylith/project/interactive.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import difflib
12
from pathlib import Path
2-
from typing import List, Set
3+
from typing import List, Set, Union
34

45
from polylith import configuration, info, repo, sync
56
from polylith.reporting import theme
@@ -44,28 +45,27 @@ def confirmation(diff: dict, project_name: str) -> None:
4445
console.print(components_message)
4546

4647

47-
def add_bricks_to_project(
48-
root: Path,
49-
ns: str,
50-
project_name: str,
51-
possible_bases: List[str],
52-
) -> None:
53-
projects_data = info.get_projects_data(root, ns)
54-
project_data = next((p for p in projects_data if p["name"] == project_name), None)
48+
def sort_bases_by_closest_match(bases: Set[str], name: str) -> List[str]:
49+
closest = difflib.get_close_matches(name, bases, cutoff=0.3)
5550

56-
if not project_data:
57-
return
51+
rest = sorted([b for b in bases if b not in closest])
52+
53+
return closest + rest
5854

59-
message = f"[data]Project [proj]{project_name}[/] created.[/]"
60-
console.print(Padding(message, (0, 0, 1, 0)))
6155

62-
first, *_ = possible_bases
56+
def choose_base_for_project(
57+
root: Path,
58+
ns: str,
59+
project_name: str,
60+
possible_bases: Set[str],
61+
) -> Union[str, None]:
62+
first, *_ = sort_bases_by_closest_match(possible_bases, project_name)
6363

6464
if not Confirm.ask(
6565
prompt=f"[data]Do you want to add bricks to the [proj]{project_name}[/] project?[/]",
6666
console=console,
6767
):
68-
return
68+
return None
6969

7070
question = "[data]What's the name of the Polylith [base]base[/] to add?[/]"
7171

@@ -78,7 +78,18 @@ def add_bricks_to_project(
7878
)
7979

8080
all_bases = info.get_bases(root, ns)
81-
found_base = next((b for b in all_bases if str.lower(b) == str.lower(base)), None)
81+
82+
return next((b for b in all_bases if str.lower(b) == str.lower(base)), None)
83+
84+
85+
def add_bricks_to_project(
86+
root: Path,
87+
ns: str,
88+
project_data: dict,
89+
possible_bases: Set[str],
90+
) -> None:
91+
project_name = project_data["name"]
92+
found_base = choose_base_for_project(root, ns, project_name, possible_bases)
8293

8394
if not found_base:
8495
confirmation({}, project_name)
@@ -95,9 +106,18 @@ def run(project_name: str) -> None:
95106
root = repo.get_workspace_root(Path.cwd())
96107
ns = configuration.get_namespace_from_config(root)
97108

98-
possible_bases = sorted(info.find_unused_bases(root, ns))
109+
possible_bases = info.find_unused_bases(root, ns)
99110

100111
if not possible_bases:
101112
return
102113

103-
add_bricks_to_project(root, ns, project_name, possible_bases)
114+
projects_data = info.get_projects_data(root, ns)
115+
project_data = next((p for p in projects_data if p["name"] == project_name), None)
116+
117+
if not project_data:
118+
return
119+
120+
message = f"[data]Project [proj]{project_name}[/] created.[/]"
121+
console.print(Padding(message, (0, 0, 1, 0)))
122+
123+
add_bricks_to_project(root, ns, project_data, possible_bases)

projects/poetry_polylith_plugin/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "poetry-polylith-plugin"
3-
version = "1.40.1"
3+
version = "1.41.0"
44
description = "A Poetry plugin that adds tooling support for the Polylith Architecture"
55
authors = ["David Vujic"]
66
homepage = "https://davidvujic.github.io/python-polylith-docs/"

projects/polylith_cli/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "polylith-cli"
3-
version = "1.33.1"
3+
version = "1.34.0"
44
description = "Python tooling support for the Polylith Architecture"
55
authors = ['David Vujic']
66
homepage = "https://davidvujic.github.io/python-polylith-docs/"

0 commit comments

Comments
 (0)