python-package-folder 5.2.2__tar.gz → 5.2.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.
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/PKG-INFO +1 -1
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/pyproject.toml +1 -1
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/manager.py +8 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/publisher.py +18 -6
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/python_package_folder.py +8 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/subfolder_build.py +9 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/version_calculator.py +236 -4
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.copier-answers.yml +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.cursor/plans/optional_version_+_semantic-release_efed88a6.plan.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.cursor/plans/replace_node.js_semantic-release_with_custom_python_implementation_64e05e1a.plan.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.cursor/rules/general.mdc +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.cursor/rules/python.mdc +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.github/workflows/ci.yml +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.github/workflows/publish.yml +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.gitignore +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/.vscode/settings.json +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/LICENSE +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/MANIFEST.in +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/Makefile +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/README.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/coverage.svg +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/development.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/docs/DEVELOPMENT.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/docs/INSTALLATION.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/docs/PUBLISHING.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/docs/REFERENCE.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/docs/USAGE.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/docs/VERSION_RESOLUTION.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/installation.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/publishing.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/__init__.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/__main__.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/analyzer.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/finder.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/py.typed +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/types.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/utils.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/version.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/conftest.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/some_globals.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/subfolder_to_build/README.md +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/subfolder_to_build/__init__.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/subfolder_to_build/some_function.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/subfolder_to_build/some_globals.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/utility_folder/_SS/some_superseded_file.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/folder_structure/utility_folder/some_utility.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_build_with_external_deps.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_exclude_patterns.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_linting.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_preserve_directory_structure.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_publisher.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_shared_subdirectory_imports.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_spreadsheet_creation_imports.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_subfolder_build.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_third_party_dependencies.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_utils.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_version_calculator.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_version_manager.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/tests.py +0 -0
- {python_package_folder-5.2.2 → python_package_folder-5.2.4}/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.4
|
|
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>
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/manager.py
RENAMED
|
@@ -1227,6 +1227,14 @@ class BuildManager:
|
|
|
1227
1227
|
publish_package_name = (
|
|
1228
1228
|
self.src_dir.name.replace("_", "-").replace(" ", "-").lower().strip("-")
|
|
1229
1229
|
)
|
|
1230
|
+
|
|
1231
|
+
# Log the package name being used for publishing
|
|
1232
|
+
import logging
|
|
1233
|
+
logger = logging.getLogger(__name__)
|
|
1234
|
+
logger.info(
|
|
1235
|
+
f"Publishing package with name: '{publish_package_name}' "
|
|
1236
|
+
f"(captured: {captured_package_name}, param: {package_name}, src_dir: '{self.src_dir.name}')"
|
|
1237
|
+
)
|
|
1230
1238
|
else:
|
|
1231
1239
|
# For regular builds, get package name from pyproject.toml
|
|
1232
1240
|
try:
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/publisher.py
RENAMED
|
@@ -346,12 +346,24 @@ class Publisher:
|
|
|
346
346
|
# Provide helpful hints based on common errors
|
|
347
347
|
if e.returncode == 1:
|
|
348
348
|
if e.stderr and ("already exists" in e.stderr.lower() or "409" in e.stderr or "conflict" in e.stderr.lower()):
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
349
|
+
if self.repository == Repository.AZURE:
|
|
350
|
+
print(
|
|
351
|
+
"\nHint for Azure Artifacts: If the version query returned 404 (not found) "
|
|
352
|
+
"with authentication but the upload returns 409 Conflict, this could indicate:\n"
|
|
353
|
+
" - Different authentication requirements between simple index (read) and upload (write) endpoints\n"
|
|
354
|
+
" - The simple index endpoint may require different permissions or authentication method\n"
|
|
355
|
+
" - The package already exists with this version\n"
|
|
356
|
+
" - Use --skip-existing to skip files that already exist\n"
|
|
357
|
+
" - Check if your token has 'Packaging (read)' scope in addition to 'Packaging (read & write)'",
|
|
358
|
+
file=sys.stderr,
|
|
359
|
+
)
|
|
360
|
+
else:
|
|
361
|
+
print(
|
|
362
|
+
"\nHint: This version may already exist on the repository. "
|
|
363
|
+
"Use --skip-existing to skip files that already exist, "
|
|
364
|
+
"or publish a new version.",
|
|
365
|
+
file=sys.stderr,
|
|
366
|
+
)
|
|
355
367
|
elif e.stderr and ("401" in e.stderr or "unauthorized" in e.stderr.lower()):
|
|
356
368
|
print(
|
|
357
369
|
"\nHint: Authentication failed. Check your credentials.",
|
|
@@ -208,6 +208,14 @@ def main() -> int:
|
|
|
208
208
|
" ", "-"
|
|
209
209
|
).lower().strip("-")
|
|
210
210
|
subfolder_rel_path = src_dir.relative_to(project_root)
|
|
211
|
+
|
|
212
|
+
# Log the package name being used for version query
|
|
213
|
+
logger = logging.getLogger(__name__)
|
|
214
|
+
logger.info(
|
|
215
|
+
f"Querying registry for package name: '{package_name}' "
|
|
216
|
+
f"(derived from src_dir: '{src_dir.name}', args.package_name: {args.package_name})"
|
|
217
|
+
)
|
|
218
|
+
|
|
211
219
|
resolved_version, error_details = resolve_version(
|
|
212
220
|
project_root,
|
|
213
221
|
package_name=package_name,
|
|
@@ -402,6 +402,10 @@ class SubfolderBuildConfig:
|
|
|
402
402
|
# Modify using parsed data
|
|
403
403
|
if "project" in data:
|
|
404
404
|
data["project"]["name"] = self.package_name
|
|
405
|
+
# Log the package name being set
|
|
406
|
+
import logging
|
|
407
|
+
logger = logging.getLogger(__name__)
|
|
408
|
+
logger.info(f"Setting package name in temporary pyproject.toml: '{self.package_name}'")
|
|
405
409
|
if "version" in data["project"]:
|
|
406
410
|
data["project"]["version"] = self.version
|
|
407
411
|
elif "dynamic" in data["project"]:
|
|
@@ -475,6 +479,11 @@ class SubfolderBuildConfig:
|
|
|
475
479
|
if not package_dirs:
|
|
476
480
|
package_dirs = []
|
|
477
481
|
|
|
482
|
+
# Log the package name being set via string manipulation
|
|
483
|
+
import logging
|
|
484
|
+
logger = logging.getLogger(__name__)
|
|
485
|
+
logger.info(f"Setting package name in temporary pyproject.toml (string manipulation): '{self.package_name}'")
|
|
486
|
+
|
|
478
487
|
for _i, line in enumerate(lines):
|
|
479
488
|
# Skip build-system section - we'll add our own for subfolder builds
|
|
480
489
|
if line.strip().startswith("[build-system]"):
|
|
@@ -13,6 +13,8 @@ from __future__ import annotations
|
|
|
13
13
|
import logging
|
|
14
14
|
import re
|
|
15
15
|
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
import tempfile
|
|
16
18
|
from html.parser import HTMLParser
|
|
17
19
|
from pathlib import Path
|
|
18
20
|
|
|
@@ -185,6 +187,175 @@ class SimpleIndexParser(HTMLParser):
|
|
|
185
187
|
return None
|
|
186
188
|
|
|
187
189
|
|
|
190
|
+
def _query_azure_artifacts_version_via_pip_index(
|
|
191
|
+
package_name: str,
|
|
192
|
+
repository_url: str,
|
|
193
|
+
username: str | None = None,
|
|
194
|
+
password: str | None = None,
|
|
195
|
+
) -> str | None:
|
|
196
|
+
"""
|
|
197
|
+
Query Azure Artifacts for latest version using 'pip index versions'.
|
|
198
|
+
|
|
199
|
+
This method uses pip's built-in index querying, which uses the same
|
|
200
|
+
authentication mechanism as pip install/publish.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
package_name: Package name to query
|
|
204
|
+
repository_url: Azure Artifacts repository URL
|
|
205
|
+
username: Optional username for authentication
|
|
206
|
+
password: Optional password/token for authentication
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Latest version string or None if not found/unsupported
|
|
210
|
+
"""
|
|
211
|
+
# Build pip index URL (remove /upload suffix if present)
|
|
212
|
+
index_url = repository_url.replace("/upload", "/simple")
|
|
213
|
+
|
|
214
|
+
logger.info(f"Querying Azure Artifacts via 'pip index versions' for '{package_name}'...")
|
|
215
|
+
|
|
216
|
+
# Build pip command
|
|
217
|
+
cmd = ["pip", "index", "versions", package_name, "--index-url", index_url]
|
|
218
|
+
|
|
219
|
+
# Add authentication if provided
|
|
220
|
+
# pip supports credentials in URL format: https://user:pass@host/path
|
|
221
|
+
if username and password:
|
|
222
|
+
auth_url = index_url.replace("https://", f"https://{username}:{password}@")
|
|
223
|
+
cmd[cmd.index("--index-url") + 1] = auth_url
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
result = subprocess.run(
|
|
227
|
+
cmd,
|
|
228
|
+
capture_output=True,
|
|
229
|
+
text=True,
|
|
230
|
+
timeout=30,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
if result.returncode == 0:
|
|
234
|
+
# Parse output: "Package 'data' versions: 0.1.0, 0.2.0, 0.3.0"
|
|
235
|
+
# Or: "data (0.1.0, 0.2.0, 0.3.0)"
|
|
236
|
+
match = re.search(r"versions?:\s*(.+)", result.stdout, re.IGNORECASE)
|
|
237
|
+
if not match:
|
|
238
|
+
# Try alternative format: "package-name (version1, version2, ...)"
|
|
239
|
+
match = re.search(rf"{re.escape(package_name)}\s*\(([^)]+)\)", result.stdout)
|
|
240
|
+
|
|
241
|
+
if match:
|
|
242
|
+
versions_str = match.group(1).strip()
|
|
243
|
+
# Split by comma and clean up
|
|
244
|
+
versions = [v.strip().strip("'\"") for v in versions_str.split(",")]
|
|
245
|
+
if versions:
|
|
246
|
+
# Sort versions to get the latest
|
|
247
|
+
try:
|
|
248
|
+
sorted_versions = sorted(versions, key=_parse_version_for_sort, reverse=True)
|
|
249
|
+
latest_version = sorted_versions[0]
|
|
250
|
+
logger.info(f"Found latest version via pip index: {latest_version}")
|
|
251
|
+
return latest_version
|
|
252
|
+
except Exception as e:
|
|
253
|
+
logger.warning(f"Error sorting versions from pip index: {e}. Using first version.")
|
|
254
|
+
return versions[-1] # Return last one as fallback
|
|
255
|
+
|
|
256
|
+
# Check if error indicates package doesn't exist
|
|
257
|
+
if "not found" in result.stderr.lower() or "no such package" in result.stderr.lower():
|
|
258
|
+
logger.info(f"Package '{package_name}' not found via pip index (first release)")
|
|
259
|
+
else:
|
|
260
|
+
logger.debug(f"pip index versions output: stdout={result.stdout}, stderr={result.stderr}")
|
|
261
|
+
|
|
262
|
+
return None
|
|
263
|
+
except subprocess.TimeoutExpired:
|
|
264
|
+
logger.warning(f"Timeout querying Azure Artifacts via pip index for '{package_name}'")
|
|
265
|
+
return None
|
|
266
|
+
except FileNotFoundError:
|
|
267
|
+
# pip command not found or pip index not available (pip < 21.2)
|
|
268
|
+
logger.debug("'pip index versions' not available, will try alternative method")
|
|
269
|
+
return None
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.warning(f"Error querying Azure Artifacts via pip index for '{package_name}': {e}")
|
|
272
|
+
return None
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _query_azure_artifacts_version_via_pip_install(
|
|
276
|
+
package_name: str,
|
|
277
|
+
repository_url: str,
|
|
278
|
+
username: str | None = None,
|
|
279
|
+
password: str | None = None,
|
|
280
|
+
) -> str | None:
|
|
281
|
+
"""
|
|
282
|
+
Query Azure Artifacts by attempting to install the latest version
|
|
283
|
+
using 'pip install --dry-run', then extracting the version.
|
|
284
|
+
|
|
285
|
+
This is a fallback method when 'pip index versions' is not available.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
package_name: Package name to query
|
|
289
|
+
repository_url: Azure Artifacts repository URL
|
|
290
|
+
username: Optional username for authentication
|
|
291
|
+
password: Optional password/token for authentication
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
Latest version string or None if not found/unsupported
|
|
295
|
+
"""
|
|
296
|
+
# Build index URL
|
|
297
|
+
index_url = repository_url.replace("/upload", "/simple")
|
|
298
|
+
|
|
299
|
+
logger.info(f"Querying Azure Artifacts via 'pip install --dry-run' for '{package_name}'...")
|
|
300
|
+
|
|
301
|
+
# Build pip command
|
|
302
|
+
cmd = [
|
|
303
|
+
sys.executable,
|
|
304
|
+
"-m",
|
|
305
|
+
"pip",
|
|
306
|
+
"install",
|
|
307
|
+
"--index-url",
|
|
308
|
+
index_url,
|
|
309
|
+
"--no-deps", # Don't install dependencies
|
|
310
|
+
"--dry-run", # Don't actually install
|
|
311
|
+
package_name,
|
|
312
|
+
]
|
|
313
|
+
|
|
314
|
+
# Add authentication if provided
|
|
315
|
+
if username and password:
|
|
316
|
+
auth_url = index_url.replace("https://", f"https://{username}:{password}@")
|
|
317
|
+
cmd[cmd.index("--index-url") + 1] = auth_url
|
|
318
|
+
|
|
319
|
+
try:
|
|
320
|
+
result = subprocess.run(
|
|
321
|
+
cmd,
|
|
322
|
+
capture_output=True,
|
|
323
|
+
text=True,
|
|
324
|
+
timeout=60,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
if result.returncode == 0:
|
|
328
|
+
# Parse output to find version
|
|
329
|
+
# pip shows: "Would install data-0.3.0" or "Collecting data==0.3.0"
|
|
330
|
+
# Try multiple patterns
|
|
331
|
+
patterns = [
|
|
332
|
+
rf"Would install\s+{re.escape(package_name)}-([\d.]+(?:[a-zA-Z0-9]+)?)",
|
|
333
|
+
rf"Collecting\s+{re.escape(package_name)}==([\d.]+(?:[a-zA-Z0-9]+)?)",
|
|
334
|
+
rf"Downloading\s+{re.escape(package_name)}-([\d.]+(?:[a-zA-Z0-9]+)?)",
|
|
335
|
+
]
|
|
336
|
+
|
|
337
|
+
for pattern in patterns:
|
|
338
|
+
match = re.search(pattern, result.stdout, re.IGNORECASE)
|
|
339
|
+
if match:
|
|
340
|
+
version = match.group(1)
|
|
341
|
+
logger.info(f"Found version via pip install --dry-run: {version}")
|
|
342
|
+
return version
|
|
343
|
+
|
|
344
|
+
# Check if error indicates package doesn't exist
|
|
345
|
+
if "not found" in result.stderr.lower() or "no matching distribution" in result.stderr.lower():
|
|
346
|
+
logger.info(f"Package '{package_name}' not found via pip install (first release)")
|
|
347
|
+
else:
|
|
348
|
+
logger.debug(f"pip install --dry-run output: stdout={result.stdout[:500]}, stderr={result.stderr[:500]}")
|
|
349
|
+
|
|
350
|
+
return None
|
|
351
|
+
except subprocess.TimeoutExpired:
|
|
352
|
+
logger.warning(f"Timeout querying Azure Artifacts via pip install for '{package_name}'")
|
|
353
|
+
return None
|
|
354
|
+
except Exception as e:
|
|
355
|
+
logger.warning(f"Error querying Azure Artifacts via pip install for '{package_name}': {e}")
|
|
356
|
+
return None
|
|
357
|
+
|
|
358
|
+
|
|
188
359
|
def _query_azure_artifacts_version(
|
|
189
360
|
package_name: str,
|
|
190
361
|
repository_url: str,
|
|
@@ -194,6 +365,50 @@ def _query_azure_artifacts_version(
|
|
|
194
365
|
"""
|
|
195
366
|
Query Azure Artifacts for the latest version.
|
|
196
367
|
|
|
368
|
+
Tries multiple methods in order:
|
|
369
|
+
1. pip index versions (fastest, uses same auth as pip install)
|
|
370
|
+
2. pip install --dry-run (fallback if pip index not available)
|
|
371
|
+
3. HTML parsing of simple index (last resort)
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
package_name: Package name to query
|
|
375
|
+
repository_url: Azure Artifacts repository URL
|
|
376
|
+
username: Optional username for authentication
|
|
377
|
+
password: Optional password/token for authentication
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Latest version string or None if not found/unsupported
|
|
381
|
+
"""
|
|
382
|
+
# Method 1: Try pip index versions first (fastest, uses same auth as publishing)
|
|
383
|
+
version = _query_azure_artifacts_version_via_pip_index(
|
|
384
|
+
package_name, repository_url, username, password
|
|
385
|
+
)
|
|
386
|
+
if version:
|
|
387
|
+
return version
|
|
388
|
+
|
|
389
|
+
# Method 2: Fallback to pip install --dry-run
|
|
390
|
+
version = _query_azure_artifacts_version_via_pip_install(
|
|
391
|
+
package_name, repository_url, username, password
|
|
392
|
+
)
|
|
393
|
+
if version:
|
|
394
|
+
return version
|
|
395
|
+
|
|
396
|
+
# Method 3: Last resort - HTML parsing (original method)
|
|
397
|
+
logger.info(f"Falling back to HTML parsing for '{package_name}'...")
|
|
398
|
+
return _query_azure_artifacts_version_via_html(
|
|
399
|
+
package_name, repository_url, username, password
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _query_azure_artifacts_version_via_html(
|
|
404
|
+
package_name: str,
|
|
405
|
+
repository_url: str,
|
|
406
|
+
username: str | None = None,
|
|
407
|
+
password: str | None = None,
|
|
408
|
+
) -> str | None:
|
|
409
|
+
"""
|
|
410
|
+
Query Azure Artifacts for the latest version via HTML parsing.
|
|
411
|
+
|
|
197
412
|
Azure Artifacts uses a simple index format (HTML) following PEP 503.
|
|
198
413
|
Parses the HTML to extract version numbers from package filenames.
|
|
199
414
|
|
|
@@ -246,10 +461,27 @@ def _query_azure_artifacts_version(
|
|
|
246
461
|
)
|
|
247
462
|
return None
|
|
248
463
|
elif response.status_code == 404:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
464
|
+
if auth:
|
|
465
|
+
# If we're using authentication and still get 404, it could be various issues
|
|
466
|
+
logger.warning(
|
|
467
|
+
f"Package '{package_name}' not found on Azure Artifacts (404) with authentication. "
|
|
468
|
+
f"This could indicate:\n"
|
|
469
|
+
f" (1) Different authentication requirements between simple index (read) and upload (write) endpoints\n"
|
|
470
|
+
f" (2) The simple index endpoint may require different permissions or authentication method\n"
|
|
471
|
+
f" (3) This is the first release (package doesn't exist yet)\n"
|
|
472
|
+
f" (4) Package name mismatch between query and publish\n"
|
|
473
|
+
f"URL: {simple_index_url}\n"
|
|
474
|
+
f"Note: If publishing succeeds but querying fails with 404, check:\n"
|
|
475
|
+
f" - Whether the simple index endpoint requires different authentication\n"
|
|
476
|
+
f" - Whether your token has 'Packaging (read)' scope in addition to 'Packaging (read & write)'\n"
|
|
477
|
+
f" - Whether the package name used for querying matches the published package name"
|
|
478
|
+
)
|
|
479
|
+
else:
|
|
480
|
+
logger.info(
|
|
481
|
+
f"Package '{package_name}' not found on Azure Artifacts (404) - this appears to be the first release. "
|
|
482
|
+
f"Note: If authentication is required, provide credentials via --username/--password or environment variables. "
|
|
483
|
+
f"URL: {simple_index_url}"
|
|
484
|
+
)
|
|
253
485
|
return None
|
|
254
486
|
elif response.status_code != 200:
|
|
255
487
|
logger.warning(
|
|
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
|
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/__init__.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/__main__.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/analyzer.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/finder.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/py.typed
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/types.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/utils.py
RENAMED
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/src/python_package_folder/version.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/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.2 → python_package_folder-5.2.4}/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.2 → python_package_folder-5.2.4}/tests/test_third_party_dependencies.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-5.2.2 → python_package_folder-5.2.4}/tests/test_version_calculator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|