python-package-folder 7.0.0__tar.gz → 7.1.0__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-7.0.0 → python_package_folder-7.1.0}/PKG-INFO +1 -1
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/pyproject.toml +1 -1
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/manager.py +50 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_subfolder_build.py +113 -1
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.copier-answers.yml +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.cursor/plans/optional_version_+_semantic-release_efed88a6.plan.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.cursor/plans/replace_node.js_semantic-release_with_custom_python_implementation_64e05e1a.plan.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.cursor/rules/general.mdc +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.cursor/rules/python.mdc +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.github/workflows/ci.yml +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.github/workflows/publish.yml +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.gitignore +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/.vscode/settings.json +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/LICENSE +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/MANIFEST.in +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/Makefile +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/README.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/coverage.svg +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/development.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/docs/DEVELOPMENT.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/docs/INSTALLATION.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/docs/PUBLISHING.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/docs/REFERENCE.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/docs/USAGE.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/docs/VERSION_RESOLUTION.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/installation.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/publishing.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/__init__.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/__main__.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/analyzer.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/finder.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/publisher.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/py.typed +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/python_package_folder.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/subfolder_build.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/types.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/utils.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/version.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/version_calculator.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/conftest.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/some_globals.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/subfolder_to_build/README.md +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/subfolder_to_build/__init__.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/subfolder_to_build/some_function.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/subfolder_to_build/some_globals.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/utility_folder/_SS/some_superseded_file.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/folder_structure/utility_folder/some_utility.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_build_with_external_deps.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_exclude_patterns.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_linting.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_preserve_directory_structure.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_publisher.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_shared_subdirectory_imports.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_spreadsheet_creation_imports.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_third_party_dependencies.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_utils.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_version_calculator.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_version_manager.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/tests.py +0 -0
- {python_package_folder-7.0.0 → python_package_folder-7.1.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-package-folder
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.1.0
|
|
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-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/manager.py
RENAMED
|
@@ -1142,6 +1142,26 @@ class BuildManager:
|
|
|
1142
1142
|
else:
|
|
1143
1143
|
print("No external dependencies found\n")
|
|
1144
1144
|
|
|
1145
|
+
# Verify temporary package directory exists if using subfolder build
|
|
1146
|
+
if self.subfolder_config and self.subfolder_config._temp_package_dir:
|
|
1147
|
+
temp_dir = self.subfolder_config._temp_package_dir
|
|
1148
|
+
if not temp_dir.exists():
|
|
1149
|
+
raise RuntimeError(
|
|
1150
|
+
f"Temporary package directory does not exist: {temp_dir}. "
|
|
1151
|
+
"This should have been created during prepare_build()."
|
|
1152
|
+
)
|
|
1153
|
+
# Verify it contains Python files
|
|
1154
|
+
py_files = list(temp_dir.glob("*.py"))
|
|
1155
|
+
if not py_files:
|
|
1156
|
+
raise RuntimeError(
|
|
1157
|
+
f"Temporary package directory exists but contains no Python files: {temp_dir}"
|
|
1158
|
+
)
|
|
1159
|
+
# Verify __init__.py exists
|
|
1160
|
+
if not (temp_dir / "__init__.py").exists():
|
|
1161
|
+
raise RuntimeError(
|
|
1162
|
+
f"Temporary package directory missing __init__.py: {temp_dir}"
|
|
1163
|
+
)
|
|
1164
|
+
|
|
1145
1165
|
print("Running build...")
|
|
1146
1166
|
# Build command should run from project root to find pyproject.toml
|
|
1147
1167
|
import os
|
|
@@ -1152,6 +1172,36 @@ class BuildManager:
|
|
|
1152
1172
|
build_command()
|
|
1153
1173
|
finally:
|
|
1154
1174
|
os.chdir(original_cwd)
|
|
1175
|
+
|
|
1176
|
+
# Verify wheel contents after build (for subfolder builds)
|
|
1177
|
+
if self.subfolder_config and self.subfolder_config.package_name:
|
|
1178
|
+
import_name = self.subfolder_config.package_name.replace("-", "_")
|
|
1179
|
+
dist_dir = self.project_root / "dist"
|
|
1180
|
+
if dist_dir.exists():
|
|
1181
|
+
wheel_files = list(dist_dir.glob("*.whl"))
|
|
1182
|
+
if wheel_files:
|
|
1183
|
+
import zipfile
|
|
1184
|
+
wheel_file = wheel_files[0]
|
|
1185
|
+
try:
|
|
1186
|
+
with zipfile.ZipFile(wheel_file, "r") as wheel:
|
|
1187
|
+
file_names = wheel.namelist()
|
|
1188
|
+
package_files = [f for f in file_names if f.startswith(f"{import_name}/")]
|
|
1189
|
+
if not package_files:
|
|
1190
|
+
print(
|
|
1191
|
+
f"\nWARNING: Built wheel does not contain package directory '{import_name}/'. "
|
|
1192
|
+
f"Only found: {[f for f in file_names if '.dist-info' not in f][:10]}",
|
|
1193
|
+
file=sys.stderr,
|
|
1194
|
+
)
|
|
1195
|
+
else:
|
|
1196
|
+
print(
|
|
1197
|
+
f"\nVerified wheel contains package directory '{import_name}/' "
|
|
1198
|
+
f"with {len(package_files)} files"
|
|
1199
|
+
)
|
|
1200
|
+
except Exception as e:
|
|
1201
|
+
print(
|
|
1202
|
+
f"\nWARNING: Could not verify wheel contents: {e}",
|
|
1203
|
+
file=sys.stderr,
|
|
1204
|
+
)
|
|
1155
1205
|
|
|
1156
1206
|
finally:
|
|
1157
1207
|
print("\nCleaning up copied files...")
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import tempfile
|
|
8
|
+
import venv
|
|
6
9
|
import zipfile
|
|
7
10
|
from pathlib import Path
|
|
8
11
|
|
|
@@ -1241,4 +1244,113 @@ build-backend = "hatchling.build"
|
|
|
1241
1244
|
data_files = [f for f in file_names if f.startswith("data/") and ".dist-info" not in f]
|
|
1242
1245
|
assert len(data_files) == 0, (
|
|
1243
1246
|
f"Wheel should not contain 'data/' directory, should use '{import_name}/' instead"
|
|
1244
|
-
)
|
|
1247
|
+
)
|
|
1248
|
+
|
|
1249
|
+
def test_wheel_installs_with_correct_package_directory(self, tmp_path: Path) -> None:
|
|
1250
|
+
"""Test that a built wheel can be installed and the package directory exists."""
|
|
1251
|
+
project_root = tmp_path / "test_project"
|
|
1252
|
+
project_root.mkdir()
|
|
1253
|
+
|
|
1254
|
+
# Create pyproject.toml
|
|
1255
|
+
pyproject_content = """[project]
|
|
1256
|
+
name = "test-package"
|
|
1257
|
+
version = "0.1.0"
|
|
1258
|
+
|
|
1259
|
+
[build-system]
|
|
1260
|
+
requires = ["hatchling"]
|
|
1261
|
+
build-backend = "hatchling.build"
|
|
1262
|
+
"""
|
|
1263
|
+
(project_root / "pyproject.toml").write_text(pyproject_content)
|
|
1264
|
+
|
|
1265
|
+
# Create subfolder with package name that has hyphens
|
|
1266
|
+
subfolder = project_root / "src" / "data"
|
|
1267
|
+
subfolder.mkdir(parents=True)
|
|
1268
|
+
|
|
1269
|
+
# Create some Python files
|
|
1270
|
+
(subfolder / "__init__.py").write_text("# Package init")
|
|
1271
|
+
(subfolder / "module.py").write_text("def hello(): return 'world'")
|
|
1272
|
+
(subfolder / "utils.py").write_text("def util(): return 'helper'")
|
|
1273
|
+
|
|
1274
|
+
# Package name with hyphens (like ml-drawing-assistant-data)
|
|
1275
|
+
package_name = "ml-drawing-assistant-data"
|
|
1276
|
+
import_name = "ml_drawing_assistant_data" # Expected import name
|
|
1277
|
+
version = "1.0.0"
|
|
1278
|
+
|
|
1279
|
+
# Build the wheel
|
|
1280
|
+
manager = BuildManager(project_root=project_root, src_dir=subfolder)
|
|
1281
|
+
|
|
1282
|
+
def build_wheel() -> None:
|
|
1283
|
+
"""Build the wheel using uv build."""
|
|
1284
|
+
subprocess.run(
|
|
1285
|
+
["uv", "build", "--wheel"],
|
|
1286
|
+
cwd=project_root,
|
|
1287
|
+
check=True,
|
|
1288
|
+
capture_output=True,
|
|
1289
|
+
)
|
|
1290
|
+
|
|
1291
|
+
try:
|
|
1292
|
+
manager.run_build(build_wheel, version=version, package_name=package_name)
|
|
1293
|
+
finally:
|
|
1294
|
+
manager.cleanup()
|
|
1295
|
+
|
|
1296
|
+
# Find the built wheel
|
|
1297
|
+
dist_dir = project_root / "dist"
|
|
1298
|
+
assert dist_dir.exists(), "dist directory should exist after build"
|
|
1299
|
+
|
|
1300
|
+
wheel_files = list(dist_dir.glob("*.whl"))
|
|
1301
|
+
assert len(wheel_files) > 0, "At least one wheel should be built"
|
|
1302
|
+
|
|
1303
|
+
wheel_file = wheel_files[0]
|
|
1304
|
+
|
|
1305
|
+
# Create a temporary virtual environment and install the wheel
|
|
1306
|
+
venv_dir = tmp_path / "test_venv"
|
|
1307
|
+
venv.create(venv_dir, with_pip=True)
|
|
1308
|
+
|
|
1309
|
+
# Determine the Python executable in the venv
|
|
1310
|
+
if sys.platform == "win32":
|
|
1311
|
+
python_exe = venv_dir / "Scripts" / "python.exe"
|
|
1312
|
+
pip_exe = venv_dir / "Scripts" / "pip.exe"
|
|
1313
|
+
else:
|
|
1314
|
+
python_exe = venv_dir / "bin" / "python"
|
|
1315
|
+
pip_exe = venv_dir / "bin" / "pip"
|
|
1316
|
+
|
|
1317
|
+
# Install the wheel
|
|
1318
|
+
install_result = subprocess.run(
|
|
1319
|
+
[str(pip_exe), "install", str(wheel_file)],
|
|
1320
|
+
capture_output=True,
|
|
1321
|
+
text=True,
|
|
1322
|
+
check=True,
|
|
1323
|
+
)
|
|
1324
|
+
|
|
1325
|
+
# Find the site-packages directory
|
|
1326
|
+
if sys.platform == "win32":
|
|
1327
|
+
site_packages = venv_dir / "Lib" / "site-packages"
|
|
1328
|
+
else:
|
|
1329
|
+
# Get Python version
|
|
1330
|
+
version_result = subprocess.run(
|
|
1331
|
+
[str(python_exe), "-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"],
|
|
1332
|
+
capture_output=True,
|
|
1333
|
+
text=True,
|
|
1334
|
+
check=True,
|
|
1335
|
+
)
|
|
1336
|
+
py_version = version_result.stdout.strip()
|
|
1337
|
+
site_packages = venv_dir / "lib" / f"python{py_version}" / "site-packages"
|
|
1338
|
+
|
|
1339
|
+
assert site_packages.exists(), f"site-packages directory should exist at {site_packages}"
|
|
1340
|
+
|
|
1341
|
+
# Verify the package directory exists (not just dist-info)
|
|
1342
|
+
package_dir = site_packages / import_name
|
|
1343
|
+
assert package_dir.exists(), (
|
|
1344
|
+
f"Package directory {import_name}/ should exist in site-packages after installation. "
|
|
1345
|
+
f"Found in site-packages: {list(site_packages.iterdir())[:20]}"
|
|
1346
|
+
)
|
|
1347
|
+
assert package_dir.is_dir(), f"{import_name} should be a directory, not a file"
|
|
1348
|
+
|
|
1349
|
+
# Verify the expected files are present
|
|
1350
|
+
assert (package_dir / "__init__.py").exists(), f"{import_name}/__init__.py should exist"
|
|
1351
|
+
assert (package_dir / "module.py").exists(), f"{import_name}/module.py should exist"
|
|
1352
|
+
assert (package_dir / "utils.py").exists(), f"{import_name}/utils.py should exist"
|
|
1353
|
+
|
|
1354
|
+
# Verify dist-info also exists
|
|
1355
|
+
dist_info_dir = site_packages / f"{import_name}-{version}.dist-info"
|
|
1356
|
+
assert dist_info_dir.exists(), f"dist-info directory should exist: {dist_info_dir}"
|
|
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-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/__init__.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/__main__.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/analyzer.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/finder.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/publisher.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/types.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/utils.py
RENAMED
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/src/python_package_folder/version.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/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-7.0.0 → python_package_folder-7.1.0}/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
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_third_party_dependencies.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-7.0.0 → python_package_folder-7.1.0}/tests/test_version_calculator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|