ducktools-pythonfinder 0.8.2__tar.gz → 0.8.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {ducktools_pythonfinder-0.8.2/src/ducktools_pythonfinder.egg-info → ducktools_pythonfinder-0.8.4}/PKG-INFO +3 -2
  2. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/scripts/build_zipapp.py +1 -1
  3. ducktools_pythonfinder-0.8.4/scripts/detail_this_python.py +32 -0
  4. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/scripts/list_python_venvs.py +1 -1
  5. ducktools_pythonfinder-0.8.4/src/ducktools/pythonfinder/_version.py +2 -0
  6. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/linux/pyenv_search.py +5 -0
  7. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/win32/pyenv_search.py +7 -0
  8. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4/src/ducktools_pythonfinder.egg-info}/PKG-INFO +3 -2
  9. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/conftest.py +1 -1
  10. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_orgsearch.py +1 -1
  11. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_pyenv.py +60 -3
  12. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_uv_finder.py +1 -1
  13. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_venv_finder.py +1 -1
  14. ducktools_pythonfinder-0.8.2/scripts/detail_this_python.py +0 -25
  15. ducktools_pythonfinder-0.8.2/src/ducktools/pythonfinder/_version.py +0 -2
  16. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/.gitignore +0 -0
  17. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/LICENSE +0 -0
  18. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/MANIFEST.in +0 -0
  19. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/README.md +0 -0
  20. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/pyproject.toml +0 -0
  21. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/scripts/print_python_versions.py +0 -0
  22. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/setup.cfg +0 -0
  23. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/__init__.py +0 -0
  24. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/__main__.py +0 -0
  25. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/darwin/__init__.py +0 -0
  26. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/details_script.py +0 -0
  27. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/linux/__init__.py +0 -0
  28. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/package_list_script.py +0 -0
  29. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/pythonorg_search.py +0 -0
  30. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/shared.py +0 -0
  31. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/venv.py +0 -0
  32. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/win32/__init__.py +0 -0
  33. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools/pythonfinder/win32/registry_search.py +0 -0
  34. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools_pythonfinder.egg-info/SOURCES.txt +0 -0
  35. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools_pythonfinder.egg-info/dependency_links.txt +0 -0
  36. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools_pythonfinder.egg-info/entry_points.txt +0 -0
  37. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools_pythonfinder.egg-info/requires.txt +0 -0
  38. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/src/ducktools_pythonfinder.egg-info/top_level.txt +0 -0
  39. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/sources/python_versions.txt +0 -0
  40. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/sources/release.json +0 -0
  41. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/sources/release_file.json +0 -0
  42. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_cache.py +0 -0
  43. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_details_script.py +0 -0
  44. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_foldersearch.py +0 -0
  45. {ducktools_pythonfinder-0.8.2 → ducktools_pythonfinder-0.8.4}/tests/test_shared.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: ducktools-pythonfinder
3
- Version: 0.8.2
3
+ Version: 0.8.4
4
4
  Summary: Cross platform tool to find available python installations
5
5
  Author: David C Ellis
6
6
  Project-URL: Homepage, https://github.com/davidcellis/ducktools-pythonfinder
@@ -25,6 +25,7 @@ Provides-Extra: testing
25
25
  Requires-Dist: pytest; extra == "testing"
26
26
  Requires-Dist: pytest-cov; extra == "testing"
27
27
  Requires-Dist: pyfakefs; extra == "testing"
28
+ Dynamic: license-file
28
29
 
29
30
  # ducktools: pythonfinder #
30
31
 
@@ -1,7 +1,7 @@
1
1
  # ducktools-pythonfinder
2
2
  # MIT License
3
3
  #
4
- # Copyright (c) 2013-2014 David C Ellis
4
+ # Copyright (c) 2023-2025 David C Ellis
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,32 @@
1
+ # ducktools-pythonfinder
2
+ # MIT License
3
+ #
4
+ # Copyright (c) 2024-2025 David C Ellis
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ """
25
+ Get the PythonInstall for the python version running
26
+ """
27
+
28
+ import sys
29
+
30
+ from ducktools.pythonfinder.shared import get_install_details
31
+
32
+ print(get_install_details(sys.executable))
@@ -1,7 +1,7 @@
1
1
  # ducktools-pythonfinder
2
2
  # MIT License
3
3
  #
4
- # Copyright (c) 2013-2014 David C Ellis
4
+ # Copyright (c) 2023-2025 David C Ellis
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,2 @@
1
+ __version__ = "0.8.4"
2
+ __version_tuple__ = (0, 8, 4)
@@ -91,6 +91,11 @@ def get_pyenv_pythons(
91
91
 
92
92
  with finder:
93
93
  for p in sorted(os.scandir(versions_folder), key=lambda x: x.path):
94
+ # Don't include folders that are venvs
95
+ venv_indicator = os.path.join(p.path, "pyvenv.cfg")
96
+ if os.path.exists(venv_indicator):
97
+ continue
98
+
94
99
  executable = os.path.join(p.path, "bin/python")
95
100
  if os.path.exists(executable):
96
101
  install = finder.get_install_details(executable, managed_by="pyenv")
@@ -53,6 +53,13 @@ def get_pyenv_pythons(
53
53
 
54
54
  with finder:
55
55
  for p in os.scandir(versions_folder):
56
+ # On windows, venv folders usually have the python.exe in \Scripts\
57
+ # while runtimes have it in the base folder so venvs shouldn't be disovered
58
+ # but exclude them early anyway
59
+ venv_indicator = os.path.join(p.path, "pyvenv.cfg")
60
+ if os.path.exists(venv_indicator):
61
+ continue
62
+
56
63
  path_base = os.path.basename(p.path)
57
64
 
58
65
  if path_base.startswith("pypy"):
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: ducktools-pythonfinder
3
- Version: 0.8.2
3
+ Version: 0.8.4
4
4
  Summary: Cross platform tool to find available python installations
5
5
  Author: David C Ellis
6
6
  Project-URL: Homepage, https://github.com/davidcellis/ducktools-pythonfinder
@@ -25,6 +25,7 @@ Provides-Extra: testing
25
25
  Requires-Dist: pytest; extra == "testing"
26
26
  Requires-Dist: pytest-cov; extra == "testing"
27
27
  Requires-Dist: pyfakefs; extra == "testing"
28
+ Dynamic: license-file
28
29
 
29
30
  # ducktools: pythonfinder #
30
31
 
@@ -1,7 +1,7 @@
1
1
  # ducktools-pythonfinder
2
2
  # MIT License
3
3
  #
4
- # Copyright (c) 2013-2014 David C Ellis
4
+ # Copyright (c) 2023-2025 David C Ellis
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,7 +1,7 @@
1
1
  # ducktools-pythonfinder
2
2
  # MIT License
3
3
  #
4
- # Copyright (c) 2013-2014 David C Ellis
4
+ # Copyright (c) 2023-2025 David C Ellis
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the "Software"), to deal
@@ -94,9 +94,16 @@ def test_mock_versions_folder(temp_finder):
94
94
  patch("os.scandir") as scandir_mock, \
95
95
  patch.object(DetailFinder, "get_install_details") as details_mock:
96
96
 
97
+ assert os.path.exists is exists_mock
98
+
97
99
  return_val = PythonInstall.from_str(version=out_ver, executable=out_executable, managed_by="pyenv")
98
100
  details_mock.return_value = return_val
99
- exists_mock.return_value = True
101
+
102
+ def false_on_venv_check(pth):
103
+ # Need to return False on the venv check, but True on all other exists checks
104
+ return False if pth.endswith("pyvenv.cfg") else True
105
+
106
+ exists_mock.side_effect = false_on_venv_check
100
107
  scandir_mock.return_value = iter([mock_dir_entry])
101
108
 
102
109
  python_versions = list(get_pyenv_pythons(versions_folder=versions_folder, finder=temp_finder))
@@ -106,6 +113,40 @@ def test_mock_versions_folder(temp_finder):
106
113
  assert python_versions == [return_val]
107
114
 
108
115
 
116
+ def test_mock_folder_skip_venv(temp_finder):
117
+ # If the venv check returns true, make sure the folder is skipped
118
+ mock_dir_entry = Mock(os.DirEntry)
119
+
120
+ out_ver = "3.12.1"
121
+ if sys.platform == "win32":
122
+ versions_folder = os.path.join("c:", "fake", "versions")
123
+ out_executable = os.path.join(versions_folder, out_ver, "python.exe")
124
+ else:
125
+ versions_folder = "~/fake/versions"
126
+ out_executable = os.path.join(versions_folder, out_ver, "bin/python")
127
+
128
+ mock_dir_entry.name = out_ver
129
+ mock_dir_entry.path = os.path.join(versions_folder, out_ver)
130
+
131
+ with patch("os.path.exists") as exists_mock, \
132
+ patch("os.scandir") as scandir_mock, \
133
+ patch.object(DetailFinder, "get_install_details") as details_mock:
134
+
135
+ assert os.path.exists is exists_mock
136
+
137
+ return_val = PythonInstall.from_str(version=out_ver, executable=out_executable, managed_by="pyenv")
138
+ details_mock.return_value = return_val
139
+
140
+ exists_mock.return_value = True
141
+ scandir_mock.return_value = iter([mock_dir_entry])
142
+
143
+ python_versions = list(get_pyenv_pythons(versions_folder=versions_folder, finder=temp_finder))
144
+
145
+ details_mock.assert_not_called()
146
+
147
+ assert python_versions == []
148
+
149
+
109
150
  @pytest.mark.skipif(sys.platform != "win32", reason="Test for Windows only")
110
151
  def test_fs_versions_win(fs, temp_finder):
111
152
  # Test with folders in fake file system
@@ -125,7 +166,15 @@ def test_fs_versions_win(fs, temp_finder):
125
166
 
126
167
  details_mock.assert_called_once_with(py_exe, managed_by="pyenv")
127
168
 
128
- assert versions == [PythonInstall.from_str(version="3.12.1", executable=py_exe, managed_by="pyenv")]
169
+ assert versions == [return_val]
170
+
171
+ # Check presence of a 'pyvenv.cfg' ignores the folder
172
+ details_mock.reset_mock()
173
+ fs.create_file(os.path.join(py_folder, "pyvenv.cfg"))
174
+
175
+ versions = list(get_pyenv_pythons(tmpdir, finder=temp_finder))
176
+ details_mock.assert_not_called()
177
+ assert versions == []
129
178
 
130
179
 
131
180
  @pytest.mark.skipif(sys.platform == "win32", reason="Test for non-Windows only")
@@ -148,7 +197,15 @@ def test_fs_versions_nix(fs, temp_finder):
148
197
  versions = list(get_pyenv_pythons(tmpdir, finder=temp_finder))
149
198
  details_mock.assert_called_once_with(py_exe, managed_by="pyenv")
150
199
 
151
- assert versions == [PythonInstall.from_str(version="3.12.1", executable=py_exe, managed_by="pyenv")]
200
+ assert versions == [return_val]
201
+
202
+ details_mock.reset_mock()
203
+
204
+ # Test the same folder is ignored if a 'pyvenv.cfg' file is discovered
205
+ fs.create_file(os.path.join(py_folder, "pyvenv.cfg"))
206
+ versions = list(get_pyenv_pythons(tmpdir, finder=temp_finder))
207
+ details_mock.assert_not_called()
208
+ assert versions == []
152
209
 
153
210
 
154
211
  @pytest.mark.skipif(sys.platform == "win32", reason="Test for non-Windows only")
@@ -1,7 +1,7 @@
1
1
  # ducktools-pythonfinder
2
2
  # MIT License
3
3
  #
4
- # Copyright (c) 2013-2014 David C Ellis
4
+ # Copyright (c) 2023-2025 David C Ellis
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,7 +1,7 @@
1
1
  # ducktools-pythonfinder
2
2
  # MIT License
3
3
  #
4
- # Copyright (c) 2013-2014 David C Ellis
4
+ # Copyright (c) 2023-2025 David C Ellis
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,25 +0,0 @@
1
- # ducktools-pythonfinder
2
- # Copyright (C) 2024 David C Ellis
3
- #
4
- # This program is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU Lesser General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU Lesser General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU Lesser General Public License
15
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
-
17
- """
18
- Get the PythonInstall for the python version running
19
- """
20
-
21
- import sys
22
-
23
- from ducktools.pythonfinder.shared import get_install_details
24
-
25
- print(get_install_details(sys.executable))
@@ -1,2 +0,0 @@
1
- __version__ = "0.8.2"
2
- __version_tuple__ = (0, 8, 2)