python-package-folder 5.2.1__tar.gz → 5.2.2__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.
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/PKG-INFO +1 -1
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/coverage.svg +2 -2
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/pyproject.toml +1 -1
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/python_package_folder.py +19 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/version_calculator.py +23 -4
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_version_calculator.py +33 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.copier-answers.yml +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.cursor/plans/optional_version_+_semantic-release_efed88a6.plan.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.cursor/plans/replace_node.js_semantic-release_with_custom_python_implementation_64e05e1a.plan.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.cursor/rules/general.mdc +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.cursor/rules/python.mdc +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.github/workflows/ci.yml +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.github/workflows/publish.yml +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.gitignore +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/.vscode/settings.json +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/LICENSE +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/MANIFEST.in +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/Makefile +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/README.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/development.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/docs/DEVELOPMENT.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/docs/INSTALLATION.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/docs/PUBLISHING.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/docs/REFERENCE.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/docs/USAGE.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/docs/VERSION_RESOLUTION.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/installation.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/publishing.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/__init__.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/__main__.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/analyzer.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/finder.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/manager.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/publisher.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/py.typed +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/subfolder_build.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/types.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/utils.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/version.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/conftest.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/some_globals.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/subfolder_to_build/README.md +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/subfolder_to_build/__init__.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/subfolder_to_build/some_function.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/subfolder_to_build/some_globals.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/utility_folder/_SS/some_superseded_file.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/utility_folder/some_utility.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_build_with_external_deps.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_exclude_patterns.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_linting.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_preserve_directory_structure.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_publisher.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_shared_subdirectory_imports.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_spreadsheet_creation_imports.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_subfolder_build.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_third_party_dependencies.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_utils.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_version_manager.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/tests.py +0 -0
- {python_package_folder-5.2.1 → python_package_folder-5.2.2}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-package-folder
|
|
3
|
-
Version: 5.2.
|
|
3
|
+
Version: 5.2.2
|
|
4
4
|
Summary: Python package to automatically package and build a folder, fetching all relevant dependencies.
|
|
5
5
|
Project-URL: Repository, https://github.com/alelom/python-package-folder
|
|
6
6
|
Author-email: Alessio Lombardi <work@alelom.com>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
15
15
|
<text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
|
|
16
16
|
<text x="31.5" y="14">coverage</text>
|
|
17
|
-
<text x="81" y="15" fill="#010101" fill-opacity=".3">
|
|
18
|
-
<text x="81" y="14">
|
|
17
|
+
<text x="81" y="15" fill="#010101" fill-opacity=".3">67%</text>
|
|
18
|
+
<text x="81" y="14">67%</text>
|
|
19
19
|
</g>
|
|
20
20
|
</svg>
|
|
@@ -186,6 +186,21 @@ def main() -> int:
|
|
|
186
186
|
repository = args.publish if args.publish else None
|
|
187
187
|
repository_url = args.repository_url if args.publish else None
|
|
188
188
|
|
|
189
|
+
# Get credentials for authenticated registry queries (especially Azure Artifacts)
|
|
190
|
+
# Try to get them from args or environment variables
|
|
191
|
+
query_username = args.username
|
|
192
|
+
query_password = args.password
|
|
193
|
+
|
|
194
|
+
# If not provided via args, check environment variables (for Azure Artifacts)
|
|
195
|
+
if repository == "azure" and not query_username:
|
|
196
|
+
query_username = os.getenv("TWINE_USERNAME") or os.getenv("PYPI_USERNAME")
|
|
197
|
+
if repository == "azure" and not query_password:
|
|
198
|
+
query_password = (
|
|
199
|
+
os.getenv("TWINE_PASSWORD")
|
|
200
|
+
or os.getenv("PYPI_PASSWORD")
|
|
201
|
+
or os.getenv("AZURE_ARTIFACTS_TOKEN")
|
|
202
|
+
)
|
|
203
|
+
|
|
189
204
|
if is_subfolder:
|
|
190
205
|
# Workflow 1: subfolder build
|
|
191
206
|
# src_dir is guaranteed to be relative to project_root due to is_subfolder check
|
|
@@ -199,6 +214,8 @@ def main() -> int:
|
|
|
199
214
|
subfolder_path=subfolder_rel_path,
|
|
200
215
|
repository=repository,
|
|
201
216
|
repository_url=repository_url,
|
|
217
|
+
username=query_username,
|
|
218
|
+
password=query_password,
|
|
202
219
|
)
|
|
203
220
|
else:
|
|
204
221
|
# Workflow 2: main package
|
|
@@ -221,6 +238,8 @@ def main() -> int:
|
|
|
221
238
|
subfolder_path=None,
|
|
222
239
|
repository=repository,
|
|
223
240
|
repository_url=repository_url,
|
|
241
|
+
username=query_username,
|
|
242
|
+
password=query_password,
|
|
224
243
|
)
|
|
225
244
|
|
|
226
245
|
if resolved_version:
|
|
@@ -25,6 +25,8 @@ def query_registry_version(
|
|
|
25
25
|
package_name: str,
|
|
26
26
|
repository: str,
|
|
27
27
|
repository_url: str | None = None,
|
|
28
|
+
username: str | None = None,
|
|
29
|
+
password: str | None = None,
|
|
28
30
|
) -> str | None:
|
|
29
31
|
"""
|
|
30
32
|
Query package registry for the latest published version.
|
|
@@ -33,6 +35,8 @@ def query_registry_version(
|
|
|
33
35
|
package_name: Package name to query
|
|
34
36
|
repository: Repository type ('pypi', 'testpypi', or 'azure')
|
|
35
37
|
repository_url: Repository URL (required for Azure Artifacts)
|
|
38
|
+
username: Optional username for authenticated queries (Azure Artifacts)
|
|
39
|
+
password: Optional password/token for authenticated queries (Azure Artifacts)
|
|
36
40
|
|
|
37
41
|
Returns:
|
|
38
42
|
Latest version string or None if not found/unsupported
|
|
@@ -54,7 +58,7 @@ def query_registry_version(
|
|
|
54
58
|
logger.warning("Azure Artifacts repository URL not provided")
|
|
55
59
|
return None
|
|
56
60
|
logger.info(f"Querying Azure Artifacts for package '{package_name}' at {repository_url}")
|
|
57
|
-
version = _query_azure_artifacts_version(package_name, repository_url)
|
|
61
|
+
version = _query_azure_artifacts_version(package_name, repository_url, username, password)
|
|
58
62
|
if version:
|
|
59
63
|
logger.info(f"Found version {version} on Azure Artifacts")
|
|
60
64
|
else:
|
|
@@ -184,6 +188,8 @@ class SimpleIndexParser(HTMLParser):
|
|
|
184
188
|
def _query_azure_artifacts_version(
|
|
185
189
|
package_name: str,
|
|
186
190
|
repository_url: str,
|
|
191
|
+
username: str | None = None,
|
|
192
|
+
password: str | None = None,
|
|
187
193
|
) -> str | None:
|
|
188
194
|
"""
|
|
189
195
|
Query Azure Artifacts for the latest version.
|
|
@@ -194,6 +200,8 @@ def _query_azure_artifacts_version(
|
|
|
194
200
|
Args:
|
|
195
201
|
package_name: Package name to query
|
|
196
202
|
repository_url: Azure Artifacts repository URL
|
|
203
|
+
username: Optional username for authentication
|
|
204
|
+
password: Optional password/token for authentication
|
|
197
205
|
|
|
198
206
|
Returns:
|
|
199
207
|
Latest version string or None if not found/unsupported
|
|
@@ -212,8 +220,15 @@ def _query_azure_artifacts_version(
|
|
|
212
220
|
return None
|
|
213
221
|
|
|
214
222
|
try:
|
|
215
|
-
|
|
216
|
-
|
|
223
|
+
# Prepare authentication if credentials are provided
|
|
224
|
+
auth = None
|
|
225
|
+
if username and password:
|
|
226
|
+
auth = (username, password)
|
|
227
|
+
logger.info(f"Fetching Azure Artifacts simple index for '{package_name}' with authentication...")
|
|
228
|
+
else:
|
|
229
|
+
logger.info(f"Fetching Azure Artifacts simple index for '{package_name}' (no authentication)...")
|
|
230
|
+
|
|
231
|
+
response = requests.get(simple_index_url, auth=auth, timeout=10)
|
|
217
232
|
logger.info(f"Azure Artifacts response: status={response.status_code}, content_length={len(response.text)} bytes")
|
|
218
233
|
|
|
219
234
|
if response.status_code == 401:
|
|
@@ -628,6 +643,8 @@ def resolve_version(
|
|
|
628
643
|
subfolder_path: Path | None = None,
|
|
629
644
|
repository: str | None = None,
|
|
630
645
|
repository_url: str | None = None,
|
|
646
|
+
username: str | None = None,
|
|
647
|
+
password: str | None = None,
|
|
631
648
|
) -> tuple[str | None, str | None]:
|
|
632
649
|
"""
|
|
633
650
|
Resolve the next version using conventional commits.
|
|
@@ -640,6 +657,8 @@ def resolve_version(
|
|
|
640
657
|
subfolder_path: Optional path to subfolder (relative to project_root)
|
|
641
658
|
repository: Optional target repository ('pypi', 'testpypi', or 'azure')
|
|
642
659
|
repository_url: Optional repository URL (required for Azure Artifacts)
|
|
660
|
+
username: Optional username for authenticated registry queries (Azure Artifacts)
|
|
661
|
+
password: Optional password/token for authenticated registry queries (Azure Artifacts)
|
|
643
662
|
|
|
644
663
|
Returns:
|
|
645
664
|
Tuple of (version string if a release is determined, error message if any)
|
|
@@ -651,7 +670,7 @@ def resolve_version(
|
|
|
651
670
|
baseline_version = None
|
|
652
671
|
if repository and package_name:
|
|
653
672
|
logger.info(f"Attempting to query {repository} for baseline version of '{package_name}'")
|
|
654
|
-
baseline_version = query_registry_version(package_name, repository, repository_url)
|
|
673
|
+
baseline_version = query_registry_version(package_name, repository, repository_url, username, password)
|
|
655
674
|
|
|
656
675
|
# Step 2: Fallback to git tags if registry query failed
|
|
657
676
|
if not baseline_version:
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_version_calculator.py
RENAMED
|
@@ -151,6 +151,39 @@ class TestQueryRegistryVersion:
|
|
|
151
151
|
# Should return None when no versions found in HTML
|
|
152
152
|
assert version is None
|
|
153
153
|
|
|
154
|
+
@patch("python_package_folder.version_calculator.requests.get")
|
|
155
|
+
def test_query_azure_artifacts_version_with_auth(self, mock_get: MagicMock) -> None:
|
|
156
|
+
"""Test querying Azure Artifacts with authentication."""
|
|
157
|
+
mock_response = Mock()
|
|
158
|
+
mock_response.status_code = 200
|
|
159
|
+
mock_response.text = """<!DOCTYPE html>
|
|
160
|
+
<html>
|
|
161
|
+
<head>
|
|
162
|
+
<title>Links for test-package</title>
|
|
163
|
+
</head>
|
|
164
|
+
<body>
|
|
165
|
+
<h1>Links for test-package</h1>
|
|
166
|
+
<a href="test-package-1.0.0-py3-none-any.whl">test-package-1.0.0-py3-none-any.whl</a>
|
|
167
|
+
<a href="test-package-1.1.0-py3-none-any.whl">test-package-1.1.0-py3-none-any.whl</a>
|
|
168
|
+
</body>
|
|
169
|
+
</html>"""
|
|
170
|
+
mock_get.return_value = mock_response
|
|
171
|
+
|
|
172
|
+
version = query_registry_version(
|
|
173
|
+
"test-package",
|
|
174
|
+
"azure",
|
|
175
|
+
repository_url="https://pkgs.dev.azure.com/ORG/PROJECT/_packaging/FEED/pypi/upload",
|
|
176
|
+
username="testuser",
|
|
177
|
+
password="testtoken",
|
|
178
|
+
)
|
|
179
|
+
# Should parse HTML and return the latest version
|
|
180
|
+
assert version == "1.1.0"
|
|
181
|
+
|
|
182
|
+
# Verify authentication was used
|
|
183
|
+
mock_get.assert_called_once()
|
|
184
|
+
call_args = mock_get.call_args
|
|
185
|
+
assert call_args[1]["auth"] == ("testuser", "testtoken")
|
|
186
|
+
|
|
154
187
|
@patch("python_package_folder.version_calculator.requests.get")
|
|
155
188
|
def test_query_registry_version_error_handling(self, mock_get: MagicMock) -> None:
|
|
156
189
|
"""Test that registry query errors are handled gracefully."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/__init__.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/__main__.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/analyzer.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/finder.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/manager.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/publisher.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/types.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/utils.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/src/python_package_folder/version.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/folder_structure/some_globals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_build_with_external_deps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.1 → python_package_folder-5.2.2}/tests/test_third_party_dependencies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|