From 5d02bed770a537282e5fcb7d3ab1cec127dd6f40 Mon Sep 17 00:00:00 2001 From: Alexandre Hannud Abdo Date: Mon, 26 Apr 2021 20:34:54 -0300 Subject: [PATCH] Get the correct version when passed multiple paths This emulates more closely the behavior of an actual import statement by: 1. traversing `sys.path` in reverse so we keep the first module found. 2. checking if there is actually a module at `path / i_item` to avoid false positives. I've checked both behaviors in concrete cases and they both match the python interpreter now, when previously they didn't. An example where both 1. and 2. are necessary is when `sys.path` is '/usr/lib:/usr/local/lib/pythonX.Y/site-packages/:/usr/lib/pythonX.Y/site-packages/' and different versions of the package are installed in the last two paths. Notice how `os.walk` will traverse '/lib/pythonX.Y/site-packages/' for the first path ('/usr/lib'), despite the fact that there's nothing to import from there, and that traversing the paths in direct order would result in the last path overwriting the version from the middle path, which comes first in import order. --- pipreqs/pipreqs.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 20aae68..65bc40c 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -209,7 +209,7 @@ def get_imports_info( def get_locally_installed_packages(encoding=None): packages = {} ignore = ["tests", "_tests", "egg", "EGG", "info"] - for path in sys.path: + for path in reversed(sys.path): for root, dirs, files in os.walk(path): for item in files: if "top_level" in item: @@ -223,7 +223,11 @@ def get_locally_installed_packages(encoding=None): continue for i_item in package_import: if ((i_item not in ignore) and - (package[0] not in ignore)): + (package[0] not in ignore) and + ( + os.path.isdir(os.path.join(path, i_item)) or + os.path.isfile(os.path.join(path, i_item + '.py')) + )): version = None if len(package) > 1: version = package[1].replace(