diff --git a/bases/polylith/cli/core.py b/bases/polylith/cli/core.py index 4057f0b3..2fef3150 100644 --- a/bases/polylith/cli/core.py +++ b/bases/polylith/cli/core.py @@ -68,6 +68,7 @@ def enriched_with_lock_files_data( def info_command( short: Annotated[bool, options.short_workspace] = False, save: Annotated[bool, options.save] = False, + group: Annotated[str, options.group] = "", ): """Info about the Polylith workspace.""" root = repo.get_workspace_root(Path.cwd()) @@ -77,6 +78,7 @@ def info_command( "short": short, "save": save, "output": output, + "groups": set(str.split(group, ",")) if group else set(), } commands.info.run(root, cli_options) diff --git a/bases/polylith/cli/options.py b/bases/polylith/cli/options.py index 45720831..9a7b4c14 100644 --- a/bases/polylith/cli/options.py +++ b/bases/polylith/cli/options.py @@ -20,3 +20,5 @@ brick = Option(help="Shows dependencies for selected brick.") save = Option(help="Store the contents of this command to file.") interface = Option(help="Show the brick interface.") + +group = Option(help="Show contents based on configured project group.") diff --git a/components/polylith/commands/check.py b/components/polylith/commands/check.py index ae4d117b..f148f0f5 100644 --- a/components/polylith/commands/check.py +++ b/components/polylith/commands/check.py @@ -80,7 +80,7 @@ def run_each( is_strict = options["strict"] is_verbose = options["verbose"] - name = project_data["name"] + name = project_data.get("alias") or project_data["name"] deps = project_data["deps"] alias = options["alias"] diff --git a/components/polylith/commands/info.py b/components/polylith/commands/info.py index 84ee83fc..f8a28ca4 100644 --- a/components/polylith/commands/info.py +++ b/components/polylith/commands/info.py @@ -9,9 +9,17 @@ def run(root: Path, options: dict): components = info.get_components(root, ns) projects_data = info.get_bricks_in_projects(root, components, bases, ns) + groups = options.get("groups") + + filtered = ( + [p for p in projects_data if p["groups"].intersection(groups)] + if groups + else projects_data + ) + info.print_workspace_summary(projects_data, bases, components, options) if not components and not bases: return - info.print_bricks_in_projects(projects_data, bases, components, options) + info.print_bricks_in_projects(filtered or projects_data, bases, components, options) diff --git a/components/polylith/configuration/__init__.py b/components/polylith/configuration/__init__.py index 4529da2a..a5a12a4b 100644 --- a/components/polylith/configuration/__init__.py +++ b/components/polylith/configuration/__init__.py @@ -2,6 +2,8 @@ get_brick_structure_from_config, get_namespace_from_config, get_output_dir, + get_project_alias_from_config, + get_project_groups_from_config, get_resources_structure_from_config, get_tag_pattern_from_config, get_tag_sort_options_from_config, @@ -15,6 +17,8 @@ "get_brick_structure_from_config", "get_namespace_from_config", "get_output_dir", + "get_project_alias_from_config", + "get_project_groups_from_config", "get_resources_structure_from_config", "get_tag_pattern_from_config", "get_tag_sort_options_from_config", diff --git a/components/polylith/configuration/core.py b/components/polylith/configuration/core.py index 70aa1519..21264684 100644 --- a/components/polylith/configuration/core.py +++ b/components/polylith/configuration/core.py @@ -1,35 +1,49 @@ from pathlib import Path -from typing import List, Union +from typing import List, Set, Union from polylith import repo -def get_namespace_from_config(path: Path) -> str: +def get_polylith_config(path: Path) -> dict: toml: dict = repo.load_workspace_config(path) - return toml["tool"]["polylith"]["namespace"] + conf = toml.get("tool", {}).get("polylith") + + if not conf: + message = "Cannot find a [tool.polylith] configuration." + raise ValueError(message) + + return conf + + +def get_namespace_from_config(path: Path) -> str: + conf = get_polylith_config(path) + ns = conf.get("namespace") + if not ns: + message = "Cannot find a [tool.polylith.namespace] section." + raise ValueError(message) -def get_git_tag_pattern(toml: dict) -> str: - """Fallback git tag pattern configuration""" - return toml["tool"]["polylith"]["git_tag_pattern"] + return ns def get_tag_pattern_from_config(path: Path, key: Union[str, None]) -> Union[str, None]: - toml: dict = repo.load_workspace_config(path) + conf = get_polylith_config(path) - patterns = toml["tool"]["polylith"].get("tag", {}).get("patterns") + patterns = conf.get("tag", {}).get("patterns") + fallback = conf.get("git_tag_pattern") if not key: - return patterns["stable"] if patterns else get_git_tag_pattern(toml) + stable = patterns.get("stable") if patterns else None + return stable or fallback - return patterns.get(key) + return patterns.get(key) if patterns else None def get_tag_sort_options_from_config(path: Path) -> List[str]: - toml: dict = repo.load_workspace_config(path) + conf = get_polylith_config(path) - options = toml["tool"]["polylith"].get("tag", {}).get("sorting") + options = conf.get("tag", {}).get("sorting") # Default sorting option if options is None: return ["-committerdate"] @@ -37,23 +51,23 @@ def get_tag_sort_options_from_config(path: Path) -> List[str]: def is_test_generation_enabled(path: Path) -> bool: - toml: dict = repo.load_workspace_config(path) + conf = get_polylith_config(path) + enabled = conf.get("test", {}).get("enabled") - enabled = toml["tool"]["polylith"]["test"]["enabled"] return bool(enabled) def is_readme_generation_enabled(path: Path) -> bool: - toml: dict = repo.load_workspace_config(path) + conf = get_polylith_config(path) + enabled = conf.get("resources", {}).get("brick_docs_enabled") - enabled = toml["tool"]["polylith"].get("resources", {}).get("brick_docs_enabled") return bool(enabled) def get_theme_from_config(path: Path) -> str: - toml: dict = repo.load_workspace_config(path) + conf = get_polylith_config(path) - return toml["tool"]["polylith"]["structure"].get("theme") or "tdd" + return conf.get("structure", {}).get("theme") or "tdd" def get_brick_structure_from_config(path: Path) -> str: @@ -84,15 +98,38 @@ def get_resources_structure_from_config(path: Path) -> str: def get_output_dir(path: Path, command_name: str) -> str: - toml: dict = repo.load_workspace_config(path) + conf = get_polylith_config(path) key = "output" - tool = toml["tool"]["polylith"] - commands = tool.get("commands", {}) - command = commands.get(command_name, {}) + commands = conf.get("commands") or {} + command = commands.get(command_name) or {} output = command.get(key) or commands.get(key) fallback = f"{repo.development_dir}/poly" return output or fallback + + +def get_projects_config(path: Path) -> dict: + conf = get_polylith_config(path) + + return conf.get("projects", {}) + + +def get_project_alias_from_config(path: Path, project_name: str) -> Union[str, None]: + projects_conf = get_projects_config(path) + alias = projects_conf.get("alias", {}) + + return alias.get(project_name) + + +def get_project_groups_from_config(path: Path, project_name: str) -> Set[str]: + projects_conf = get_projects_config(path) + + groups = projects_conf.get("groups") or {} + + if not groups: + return set() + + return {k for k, v in groups.items() if project_name in v} diff --git a/components/polylith/diff/report.py b/components/polylith/diff/report.py index ed1835e0..d71a0571 100644 --- a/components/polylith/diff/report.py +++ b/components/polylith/diff/report.py @@ -15,7 +15,7 @@ def print_diff_details( console = Console(theme=theme.poly_theme) options = {"command": "diff"} - table = info.report.build_bricks_in_projects_table( + table = info.build_bricks_in_projects_table( projects_data, bases, components, options ) diff --git a/components/polylith/info/__init__.py b/components/polylith/info/__init__.py index 4498745d..c6335972 100644 --- a/components/polylith/info/__init__.py +++ b/components/polylith/info/__init__.py @@ -6,6 +6,7 @@ get_projects_data, ) from polylith.info.report import ( + build_bricks_in_projects_table, is_project, print_bricks_in_projects, print_workspace_summary, @@ -17,6 +18,7 @@ "get_bricks_in_projects", "get_components", "get_projects_data", + "build_bricks_in_projects_table", "is_project", "print_bricks_in_projects", "print_workspace_summary", diff --git a/components/polylith/info/report.py b/components/polylith/info/report.py index b89cbc5f..b8daa780 100644 --- a/components/polylith/info/report.py +++ b/components/polylith/info/report.py @@ -21,12 +21,14 @@ def is_project(project: dict) -> bool: def printable_name(project: dict, short: bool) -> str: + alias = project.get("alias") + if is_project(project): template = "[proj]{name}[/]" - name = project["name"] + name = alias or project["name"] else: template = "[data]{name}[/]" - name = "development" + name = alias or "development" if short: return template.format(name="\n".join(name)) @@ -92,6 +94,8 @@ def print_workspace_summary( options: dict, ) -> None: save = options.get("save", False) + groups = ", ".join(options.get("groups") or set()) + console = Console(theme=theme.poly_theme, record=save) console.print(Padding("[data]Workspace summary[/]", (1, 0, 1, 0))) @@ -106,5 +110,8 @@ def print_workspace_summary( console.print(f"[base]bases[/]: [data]{number_of_bases}[/]") console.print(f"[data]development[/]: [data]{number_of_dev}[/]") + if groups: + console.print(Padding(f"[data]group[/]: [proj]{groups}[/]", (1, 0, 0, 0))) + if save: output.save_recorded(console, options, "workspace_summary") diff --git a/components/polylith/libs/report.py b/components/polylith/libs/report.py index 63b31c93..d2329e63 100644 --- a/components/polylith/libs/report.py +++ b/components/polylith/libs/report.py @@ -135,11 +135,7 @@ def get_version(lib: str, project_data: dict) -> str: return project_data["deps"]["items"].get(lib) -def find_version( - lib: str, project_name: str, projects_data: List[dict] -) -> Union[str, None]: - project_data = next(p for p in projects_data if p["name"] == project_name) - +def find_version(lib: str, project_data: dict) -> Union[str, None]: return get_version(lib, project_data) @@ -147,6 +143,12 @@ def printable_header(header: str, short: bool) -> str: return "\n".join(header) if short else header +def printable_project_header(project_data: dict, short: bool) -> str: + name = project_data.get("alias") or project_data["name"] + + return printable_header(name, short) + + def is_same_version(versions: list) -> bool: unique = {v for v in versions if v} @@ -163,16 +165,16 @@ def libs_in_projects_table( short = options["short"] - project_names = sorted({p["name"] for p in projects_data}) - project_headers = [f"[proj]{printable_header(n, short)}[/]" for n in project_names] + projects = sorted(projects_data, key=lambda p: p["name"]) + proj_headers = [f"[proj]{printable_project_header(p, short)}[/]" for p in projects] dev_header = printable_header("development", short) - headers = ["[data]library[/]"] + project_headers + [f"[data]{dev_header}[/]"] + headers = ["[data]library[/]"] + proj_headers + [f"[data]{dev_header}[/]"] for header in headers: table.add_column(header) for lib in sorted(libraries): - proj_versions = [find_version(lib, n, projects_data) for n in project_names] + proj_versions = [find_version(lib, p) for p in projects] dev_version = get_version(lib, development_data) is_same = is_same_version(proj_versions + [dev_version]) diff --git a/components/polylith/poetry/commands/command_options.py b/components/polylith/poetry/commands/command_options.py index 637bb4f7..5e41cf66 100644 --- a/components/polylith/poetry/commands/command_options.py +++ b/components/polylith/poetry/commands/command_options.py @@ -33,3 +33,11 @@ description="More strict checks when matching name and version of third-party libraries and imports.", flag=True, ) + + +group = option( + long_name="group", + description="Show contents based on configured project group", + flag=False, + multiple=True, +) diff --git a/components/polylith/poetry/commands/info.py b/components/polylith/poetry/commands/info.py index 8110c31b..91c5cbbc 100644 --- a/components/polylith/poetry/commands/info.py +++ b/components/polylith/poetry/commands/info.py @@ -9,7 +9,7 @@ class InfoCommand(Command): name = "poly info" description = "Info about the Polylith workspace." - options = [command_options.save, command_options.short] + options = [command_options.save, command_options.short, command_options.group] def handle(self) -> int: short = True if self.option("short") else False @@ -22,6 +22,7 @@ def handle(self) -> int: "short": short, "save": save, "output": output, + "groups": set(self.option("group") or []), } commands.info.run(root, options) diff --git a/components/polylith/project/get.py b/components/polylith/project/get.py index 34653798..8eeb5951 100644 --- a/components/polylith/project/get.py +++ b/components/polylith/project/get.py @@ -1,6 +1,6 @@ from functools import lru_cache from pathlib import Path -from typing import List +from typing import List, Set, Union import tomlkit from polylith import configuration, repo, toml @@ -23,6 +23,18 @@ def get_project_name_from_toml(data: dict) -> str: raise KeyError(f"Error in {path}") from e +def get_project_alias(path: Path, data: dict) -> Union[str, None]: + project_name = get_project_name_from_toml(data) + + return configuration.get_project_alias_from_config(path, project_name) + + +def get_project_groups(path: Path, data: dict) -> Set[str]: + project_name = get_project_name_from_toml(data) + + return configuration.get_project_groups_from_config(path, project_name) + + @lru_cache def get_toml(path: Path) -> tomlkit.TOMLDocument: return toml.read_toml_document(path) @@ -58,6 +70,8 @@ def get_packages_for_projects(root: Path) -> List[dict]: return [ { "name": get_project_name_from_toml(d), + "alias": get_project_alias(root, d), + "groups": get_project_groups(root, d), "packages": toml.get_project_package_includes(namespace, d["toml"]), "path": d["path"], "type": d["type"], diff --git a/components/polylith/sync/collect.py b/components/polylith/sync/collect.py index fbddc3b6..85610488 100644 --- a/components/polylith/sync/collect.py +++ b/components/polylith/sync/collect.py @@ -46,6 +46,7 @@ def _calculate(root: Path, namespace: str, project_data: dict, bases: Set[str]) return { "name": project_data["name"], + "alias": project_data["alias"], "path": project_data["path"], "is_project": is_project, "bases": bases_diff if is_project else fn(bases_diff, "bases"), diff --git a/components/polylith/sync/report.py b/components/polylith/sync/report.py index 08b47922..6c913318 100644 --- a/components/polylith/sync/report.py +++ b/components/polylith/sync/report.py @@ -13,7 +13,7 @@ def print_summary(diff: dict) -> None: console = Console(theme=theme.poly_theme) is_project = diff["is_project"] - name = diff["name"] if is_project else "development" + name = diff["alias"] or diff["name"] if is_project else "development" bases = diff["bases"] components = diff["components"] diff --git a/projects/pdm_polylith_bricks/pyproject.toml b/projects/pdm_polylith_bricks/pyproject.toml index e182eb75..272e554d 100644 --- a/projects/pdm_polylith_bricks/pyproject.toml +++ b/projects/pdm_polylith_bricks/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pdm-polylith-bricks" -version = "1.3.7" +version = "1.3.8" description = "a PDM build hook for Polylith" authors = ["David Vujic"] homepage = "https://davidvujic.github.io/python-polylith-docs/" diff --git a/projects/pdm_polylith_workspace/pyproject.toml b/projects/pdm_polylith_workspace/pyproject.toml index b7b4560f..f4622cb3 100644 --- a/projects/pdm_polylith_workspace/pyproject.toml +++ b/projects/pdm_polylith_workspace/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pdm-polylith-workspace" -version = "1.3.7" +version = "1.3.8" description = "a PDM build hook for a Polylith workspace" homepage = "https://davidvujic.github.io/python-polylith-docs/" repository = "https://github.com/davidvujic/python-polylith" diff --git a/projects/poetry_polylith_plugin/pyproject.toml b/projects/poetry_polylith_plugin/pyproject.toml index 90dfa126..cdb52938 100644 --- a/projects/poetry_polylith_plugin/pyproject.toml +++ b/projects/poetry_polylith_plugin/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "poetry-polylith-plugin" -version = "1.49.1" +version = "1.50.0" description = "A Poetry plugin that adds tooling support for the Polylith Architecture" authors = ["David Vujic"] homepage = "https://davidvujic.github.io/python-polylith-docs/" diff --git a/projects/polylith_cli/pyproject.toml b/projects/polylith_cli/pyproject.toml index 55bb732d..74d0fa1a 100644 --- a/projects/polylith_cli/pyproject.toml +++ b/projects/polylith_cli/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "polylith-cli" -version = "1.43.1" +version = "1.44.0" description = "Python tooling support for the Polylith Architecture" authors = ['David Vujic'] homepage = "https://davidvujic.github.io/python-polylith-docs/" diff --git a/test/components/polylith/configuration/test_core.py b/test/components/polylith/configuration/test_core.py index 842ac84e..e48acac7 100644 --- a/test/components/polylith/configuration/test_core.py +++ b/test/components/polylith/configuration/test_core.py @@ -21,6 +21,14 @@ [tool.polylith.test] enabled = true + +[tool.polylith.projects.alias] +my-project-with-a-long-name = "first" +my-other-project-that-also-has-a-long-name = "second" + +[tool.polylith.projects.groups] +accounting = ["the-accounting-project", "my-project-with-a-long-name"] +handlers = ["my-project-with-a-long-name", "other-handler-project"] """ @@ -136,3 +144,19 @@ def test_get_structure_for_tdd_theme(use_tdd): assert brick == "{brick}/{package}/src/{namespace}/{package}" assert test == "{brick}/{package}/test/{namespace}/{package}" assert resources == "{brick}/{package}" + + +def test_get_project_alias_from_config(use_loose): + first = core.get_project_alias_from_config(fake_path, "my-project-with-a-long-name") + other = core.get_project_alias_from_config(fake_path, "unknown") + + assert first == "first" + assert other is None + + +def test_get_project_groups_from_config(use_loose): + first = core.get_project_groups_from_config(fake_path, "my-project-with-a-long-name") + other = core.get_project_groups_from_config(fake_path, "unknown") + + assert first == {"accounting", "handlers"} + assert other == set() diff --git a/workspace.toml b/workspace.toml index 45649af2..926d4d83 100644 --- a/workspace.toml +++ b/workspace.toml @@ -10,3 +10,14 @@ release = "v[0-9]*" [tool.polylith.test] enabled = true + +[tool.polylith.projects.alias] +hatch-polylith-bricks = "hatch" +pdm-polylith-bricks = "pdm-bricks" +pdm-polylith-workspace = "pdm-workspace" +poetry-polylith-plugin = "poetry-plugin" +polylith-cli = "cli" + +[tool.polylith.projects.groups] +hooks = ["hatch-polylith-bricks", "pdm-polylith-bricks", "pdm-polylith-workspace"] +command-line = ["poetry-polylith-plugin", "polylith-cli"]