Repository: DavidVujic/python-polylith

Issue:
poly check: should use data from project-specific lock files, and not use the loose comparison between names.
### Discussed in https://github.com/DavidVujic/python-polylith/discussions/266

<div type='discussions-op-text'>

<sup>Originally posted by **enadeau** September 21, 2024</sup>


The `poly check` command doesn't report on missing library when the root lock file includes the dependency. When having a `lock` file specific for a project, it should verify the library based on that.

Discussion:

Solution patch:
diff --git a/components/polylith/commands/check.py b/components/polylith/commands/check.py
index e44bc32..d0c282f 100644
--- a/components/polylith/commands/check.py
+++ b/components/polylith/commands/check.py
@@ -55,16 +55,21 @@ def run(root: Path, ns: str, project_data: dict, options: dict) -> bool:
     deps = project_data["deps"]
     alias = options["alias"]
 
+    from_lock_file = libs.is_from_lock_file(deps)
+
     collected_imports = check.report.collect_all_imports(root, ns, project_data)
     collected_libs = distributions.known_aliases_and_sub_dependencies(
-        deps, alias, options
+        deps,
+        alias,
+        options,
+        from_lock_file,
     )
 
     details = check.report.create_report(
         project_data,
         collected_imports,
         collected_libs,
-        is_strict,
+        is_strict or from_lock_file,
     )
 
     res = all([not details["brick_diff"], not details["libs_diff"]])
diff --git a/components/polylith/commands/libs.py b/components/polylith/commands/libs.py
index f8951b8..bd15362 100644
--- a/components/polylith/commands/libs.py
+++ b/components/polylith/commands/libs.py
@@ -3,7 +3,7 @@
 from typing import List, Set
 
 from polylith import distributions
-from polylith.libs import report
+from polylith.libs import is_from_lock_file, report
 
 
 def missing_libs(project_data: dict, imports: dict, options: dict) -> bool:
@@ -15,15 +15,17 @@ def missing_libs(project_data: dict, imports: dict, options: dict) -> bool:
 
     brick_imports = imports[name]
 
+    from_lock_file = is_from_lock_file(deps)
+
     libs = distributions.known_aliases_and_sub_dependencies(
-        deps, library_alias, options
+        deps, library_alias, options, from_lock_file
     )
 
     return report.print_missing_installed_libs(
         brick_imports,
         libs,
         name,
-        is_strict,
+        is_strict or from_lock_file,
     )
 
 
diff --git a/components/polylith/distributions/collect.py b/components/polylith/distributions/collect.py
index dc97f96..5beb9ad 100644
--- a/components/polylith/distributions/collect.py
+++ b/components/polylith/distributions/collect.py
@@ -30,7 +30,7 @@ def extract_library_names(deps: dict) -> Set[str]:
 
 
 def known_aliases_and_sub_dependencies(
-    deps: dict, library_alias: list, options: dict
+    deps: dict, library_alias: list, options: dict, from_lock_file: bool,
 ) -> Set[str]:
     """Collect known aliases (packages) for third-party libraries.
 
@@ -38,7 +38,6 @@ def known_aliases_and_sub_dependencies(
     collect sub-dependencies and distribution top-namespace for each library, and append to the result.
     """
 
-    lock_file = any(str.endswith(deps["source"], s) for s in {".lock", ".txt"})
     third_party_libs = extract_library_names(deps)
 
     fn = options.get("dists_fn", get_distributions)
@@ -46,7 +45,7 @@ def known_aliases_and_sub_dependencies(
 
     dist_packages = distributions_packages(dists)
     custom_aliases = alias.parse(library_alias)
-    sub_deps = distributions_sub_packages(dists) if not lock_file else {}
+    sub_deps = distributions_sub_packages(dists) if not from_lock_file else {}
 
     a = alias.pick(dist_packages, third_party_libs)
     b = alias.pick(custom_aliases, third_party_libs)
diff --git a/components/polylith/libs/__init__.py b/components/polylith/libs/__init__.py
index 59af018..171aff2 100644
--- a/components/polylith/libs/__init__.py
+++ b/components/polylith/libs/__init__.py
@@ -1,11 +1,12 @@
 from polylith.libs import report
 from polylith.libs.grouping import extract_third_party_imports, get_third_party_imports
-from polylith.libs.lock_files import extract_libs, pick_lock_file
+from polylith.libs.lock_files import extract_libs, is_from_lock_file, pick_lock_file
 
 __all__ = [
     "report",
     "extract_third_party_imports",
     "get_third_party_imports",
     "extract_libs",
+    "is_from_lock_file",
     "pick_lock_file",
 ]
diff --git a/components/polylith/libs/lock_files.py b/components/polylith/libs/lock_files.py
index 5371020..c9110b9 100644
--- a/components/polylith/libs/lock_files.py
+++ b/components/polylith/libs/lock_files.py
@@ -71,3 +71,7 @@ def extract_libs(project_data: dict, filename: str, filetype: str) -> dict:
         return extract_lib_names_from_txt(path)
     except (IndexError, KeyError, ValueError) as e:
         raise ValueError(f"Failed reading {filename}: {repr(e)}") from e
+
+
+def is_from_lock_file(deps: dict) -> bool:
+    return any(deps["source"] == s for s in set(patterns.keys()))
diff --git a/projects/poetry_polylith_plugin/pyproject.toml b/projects/poetry_polylith_plugin/pyproject.toml
index 1de34a6..5b58067 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.29.0"
+version = "1.30.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 4567f39..41470ea 100644
--- a/projects/polylith_cli/pyproject.toml
+++ b/projects/polylith_cli/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "polylith-cli"
-version = "1.17.0"
+version = "1.18.0"
 description = "Python tooling support for the Polylith Architecture"
 authors = ['David Vujic']
 homepage = "https://davidvujic.github.io/python-polylith-docs/"


Test patch:
diff --git a/test/components/polylith/distributions/test_collect.py b/test/components/polylith/distributions/test_collect.py
index 50fe7de..5fc3c02 100644
--- a/test/components/polylith/distributions/test_collect.py
+++ b/test/components/polylith/distributions/test_collect.py
@@ -38,7 +38,7 @@ def test_collect_known_aliases_and_sub_dependencies():
 
     fake_alias = ["hello-world-library=hello"]
 
-    res = collect.known_aliases_and_sub_dependencies(fake_deps, fake_alias, {})
+    res = collect.known_aliases_and_sub_dependencies(fake_deps, fake_alias, {}, False)
 
     assert "typer" in res
     assert "typing-extensions" in res