python-package-folder 2.0.4__tar.gz → 2.0.5__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-2.0.4 → python_package_folder-2.0.5}/PKG-INFO +1 -1
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/coverage.svg +2 -2
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/manager.py +68 -25
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.copier-answers.yml +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.cursor/rules/general.mdc +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.cursor/rules/python.mdc +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.github/workflows/ci.yml +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.github/workflows/publish.yml +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.gitignore +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/.vscode/settings.json +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/LICENSE +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/Makefile +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/README.md +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/development.md +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/installation.md +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/publishing.md +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/pyproject.toml +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/__init__.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/__main__.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/analyzer.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/finder.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/publisher.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/py.typed +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/python_package_folder.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/subfolder_build.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/types.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/utils.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/version.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/conftest.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/some_globals.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/subfolder_to_build/README.md +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/subfolder_to_build/__init__.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/subfolder_to_build/some_function.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/subfolder_to_build/some_globals.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/utility_folder/_SS/some_superseded_file.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/folder_structure/utility_folder/some_utility.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_build_with_external_deps.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_linting.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_publisher.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_subfolder_build.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_third_party_dependencies.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_utils.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_version_manager.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/tests.py +0 -0
- {python_package_folder-2.0.4 → python_package_folder-2.0.5}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-package-folder
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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">68%</text>
|
|
18
|
+
<text x="81" y="14">68%</text>
|
|
19
19
|
</g>
|
|
20
20
|
</svg>
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/manager.py
RENAMED
|
@@ -86,6 +86,8 @@ class BuildManager:
|
|
|
86
86
|
self.project_root, self.src_dir, exclude_patterns=exclude_patterns
|
|
87
87
|
)
|
|
88
88
|
self.subfolder_config: SubfolderBuildConfig | None = None
|
|
89
|
+
# Cache for package name lookups (expensive operation)
|
|
90
|
+
self._packages_distributions_cache: dict[str, list[str]] | None = None
|
|
89
91
|
|
|
90
92
|
# Check if it's a valid Python package directory
|
|
91
93
|
if not any(self.src_dir.glob("*.py")) and not (self.src_dir / "__init__.py").exists():
|
|
@@ -271,7 +273,9 @@ class BuildManager:
|
|
|
271
273
|
# For subfolder builds, extract third-party dependencies and add to pyproject.toml
|
|
272
274
|
if self._is_subfolder_build() and self.subfolder_config:
|
|
273
275
|
# Re-analyze all Python files (including copied dependencies) to find third-party imports
|
|
276
|
+
print("Analyzing Python files for third-party dependencies...")
|
|
274
277
|
all_python_files = analyzer.find_all_python_files(self.src_dir)
|
|
278
|
+
print(f"Found {len(all_python_files)} Python files to analyze")
|
|
275
279
|
third_party_deps = self._extract_third_party_dependencies(all_python_files, analyzer)
|
|
276
280
|
if third_party_deps:
|
|
277
281
|
print(
|
|
@@ -413,8 +417,12 @@ class BuildManager:
|
|
|
413
417
|
import importlib.metadata as importlib_metadata
|
|
414
418
|
|
|
415
419
|
# Use packages_distributions() if available (Python 3.10+)
|
|
420
|
+
# Cache the result since it's expensive to call
|
|
416
421
|
if hasattr(importlib_metadata, "packages_distributions"):
|
|
417
|
-
|
|
422
|
+
if self._packages_distributions_cache is None:
|
|
423
|
+
# Cache the packages_distributions() result
|
|
424
|
+
self._packages_distributions_cache = importlib_metadata.packages_distributions()
|
|
425
|
+
packages_map = self._packages_distributions_cache
|
|
418
426
|
# packages_map is a dict mapping module names to list of distribution names
|
|
419
427
|
if root_module in packages_map:
|
|
420
428
|
# Return the first distribution name (usually there's only one)
|
|
@@ -422,26 +430,45 @@ class BuildManager:
|
|
|
422
430
|
if dist_names:
|
|
423
431
|
return dist_names[0]
|
|
424
432
|
|
|
425
|
-
# Fallback: search all distributions
|
|
433
|
+
# Fallback: search all distributions (this can be slow, so limit search)
|
|
434
|
+
# Only check top-level package matches to speed up search
|
|
435
|
+
dist_count = 0
|
|
436
|
+
max_distributions_to_check = 1000 # Limit to prevent excessive searching
|
|
426
437
|
for dist in importlib_metadata.distributions():
|
|
438
|
+
dist_count += 1
|
|
439
|
+
if dist_count > max_distributions_to_check:
|
|
440
|
+
# Too many distributions, give up to avoid hanging
|
|
441
|
+
break
|
|
427
442
|
try:
|
|
428
|
-
# Check
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
# Check distribution name first (fast check)
|
|
444
|
+
dist_name = dist.metadata.get("Name", "")
|
|
445
|
+
# If distribution name matches or contains the module name, check files
|
|
446
|
+
if dist_name.lower().replace(
|
|
447
|
+
"-", "_"
|
|
448
|
+
) == root_module.lower() or root_module.lower() in dist_name.lower().replace(
|
|
449
|
+
"-", "_"
|
|
450
|
+
):
|
|
451
|
+
# Check if this distribution provides the module by looking at its files
|
|
452
|
+
files = dist.files or []
|
|
453
|
+
# Limit file checking to first 100 files per distribution
|
|
454
|
+
file_count = 0
|
|
455
|
+
for file in files:
|
|
456
|
+
file_count += 1
|
|
457
|
+
if file_count > 100:
|
|
458
|
+
break
|
|
459
|
+
file_str = str(file)
|
|
460
|
+
# Check if file is the module itself or in a package directory
|
|
461
|
+
if (
|
|
462
|
+
file.suffix == ".py"
|
|
463
|
+
and (file.stem == root_module or file.stem == "__init__")
|
|
464
|
+
) or (
|
|
465
|
+
"/" in file_str
|
|
466
|
+
and (
|
|
467
|
+
file_str.startswith(f"{root_module}/")
|
|
468
|
+
or file_str.startswith(f"{root_module.replace('_', '-')}/")
|
|
469
|
+
)
|
|
470
|
+
):
|
|
471
|
+
return dist.metadata["Name"]
|
|
445
472
|
except Exception:
|
|
446
473
|
continue
|
|
447
474
|
|
|
@@ -494,8 +521,14 @@ class BuildManager:
|
|
|
494
521
|
List of unique third-party package names (e.g., ["pypdf", "requests", "pymupdf"])
|
|
495
522
|
"""
|
|
496
523
|
third_party_packages: set[str] = set()
|
|
524
|
+
# Cache package name lookups to avoid repeated expensive searches
|
|
525
|
+
package_name_cache: dict[str, str | None] = {}
|
|
526
|
+
|
|
527
|
+
total_files = len(python_files)
|
|
528
|
+
for idx, file_path in enumerate(python_files):
|
|
529
|
+
if idx > 0 and idx % 50 == 0:
|
|
530
|
+
print(f" Analyzing file {idx}/{total_files}...", end="\r", flush=True)
|
|
497
531
|
|
|
498
|
-
for file_path in python_files:
|
|
499
532
|
imports = analyzer.extract_imports(file_path)
|
|
500
533
|
for imp in imports:
|
|
501
534
|
analyzer.classify_import(imp, self.src_dir)
|
|
@@ -510,8 +543,12 @@ class BuildManager:
|
|
|
510
543
|
|
|
511
544
|
# If classified as third_party, try to get actual package name
|
|
512
545
|
if imp.classification == "third_party":
|
|
513
|
-
#
|
|
514
|
-
|
|
546
|
+
# Check cache first
|
|
547
|
+
if root_module not in package_name_cache:
|
|
548
|
+
package_name_cache[root_module] = self._get_package_name_from_import(
|
|
549
|
+
imp.module_name
|
|
550
|
+
)
|
|
551
|
+
actual_package = package_name_cache[root_module]
|
|
515
552
|
if actual_package:
|
|
516
553
|
third_party_packages.add(actual_package)
|
|
517
554
|
else:
|
|
@@ -522,15 +559,21 @@ class BuildManager:
|
|
|
522
559
|
elif imp.classification == "ambiguous" or imp.classification is None:
|
|
523
560
|
# Check if it's not a local or external module
|
|
524
561
|
if not imp.resolved_path:
|
|
525
|
-
#
|
|
526
|
-
|
|
527
|
-
|
|
562
|
+
# Check cache first
|
|
563
|
+
if root_module not in package_name_cache:
|
|
564
|
+
package_name_cache[root_module] = self._get_package_name_from_import(
|
|
565
|
+
imp.module_name
|
|
566
|
+
)
|
|
567
|
+
actual_package = package_name_cache[root_module]
|
|
528
568
|
if actual_package:
|
|
529
569
|
third_party_packages.add(actual_package)
|
|
530
570
|
else:
|
|
531
571
|
# Fallback: use import name (will be normalized later)
|
|
532
572
|
third_party_packages.add(root_module)
|
|
533
573
|
|
|
574
|
+
if total_files > 50:
|
|
575
|
+
print() # New line after progress indicator
|
|
576
|
+
|
|
534
577
|
return sorted(list(third_party_packages))
|
|
535
578
|
|
|
536
579
|
def _report_ambiguous_imports(self, python_files: list[Path]) -> None:
|
|
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-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/__init__.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/__main__.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/analyzer.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/finder.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/publisher.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/types.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/utils.py
RENAMED
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/src/python_package_folder/version.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/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-2.0.4 → python_package_folder-2.0.5}/tests/test_build_with_external_deps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-2.0.4 → python_package_folder-2.0.5}/tests/test_third_party_dependencies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|