Repository: ansible/ansible-navigator (language: python)

Issue:
Switch to the use of `pathlib` where possible
as noted in #624

Switch to the use of `pathlib` where possible away from `os.path`


Discussion / hints:
https://gitlab.com/RoPP/flake8-use-pathlib

Fix patch:
diff --git a/share/ansible_navigator/utils/catalog_collections.py b/share/ansible_navigator/utils/catalog_collections.py
index a58bde5da..0179a22d5 100644
--- a/share/ansible_navigator/utils/catalog_collections.py
+++ b/share/ansible_navigator/utils/catalog_collections.py
@@ -12,9 +12,10 @@
 from collections import Counter
 from collections import OrderedDict
 from datetime import datetime
-from glob import glob
 from json.decoder import JSONDecodeError
+from pathlib import Path
 from typing import Dict
+from typing import Generator
 from typing import List
 from typing import Tuple
 
@@ -43,58 +44,56 @@
 class CollectionCatalog:
     """A collection cataloger."""
 
-    def __init__(self, directories: List[str]):
+    def __init__(self, directories: List[Path]):
         """Initialize the collection cataloger.
 
         :param directories: A list of directories that may contain collections
         """
-        self._directories = directories
+        self._directories: List[Path] = directories
         self._collections: OrderedDict[str, Dict] = OrderedDict()
         self._errors: List[Dict[str, str]] = []
         self._messages: List[str] = []
 
     def _catalog_plugins(self, collection: Dict) -> None:
-        # pylint: disable=too-many-locals
         """Catalog the plugins within a collection.
 
         :param collection: Details describing the collection
         """
-        path = collection["path"]
         file_checksums = {}
 
         file_manifest_file = collection.get("file_manifest_file", {}).get("name")
         if file_manifest_file:
-            file_path = f"{path}/{file_manifest_file}"
-            if os.path.exists(file_path):
+            file_path = Path(collection["path"], file_manifest_file)
+            if file_path.exists():
                 with open(file=file_path, encoding="utf-8") as fh:
                     try:
                         loaded = json.load(fh)
                         file_checksums = {v["name"]: v for v in loaded["files"]}
                     except (JSONDecodeError, KeyError) as exc:
-                        self._errors.append({"path": file_path, "error": str(exc)})
+                        self._errors.append({"path": str(file_path), "error": str(exc)})
 
         exempt = ["action", "module_utils", "doc_fragments"]
-        plugin_directory = os.path.join(path, "plugins")
-        if os.path.isdir(plugin_directory):
+        plugin_directory = Path(collection["path"], "plugins")
+        if plugin_directory.is_dir():
             plugin_dirs = [
-                (f.name, f.path)
-                for f in os.scandir(plugin_directory)
-                if f.is_dir() and f.name not in exempt
+                plugin_dir
+                for plugin_dir in plugin_directory.iterdir()
+                if plugin_dir.is_dir() and plugin_dir.name not in exempt
             ]
-            for plugin_type, path in plugin_dirs:
+            for plugin_dir in plugin_dirs:
+                plugin_type = plugin_dir.name
                 if plugin_type == "modules":
                     plugin_type = "module"
-                for (dirpath, _dirnames, filenames) in os.walk(path):
-                    self._process_plugin_dir(
-                        plugin_type,
-                        filenames,
-                        file_checksums,
-                        dirpath,
-                        collection,
-                    )
+                filenames = plugin_dir.glob("**/*.py")
+                self._process_plugin_dir(
+                    plugin_type,
+                    filenames,
+                    file_checksums,
+                    collection,
+                )
 
     @staticmethod
-    def _generate_checksum(file_path: str, relative_path: str) -> Dict:
+    def _generate_checksum(file_path: Path, relative_path: Path) -> Dict:
         """Generate a standard checksum for a file.
 
         :param file_path: The path to the file to generate a checksum for
@@ -117,62 +116,59 @@ def _generate_checksum(file_path: str, relative_path: str) -> Dict:
     def _process_plugin_dir(
         self,
         plugin_type: str,
-        filenames: List,
-        file_checksums: Dict,
-        dirpath: str,
+        filenames: Generator[Path, None, None],
+        file_checksums: Dict[str, Dict],
         collection: Dict,
     ) -> None:
-        # pylint: disable=too-many-arguments
         """Process each plugin within one plugin directory.
 
         :param plugin_type: The type of plugins
         :param filenames: The filenames of the plugins
         :param file_checksums: The checksums for the plugin files
-        :param dirpath: The path of the directory containing the plugins
         :param collection: The details of the collection
         """
         for filename in filenames:
-            file_path = f"{dirpath}/{filename}"
-            relative_path = file_path.replace(collection["path"], "")
-            _basename, extension = os.path.splitext(filename)
-            if not filename.startswith("__") and extension == ".py":
-                checksum_dict = file_checksums.get(relative_path)
-                if not checksum_dict:
-                    checksum_dict = self._generate_checksum(file_path, relative_path)
-                checksum = checksum_dict[f"chksum_{checksum_dict['chksum_type']}"]
-                collection["plugin_checksums"][checksum] = {
-                    "path": relative_path,
-                    "type": plugin_type,
-                }
-
-    def _one_path(self, directory: str) -> None:
+            if str(filename).startswith("__"):
+                continue
+
+            relative_path = Path(filename).relative_to(collection["path"])
+            checksum_dict = file_checksums.get(str(relative_path))
+            if not checksum_dict:
+                checksum_dict = self._generate_checksum(filename, relative_path)
+            checksum = checksum_dict[f"chksum_{checksum_dict['chksum_type']}"]
+            collection["plugin_checksums"][checksum] = {
+                "path": str(relative_path),
+                "type": plugin_type,
+            }
+
+    def _one_path(self, directory: Path) -> None:
         """Process the contents of an <...>/ansible_collections/ directory.
 
         :param directory: The path to collections directory to walk and load
         """
-        for directory_path in glob(f"{directory}/*/*/"):
-            manifest_file = f"{directory_path}/MANIFEST.json"
-            galaxy_file = f"{directory_path}/galaxy.yml"
+        for directory_path in directory.glob("*/*/"):
+            manifest_file = directory_path / "MANIFEST.json"
+            galaxy_file = directory_path / "galaxy.yml"
             collection = None
-            if os.path.exists(manifest_file):
+            if manifest_file.exists():
                 with open(file=manifest_file, encoding="utf-8") as fh:
                     try:
                         collection = json.load(fh)
                         collection["meta_source"] = "MANIFEST.json"
                     except JSONDecodeError:
                         error = {
-                            "path": os.path.dirname(manifest_file),
+                            "path": str(manifest_file),
                             "error": "failed to load MANIFEST.json",
                         }
                         self._errors.append(error)
-            elif os.path.exists(galaxy_file):
+            elif galaxy_file.exists():
                 with open(file=galaxy_file, encoding="utf-8") as fh:
                     try:
                         collection = {"collection_info": yaml.load(fh, Loader=SafeLoader)}
                         collection["meta_source"] = "galaxy.yml"
                     except YAMLError:
                         error = {
-                            "path": os.path.dirname(galaxy_file),
+                            "path": str(galaxy_file),
                             "error": "failed to load galaxy.yml",
                         }
                         self._errors.append(error)
@@ -182,16 +178,16 @@ def _one_path(self, directory: str) -> None:
                 collection["known_as"] = collection_name
                 collection["plugins"] = []
                 collection["plugin_checksums"] = {}
-                collection["path"] = directory_path
+                collection["path"] = str(directory_path)
 
-                runtime_file = f"{directory_path}/meta/runtime.yml"
+                runtime_file = directory_path / "meta" / "runtime.yml"
                 collection["runtime"] = {}
-                if os.path.exists(runtime_file):
+                if runtime_file.exists():
                     with open(file=runtime_file, encoding="utf-8") as fh:
                         try:
                             collection["runtime"] = yaml.load(fh, Loader=SafeLoader)
                         except YAMLError as exc:
-                            self._errors.append({"path": runtime_file, "error": str(exc)})
+                            self._errors.append({"path": str(runtime_file), "error": str(exc)})
 
                 self._collections[collection["path"]] = collection
             else:
@@ -223,8 +219,8 @@ def process_directories(self) -> Tuple[Dict, List]:
         :returns: All collections found and any errors
         """
         for directory in self._directories:
-            collection_directory = f"{directory}/ansible_collections"
-            if os.path.exists(collection_directory):
+            collection_directory = directory / "ansible_collections"
+            if collection_directory.exists():
                 self._one_path(collection_directory)
         for _collection_path, collection in self._collections.items():
             self._catalog_plugins(collection)
@@ -251,7 +247,7 @@ def worker(pending_queue: multiprocessing.Queue, completed_queue: multiprocessin
 
         try:
             (doc, examples, returndocs, metadata) = get_docstring(
-                filename=plugin_path,
+                filename=str(plugin_path),
                 fragment_loader=fragment_loader,
                 collection_name=collection_name,
             )
@@ -296,14 +292,14 @@ def identify_missing(collections: Dict, collection_cache: KeyValueStore) -> Tupl
                         (
                             collection["known_as"],
                             checksum,
-                            f"{collection['path']}{details['path']}",
+                            Path(collection["path"], details["path"]),
                         ),
                     )
                 handled.add(checksum)
     return handled, missing, plugin_count
 
 
-def parse_args():
+def parse_args() -> Tuple[argparse.Namespace, List[Path]]:
     """Parse the arguments from the command line.
 
     :returns: The parsed arguments and all directories to search
@@ -336,7 +332,7 @@ def parse_args():
 
     resolved = []
     for directory in directories:
-        realpath = os.path.realpath(directory)
+        realpath = Path(directory).resolve()
         if realpath not in resolved:
             resolved.append(realpath)
 
@@ -401,7 +397,7 @@ def retrieve_docs(
         elif message_type == "error":
             checksum, plugin_path, error = message
             collection_cache[checksum] = json.dumps({"error": error})
-            errors.append({"path": plugin_path, "error": error})
+            errors.append({"path": str(plugin_path), "error": error})
             stats["cache_added_errors"] += 1
 
 
@@ -439,8 +435,12 @@ def main() -> Dict:
     collections, errors = cc_obj.process_directories()
     stats["collection_count"] = len(collections)
 
-    collection_cache_path = os.path.abspath(os.path.expanduser(args.collection_cache_path))
-    collection_cache = KeyValueStore(collection_cache_path)
+    collection_cache_path = Path(args.collection_cache_path).resolve().expanduser()
+    # compatibility with py36, pass string to sqlite3.connect
+    if sys.version_info >= (3, 7):
+        collection_cache = KeyValueStore(collection_cache_path)
+    else:
+        collection_cache = KeyValueStore(str(collection_cache_path))
 
     handled, missing, plugin_count = identify_missing(collections, collection_cache)
     stats["plugin_count"] = plugin_count
@@ -477,7 +477,7 @@ def main() -> Dict:
 
     args, parent_directories = parse_args()
 
-    COLLECTION_SCAN_PATHS = ":".join(parent_directories)
+    COLLECTION_SCAN_PATHS = ":".join(str(parent) for parent in parent_directories)
     os.environ["ANSIBLE_COLLECTIONS_PATHS"] = COLLECTION_SCAN_PATHS
 
     result = main()


Test patch:
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/0.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/0.json
index bcab4285b..bbc227941 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/0.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/0.json
@@ -4,8 +4,8 @@
     "comment": "ansible-navigator collections browse window",
     "output": [
         "  NAME                       VERSION    SHADOWED    TYPE           PATH",
-        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/10.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/10.json
index 261ab5d4a..6cac87042 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/10.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/10.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/12.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/12.json
index 83e884c1c..a32441d32 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/12.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/12.json
@@ -4,8 +4,8 @@
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
         "  NAME                       VERSION    SHADOWED    TYPE           PATH",
-        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/2.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/2.json
index 247a35836..7113160d4 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/2.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/2.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/4.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/4.json
index 008474bbe..91f256277 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/4.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/4.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/6.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/6.json
index affcf5e8d..da8796a0f 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/6.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/6.json
@@ -4,8 +4,8 @@
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
         "  NAME                       VERSION    SHADOWED    TYPE           PATH",
-        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/8.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/8.json
index 9daa057b7..9a753e8c6 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/8.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee.py/test/8.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee_with_volmount.py/test/0.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee_with_volmount.py/test/0.json
index ad1893b49..bb4f7ab06 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_ee_with_volmount.py/test/0.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_ee_with_volmount.py/test/0.json
@@ -3,9 +3,9 @@
     "index": 0,
     "comment": "ansible-navigator collections browse window",
     "output": [
-        "  NAME                             VERSION      SHADOWED       TYPE              PATH",
-        "0│company_name.coll_1              1.0.0           False       bind_mount        /tmp/collections_to_volmount/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2              2.0.0           False       bind_mount        /tmp/collections_to_volmount/ansible_collections/company_name/coll_2/",
+        "  NAME                              VERSION      SHADOWED       TYPE               PATH",
+        "0│company_name.coll_1               1.0.0           False       bind_mount         /tmp/collections_to_volmount/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2               2.0.0           False       bind_mount         /tmp/collections_to_volmount/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/0.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/0.json
index 254297444..7509578a4 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/0.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/0.json
@@ -4,8 +4,8 @@
     "comment": "ansible-navigator collections browse window",
     "output": [
         "  NAME                         VERSION    SHADOWED     PATH",
-        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/10.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/10.json
index 6e59c098e..814f82ac8 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/10.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/10.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/12.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/12.json
index e30ac2117..76eaf4bd3 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/12.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/12.json
@@ -4,8 +4,8 @@
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
         "  NAME                         VERSION    SHADOWED     PATH",
-        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/2.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/2.json
index 9c5b6a727..703cc31bb 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/2.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/2.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/4.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/4.json
index 4ad315f91..8f3d75461 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/4.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/4.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/6.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/6.json
index 39a154805..38855812e 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/6.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/6.json
@@ -4,8 +4,8 @@
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
         "  NAME                         VERSION    SHADOWED     PATH",
-        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/8.json b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/8.json
index 337f0497e..ea8ced51c 100644
--- a/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/8.json
+++ b/tests/fixtures/integration/actions/collections/test_direct_interactive_noee.py/test/8.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_direct_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/1.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/1.json
index 1377168d6..1ef2b7d4b 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/1.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/1.json
@@ -4,8 +4,8 @@
     "comment": "ansible-navigator collections top window",
     "output": [
         "  NAME                       VERSION    SHADOWED    TYPE           PATH",
-        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/11.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/11.json
index 8d48f227a..dcfaa05f0 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/11.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/11.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/13.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/13.json
index 235ac35c7..4a34007ce 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/13.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/13.json
@@ -4,8 +4,8 @@
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
         "  NAME                       VERSION    SHADOWED    TYPE           PATH",
-        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/3.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/3.json
index d7a436bdc..592bd2c1a 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/3.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/3.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/5.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/5.json
index 8a766d3dd..2d0112f76 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/5.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/5.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/7.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/7.json
index 8f519272b..d5ed8e6f7 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/7.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/7.json
@@ -4,8 +4,8 @@
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
         "  NAME                       VERSION    SHADOWED    TYPE           PATH",
-        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        "0│company_name.coll_1        1.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2        2.0.0         False    bind_mount     FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/9.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/9.json
index fe8f6cc9c..9e7f4d1f7 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/9.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_ee.py/test/9.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_ee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/1.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/1.json
index 3f0e96ed4..900bccfb1 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/1.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/1.json
@@ -3,9 +3,9 @@
     "index": 1,
     "comment": "ansible-navigator collections top window",
     "output": [
-        "  NAME                        VERSION    SHADOWED     PATH",
-        "0│company_name.coll_1         1.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2         2.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        "  NAME                         VERSION    SHADOWED     PATH",
+        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/11.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/11.json
index ee61b3969..8705e635a 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/11.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/11.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/13.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/13.json
index 3bfa9a233..88fa02393 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/13.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/13.json
@@ -3,9 +3,9 @@
     "index": 13,
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
-        "  NAME                        VERSION    SHADOWED     PATH",
-        "0│company_name.coll_1         1.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2         2.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        "  NAME                         VERSION    SHADOWED     PATH",
+        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/3.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/3.json
index 5a2af1c1f..2e6f0dbd2 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/3.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/3.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/5.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/5.json
index 3778ba83a..df5705eb4 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/5.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/5.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_1",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 1.0.0",
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/7.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/7.json
index 230e8d452..d0fa81b34 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/7.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/7.json
@@ -3,9 +3,9 @@
     "index": 7,
     "comment": "Back to ansible-navigator collections browse window",
     "output": [
-        "  NAME                        VERSION    SHADOWED     PATH",
-        "0│company_name.coll_1         1.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1/",
-        "1│company_name.coll_2         2.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        "  NAME                         VERSION    SHADOWED     PATH",
+        "0│company_name.coll_1          1.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_1",
+        "1│company_name.coll_2          2.0.0         False     FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         "^f/PgUp page up                     ^b/PgDn page down                     ↑↓ scroll                     esc back                     [0-9] goto                     :help help"
     ]
 }
diff --git a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/9.json b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/9.json
index 72f35e247..0b88524f2 100644
--- a/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/9.json
+++ b/tests/fixtures/integration/actions/collections/test_welcome_interactive_noee.py/test/9.json
@@ -12,7 +12,7 @@
         " 5│  license_file: LICENSE",
         " 6│  name: company_name.coll_2",
         " 7│  namespace: company_name",
-        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2/",
+        " 8│  path: FIXTURES_COLLECTION_DIR/test_welcome_interactive_noee.py/collections/ansible_collections/company_name/coll_2",
         " 9│  readme: README.md",
         "10│  shadowed_by: []",
         "11│  version: 2.0.0",