Repository: DavidVujic/python-polylith

Issue:
(poetry plugin) Third-party import lookup fails for some libraries (example: python-jose).
**Describe the bug**
The `poly check` and `poly libs` commands should pick up the top level name from the distribution. But in this case - `python-jose` - it doesn't. Probably because of an unexpected format in the `top_level.txt` of the distribution.


Discussion:
sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=DavidVujic_python-polylith&pullRequest=230) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=DavidVujic_python-polylith&pullRequest=230&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=DavidVujic_python-polylith&pullRequest=230&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=DavidVujic_python-polylith&pullRequest=230&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=DavidVujic_python-polylith&pullRequest=230&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=DavidVujic_python-polylith&pullRequest=230&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=DavidVujic_python-polylith&pullRequest=230)



Patch:
diff --git a/components/polylith/distributions/collect.py b/components/polylith/distributions/collect.py
index 6fbe858..c55bc42 100644
--- a/components/polylith/distributions/collect.py
+++ b/components/polylith/distributions/collect.py
@@ -1,3 +1,4 @@
+from functools import reduce
 from typing import Set
 
 from polylith import alias
@@ -9,6 +10,25 @@ from polylith.distributions.core import (
 )
 
 
+def extract_extras(name: str) -> Set[str]:
+    chars = ["[", "]"]
+    replacement = ","
+
+    res = reduce(lambda acc, char: str.replace(acc, char, replacement), chars, name)
+
+    parts = str.split(res, replacement)
+
+    return {str.strip(p) for p in parts if p}
+
+
+def extract_library_names(deps: dict) -> Set[str]:
+    names = {k for k, _v in deps["items"].items()}
+
+    with_extras = [extract_extras(n) for n in names]
+
+    return set().union(*with_extras)
+
+
 def known_aliases_and_sub_dependencies(deps: dict, library_alias: list) -> Set[str]:
     """Collect known aliases (packages) for third-party libraries.
 
@@ -17,7 +37,7 @@ def known_aliases_and_sub_dependencies(deps: dict, library_alias: list) -> Set[s
     """
 
     lock_file = any(str.endswith(deps["source"], s) for s in {".lock", ".txt"})
-    third_party_libs = {k for k, _v in deps["items"].items()}
+    third_party_libs = extract_library_names(deps)
 
     dists = get_distributions()
 
diff --git a/components/polylith/distributions/core.py b/components/polylith/distributions/core.py
index 6886d54..6e1f458 100644
--- a/components/polylith/distributions/core.py
+++ b/components/polylith/distributions/core.py
@@ -25,10 +25,16 @@ def map_sub_packages(acc, dist) -> dict:
     return {**acc, **dist_subpackages(dist)}
 
 
+def parsed_top_level_namespace(namespaces: List[str]) -> List[str]:
+    return [str.replace(ns, "/", ".") for ns in namespaces]
+
+
 def top_level_packages(dist) -> List[str]:
     top_level = dist.read_text("top_level.txt")
 
-    return str.split(top_level or "")
+    namespaces = str.split(top_level or "")
+
+    return parsed_top_level_namespace(namespaces)
 
 
 def mapped_packages(dist) -> dict:
diff --git a/projects/poetry_polylith_plugin/pyproject.toml b/projects/poetry_polylith_plugin/pyproject.toml
index 19abaff..35b2c8c 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.23.0"
+version = "1.23.1"
 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 4950f07..88936d3 100644
--- a/projects/polylith_cli/pyproject.toml
+++ b/projects/polylith_cli/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "polylith-cli"
-version = "1.10.0"
+version = "1.10.1"
 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
new file mode 100644
index 0000000..89bbe8b
--- /dev/null
+++ b/test/components/polylith/distributions/test_collect.py
@@ -0,0 +1,30 @@
+from polylith.distributions import collect
+
+
+def test_parse_third_party_library_name():
+    fake_project_deps = {
+        "items": {
+            "python": "^3.10",
+            "fastapi": "^0.110.0",
+            "uvicorn[standard]": "^0.27.1",
+            "python-jose[cryptography]": "^3.3.0",
+            "hello[world, something]": "^3.3.0"
+        },
+        "source": "pyproject.toml",
+    }
+
+    expected = {
+        "python",
+        "fastapi",
+        "uvicorn",
+        "standard",
+        "python-jose",
+        "cryptography",
+        "hello",
+        "world",
+        "something",
+    }
+
+    res = collect.extract_library_names(fake_project_deps)
+
+    assert res == expected
diff --git a/test/components/polylith/distributions/test_core.py b/test/components/polylith/distributions/test_core.py
index a0e0a3f..862097e 100644
--- a/test/components/polylith/distributions/test_core.py
+++ b/test/components/polylith/distributions/test_core.py
@@ -5,6 +5,15 @@ import pytest
 from polylith import distributions
 
 
+class FakeDist:
+    def __init__(self, name: str, data: str):
+        self.data = data
+        self.metadata = {"name": name}
+
+    def read_text(self, *args):
+        return self.data
+
+
 def test_distribution_packages():
     dists = list(importlib.metadata.distributions())
 
@@ -17,6 +26,18 @@ def test_distribution_packages():
     assert res[expected_dist] == [expected_package]
 
 
+def test_distribution_packages_parse_contents_of_top_level_txt():
+    dists = [FakeDist("python-jose", "jose\njose/backends\n")]
+
+    res = distributions.distributions_packages(dists)
+
+    expected_dist = "python-jose"
+    expected_packages = ["jose", "jose.backends"]
+
+    assert res.get(expected_dist) is not None
+    assert res[expected_dist] == expected_packages
+
+
 def test_parse_package_name_from_dist_requires():
     expected = {
         "greenlet": "greenlet !=0.4.17",