python-package-folder 3.1.3__py3-none-any.whl → 4.1.0__py3-none-any.whl
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/_hatch_build.py +39 -0
- python_package_folder/python_package_folder.py +221 -11
- {python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/METADATA +80 -9
- {python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/RECORD +7 -6
- {python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/WHEEL +1 -1
- {python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/entry_points.txt +0 -0
- {python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Hatch build hook to automatically include all files from the scripts directory.
|
|
3
|
+
|
|
4
|
+
This hook ensures all non-Python files in the scripts directory are included
|
|
5
|
+
in the wheel without creating duplicates, and automatically includes any new
|
|
6
|
+
files added to the directory without requiring manual configuration updates.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CustomBuildHook(BuildHookInterface):
|
|
16
|
+
"""Build hook to include all files from the scripts directory."""
|
|
17
|
+
|
|
18
|
+
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
19
|
+
"""Initialize the build hook and add scripts directory files."""
|
|
20
|
+
# Get the source directory for the package
|
|
21
|
+
source_dir = Path(self.root) / "src" / "python_package_folder"
|
|
22
|
+
scripts_dir = source_dir / "scripts"
|
|
23
|
+
|
|
24
|
+
# If scripts directory exists, include all files from it
|
|
25
|
+
if scripts_dir.exists() and scripts_dir.is_dir():
|
|
26
|
+
# Add all files from scripts directory to force-include
|
|
27
|
+
# This ensures they're included in the wheel at the correct location
|
|
28
|
+
for script_file in scripts_dir.iterdir():
|
|
29
|
+
if script_file.is_file():
|
|
30
|
+
# Calculate relative paths
|
|
31
|
+
source_path = script_file.relative_to(self.root)
|
|
32
|
+
# Target path inside the wheel package
|
|
33
|
+
target_path = f"python_package_folder/scripts/{script_file.name}"
|
|
34
|
+
|
|
35
|
+
# Add to force-include (hatchling will handle this)
|
|
36
|
+
# We need to add it to build_data['force_include']
|
|
37
|
+
if "force_include" not in build_data:
|
|
38
|
+
build_data["force_include"] = {}
|
|
39
|
+
build_data["force_include"][str(source_path)] = target_path
|
|
@@ -14,10 +14,157 @@ import subprocess
|
|
|
14
14
|
import sys
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
try:
|
|
18
|
+
from importlib import resources
|
|
19
|
+
except ImportError:
|
|
20
|
+
import importlib_resources as resources # type: ignore[no-redef]
|
|
21
|
+
|
|
17
22
|
from .manager import BuildManager
|
|
18
23
|
from .utils import find_project_root, find_source_directory
|
|
19
24
|
|
|
20
25
|
|
|
26
|
+
def resolve_version_via_semantic_release(
|
|
27
|
+
project_root: Path,
|
|
28
|
+
subfolder_path: Path | None = None,
|
|
29
|
+
package_name: str | None = None,
|
|
30
|
+
repository: str | None = None,
|
|
31
|
+
repository_url: str | None = None,
|
|
32
|
+
) -> str | None:
|
|
33
|
+
"""
|
|
34
|
+
Resolve the next version using semantic-release via Node.js script.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
project_root: Root directory of the project
|
|
38
|
+
subfolder_path: Optional path to subfolder (relative to project_root) for Workflow 1
|
|
39
|
+
package_name: Optional package name for subfolder builds
|
|
40
|
+
repository: Optional target repository ('pypi', 'testpypi', or 'azure')
|
|
41
|
+
repository_url: Optional repository URL (required for Azure Artifacts)
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Version string if a release is determined, None if no release or error
|
|
45
|
+
"""
|
|
46
|
+
# Try to find the script in multiple locations:
|
|
47
|
+
# 1. Project root / scripts (for development or when script is in repo)
|
|
48
|
+
# 2. Package installation directory / scripts (for installed package)
|
|
49
|
+
# - For normal installs: direct file path
|
|
50
|
+
# - For zip/pex installs: extract to temporary file using as_file()
|
|
51
|
+
|
|
52
|
+
# Track temporary file context for cleanup
|
|
53
|
+
temp_script_context = None
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
# First, try project root (development)
|
|
57
|
+
dev_script = project_root / "scripts" / "get-next-version.cjs"
|
|
58
|
+
if dev_script.exists():
|
|
59
|
+
script_path = dev_script
|
|
60
|
+
else:
|
|
61
|
+
# Try to locate script in installed package using importlib.resources
|
|
62
|
+
script_path = None
|
|
63
|
+
try:
|
|
64
|
+
package = resources.files("python_package_folder")
|
|
65
|
+
script_resource = package / "scripts" / "get-next-version.cjs"
|
|
66
|
+
if script_resource.is_file():
|
|
67
|
+
# Try direct path conversion first (normal file system install)
|
|
68
|
+
try:
|
|
69
|
+
script_path_candidate = Path(str(script_resource))
|
|
70
|
+
if script_path_candidate.exists():
|
|
71
|
+
script_path = script_path_candidate
|
|
72
|
+
except (TypeError, ValueError):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
# If direct path didn't work, try as_file() for zip/pex installs
|
|
76
|
+
if script_path is None:
|
|
77
|
+
try:
|
|
78
|
+
temp_script_context = resources.as_file(script_resource)
|
|
79
|
+
script_path = temp_script_context.__enter__()
|
|
80
|
+
except (TypeError, ValueError, OSError):
|
|
81
|
+
pass
|
|
82
|
+
except (ImportError, ModuleNotFoundError, TypeError, AttributeError, OSError):
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
# Fallback: try relative to package directory
|
|
86
|
+
if script_path is None:
|
|
87
|
+
package_dir = Path(__file__).parent
|
|
88
|
+
fallback_script = package_dir / "scripts" / "get-next-version.cjs"
|
|
89
|
+
if fallback_script.exists():
|
|
90
|
+
script_path = fallback_script
|
|
91
|
+
|
|
92
|
+
if not script_path:
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
# Build command arguments
|
|
96
|
+
cmd = ["node", str(script_path), str(project_root)]
|
|
97
|
+
if subfolder_path and package_name:
|
|
98
|
+
# Workflow 1: subfolder build
|
|
99
|
+
rel_path = (
|
|
100
|
+
subfolder_path.relative_to(project_root)
|
|
101
|
+
if subfolder_path.is_absolute()
|
|
102
|
+
else subfolder_path
|
|
103
|
+
)
|
|
104
|
+
cmd.extend([str(rel_path), package_name])
|
|
105
|
+
elif package_name:
|
|
106
|
+
# Main package build with package_name (for registry queries)
|
|
107
|
+
# Pass null for subfolder_path, then package_name
|
|
108
|
+
cmd.extend(["", package_name])
|
|
109
|
+
# Workflow 2: main package without package_name (no additional args needed)
|
|
110
|
+
|
|
111
|
+
# Add repository information if provided
|
|
112
|
+
if repository:
|
|
113
|
+
cmd.append(repository)
|
|
114
|
+
if repository_url:
|
|
115
|
+
cmd.append(repository_url)
|
|
116
|
+
|
|
117
|
+
result = subprocess.run(
|
|
118
|
+
cmd,
|
|
119
|
+
capture_output=True,
|
|
120
|
+
text=True,
|
|
121
|
+
cwd=project_root,
|
|
122
|
+
check=False,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if result.returncode != 0:
|
|
126
|
+
# Log error details for debugging
|
|
127
|
+
if result.stderr:
|
|
128
|
+
print(
|
|
129
|
+
f"Warning: semantic-release version resolution failed: {result.stderr}",
|
|
130
|
+
file=sys.stderr,
|
|
131
|
+
)
|
|
132
|
+
elif result.stdout:
|
|
133
|
+
print(
|
|
134
|
+
f"Warning: semantic-release version resolution failed: {result.stdout}",
|
|
135
|
+
file=sys.stderr,
|
|
136
|
+
)
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
version = result.stdout.strip()
|
|
140
|
+
if version and version != "none":
|
|
141
|
+
return version
|
|
142
|
+
|
|
143
|
+
return None
|
|
144
|
+
except FileNotFoundError:
|
|
145
|
+
# Node.js not found
|
|
146
|
+
print(
|
|
147
|
+
"Warning: Node.js not found. Cannot resolve version via semantic-release.",
|
|
148
|
+
file=sys.stderr,
|
|
149
|
+
)
|
|
150
|
+
return None
|
|
151
|
+
except Exception as e:
|
|
152
|
+
# Other errors (e.g., permission issues, script not found)
|
|
153
|
+
print(
|
|
154
|
+
f"Warning: Error resolving version via semantic-release: {e}",
|
|
155
|
+
file=sys.stderr,
|
|
156
|
+
)
|
|
157
|
+
return None
|
|
158
|
+
finally:
|
|
159
|
+
# Clean up temporary file if we extracted from zip/pex
|
|
160
|
+
# This must be at function level to ensure cleanup even on early return
|
|
161
|
+
if temp_script_context is not None:
|
|
162
|
+
try:
|
|
163
|
+
temp_script_context.__exit__(None, None, None)
|
|
164
|
+
except Exception:
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
|
|
21
168
|
def main() -> int:
|
|
22
169
|
"""
|
|
23
170
|
Main entry point for the build script.
|
|
@@ -77,7 +224,7 @@ def main() -> int:
|
|
|
77
224
|
)
|
|
78
225
|
parser.add_argument(
|
|
79
226
|
"--version",
|
|
80
|
-
help="Set a specific version before building (PEP 440 format, e.g., '1.2.3').
|
|
227
|
+
help="Set a specific version before building (PEP 440 format, e.g., '1.2.3'). Optional: if omitted, version will be resolved via semantic-release when needed.",
|
|
81
228
|
)
|
|
82
229
|
parser.add_argument(
|
|
83
230
|
"--package-name",
|
|
@@ -151,18 +298,81 @@ def main() -> int:
|
|
|
151
298
|
sys.exit(result.returncode)
|
|
152
299
|
|
|
153
300
|
# Check if building a subfolder (not the main src/)
|
|
154
|
-
|
|
155
|
-
|
|
301
|
+
# A subfolder must be within the project root but not the main src/ directory
|
|
302
|
+
is_subfolder = (
|
|
303
|
+
src_dir.is_relative_to(project_root)
|
|
304
|
+
and src_dir != project_root / "src"
|
|
305
|
+
and src_dir != project_root
|
|
156
306
|
)
|
|
157
307
|
|
|
158
|
-
#
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
308
|
+
# Resolve version via semantic-release if not provided and needed
|
|
309
|
+
resolved_version = args.version
|
|
310
|
+
if not resolved_version and not args.analyze_only:
|
|
311
|
+
# Version is needed for subfolder builds or when publishing main package
|
|
312
|
+
if is_subfolder or args.publish:
|
|
313
|
+
print("No --version provided, attempting to resolve via semantic-release...")
|
|
314
|
+
# Get repository info if publishing
|
|
315
|
+
repository = args.publish if args.publish else None
|
|
316
|
+
repository_url = args.repository_url if args.publish else None
|
|
317
|
+
|
|
318
|
+
if is_subfolder:
|
|
319
|
+
# Workflow 1: subfolder build
|
|
320
|
+
# src_dir is guaranteed to be relative to project_root due to is_subfolder check
|
|
321
|
+
package_name = args.package_name or src_dir.name.replace("_", "-").replace(
|
|
322
|
+
" ", "-"
|
|
323
|
+
).lower().strip("-")
|
|
324
|
+
subfolder_rel_path = src_dir.relative_to(project_root)
|
|
325
|
+
resolved_version = resolve_version_via_semantic_release(
|
|
326
|
+
project_root,
|
|
327
|
+
subfolder_rel_path,
|
|
328
|
+
package_name,
|
|
329
|
+
repository=repository,
|
|
330
|
+
repository_url=repository_url,
|
|
331
|
+
)
|
|
332
|
+
else:
|
|
333
|
+
# Workflow 2: main package
|
|
334
|
+
# For main package, we need package_name from pyproject.toml for registry queries
|
|
335
|
+
package_name_for_registry = None
|
|
336
|
+
if repository:
|
|
337
|
+
try:
|
|
338
|
+
import tomllib
|
|
339
|
+
pyproject_path = project_root / "pyproject.toml"
|
|
340
|
+
if pyproject_path.exists():
|
|
341
|
+
with open(pyproject_path, "rb") as f:
|
|
342
|
+
data = tomllib.load(f)
|
|
343
|
+
package_name_for_registry = data.get("project", {}).get("name")
|
|
344
|
+
except Exception:
|
|
345
|
+
pass
|
|
346
|
+
|
|
347
|
+
resolved_version = resolve_version_via_semantic_release(
|
|
348
|
+
project_root,
|
|
349
|
+
subfolder_path=None,
|
|
350
|
+
package_name=package_name_for_registry,
|
|
351
|
+
repository=repository,
|
|
352
|
+
repository_url=repository_url,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
if resolved_version:
|
|
356
|
+
print(f"Resolved version via semantic-release: {resolved_version}")
|
|
357
|
+
else:
|
|
358
|
+
error_msg = (
|
|
359
|
+
"Could not resolve version via semantic-release.\n"
|
|
360
|
+
"This could mean:\n"
|
|
361
|
+
" - No release is needed (no relevant commits)\n"
|
|
362
|
+
" - semantic-release is not installed or configured\n"
|
|
363
|
+
" - Node.js is not available\n\n"
|
|
364
|
+
"Please either:\n"
|
|
365
|
+
" - Install semantic-release: npm install -g semantic-release"
|
|
366
|
+
)
|
|
367
|
+
if is_subfolder:
|
|
368
|
+
error_msg += "\n - Install semantic-release-commit-filter: npm install -g semantic-release-commit-filter"
|
|
369
|
+
error_msg += "\n - Or provide --version explicitly"
|
|
370
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
371
|
+
return 1
|
|
372
|
+
|
|
373
|
+
# Use resolved version for the rest of the flow
|
|
374
|
+
if resolved_version:
|
|
375
|
+
args.version = resolved_version
|
|
166
376
|
|
|
167
377
|
if args.publish:
|
|
168
378
|
manager.build_and_publish(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-package-folder
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.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>
|
|
@@ -75,6 +75,9 @@ cd src/api_package
|
|
|
75
75
|
# Build and publish to TestPyPI with version 1.2.0
|
|
76
76
|
python-package-folder --publish testpypi --version 1.2.0
|
|
77
77
|
|
|
78
|
+
# Or publish to PyPI with automatic version resolution via semantic-release
|
|
79
|
+
python-package-folder --publish pypi
|
|
80
|
+
|
|
78
81
|
# Or publish to PyPI with a custom package name
|
|
79
82
|
python-package-folder --publish pypi --version 1.2.0 --package-name "my-api-package"
|
|
80
83
|
|
|
@@ -169,6 +172,13 @@ uv add twine
|
|
|
169
172
|
|
|
170
173
|
**For secure credential storage**: `keyring` is optional but recommended (install with `pip install keyring`)
|
|
171
174
|
|
|
175
|
+
**For automatic version resolution**: When using `--version` optional mode (automatic version resolution via semantic-release), you'll need:
|
|
176
|
+
- Node.js and npm (or npx)
|
|
177
|
+
- semantic-release: `npm install -g semantic-release`
|
|
178
|
+
- For subfolder builds: semantic-release-commit-filter: `npm install -g semantic-release-commit-filter`
|
|
179
|
+
|
|
180
|
+
Alternatively, install these as devDependencies in your project's `package.json`.
|
|
181
|
+
|
|
172
182
|
|
|
173
183
|
## Quick Start
|
|
174
184
|
|
|
@@ -182,9 +192,13 @@ Useful for monorepos containing many subfolders that may need publishing as stan
|
|
|
182
192
|
# First cd to the specific subfolder
|
|
183
193
|
cd src/subfolder_to_build_and_publish
|
|
184
194
|
|
|
185
|
-
# Build and publish any subdirectory of your repo to TestPyPi (https://test.pypi.org/)
|
|
195
|
+
# Build and publish any subdirectory of your repo to TestPyPi (https://test.pypi.org/)
|
|
196
|
+
# Version can be provided explicitly or resolved automatically via semantic-release
|
|
186
197
|
python-package-folder --publish testpypi --version 0.0.2
|
|
187
198
|
|
|
199
|
+
# Or let semantic-release determine the next version automatically (requires semantic-release setup)
|
|
200
|
+
python-package-folder --publish testpypi
|
|
201
|
+
|
|
188
202
|
# Only analyse (no building)
|
|
189
203
|
cd src/subfolder_to_build_and_publish
|
|
190
204
|
python-package-folder --analyze-only
|
|
@@ -457,33 +471,89 @@ The `--version` option:
|
|
|
457
471
|
**Version Format**: Versions must follow PEP 440 (e.g., `1.2.3`, `1.2.3a1`, `1.2.3.post1`, `1.2.3.dev1`)
|
|
458
472
|
|
|
459
473
|
|
|
474
|
+
### Automatic Version Resolution (semantic-release)
|
|
475
|
+
|
|
476
|
+
When `--version` is not provided, the tool can automatically determine the next version using semantic-release. This requires Node.js, npm, and semantic-release to be installed.
|
|
477
|
+
|
|
478
|
+
**Version Detection:**
|
|
479
|
+
- **Baseline version**:
|
|
480
|
+
- **Registry Query (Preferred)**: When publishing to a repository (PyPI, TestPyPI, or Azure Artifacts), the tool queries the target registry for the latest published version and uses it as the baseline for version calculation. This ensures version calculations are based on what's actually published, not just git tags.
|
|
481
|
+
- **Git Tags (Fallback)**: If the package doesn't exist on the registry yet (first release) or if registry query fails, the tool falls back to using git tags to determine the starting version.
|
|
482
|
+
- **New version to publish**: After determining the baseline version, [`semantic-release`](https://semantic-release.gitbook.io/semantic-release/) analyzes commits since that version to calculate the next version bump (major, minor, or patch) based on [_conventional commit_](https://www.conventionalcommits.org/en/v1.0.0/) messages.
|
|
483
|
+
|
|
484
|
+
**For subfolder builds (Workflow 1):**
|
|
485
|
+
- Uses per-package tags: `{package-name}-v{version}` (e.g., `my-package-v1.2.3`)
|
|
486
|
+
- Queries the target registry for the latest published version of the subfolder package
|
|
487
|
+
- Filters commits to only those affecting the subfolder path
|
|
488
|
+
- **Commit filtering behavior**: Only commits that modify files within the subfolder path are considered for version calculation. Commits that only target files outside the subfolder are excluded. For example:
|
|
489
|
+
- `fix: update my_subfolder/foo.py` → **Included** (affects subfolder)
|
|
490
|
+
- `feat: add feature to other_package/bar.py` → **Excluded** (doesn't affect subfolder)
|
|
491
|
+
- `fix: update my_subfolder/baz.py and shared/utils.py` → **Included** (affects subfolder, even if it also touches files outside)
|
|
492
|
+
- Requires `semantic-release-commit-filter` plugin
|
|
493
|
+
|
|
494
|
+
**For main package builds (Workflow 2):**
|
|
495
|
+
- Uses repo-level tags: `v{version}` (e.g., `v1.2.3`)
|
|
496
|
+
- Queries the target registry for the latest published version when publishing
|
|
497
|
+
- Analyzes all commits in the repository
|
|
498
|
+
|
|
499
|
+
**Registry Support:**
|
|
500
|
+
- **PyPI**: Fully supported via JSON API (`https://pypi.org/pypi/{package-name}/json`)
|
|
501
|
+
- **TestPyPI**: Fully supported via JSON API (`https://test.pypi.org/pypi/{package-name}/json`)
|
|
502
|
+
- **Azure Artifacts**: Basic support with fallback to git tags. Azure Artifacts uses a different API format and may require authentication, so if the query fails, the tool automatically falls back to git tags.
|
|
503
|
+
|
|
504
|
+
**Setup:**
|
|
505
|
+
```bash
|
|
506
|
+
# Install semantic-release globally
|
|
507
|
+
npm install -g semantic-release
|
|
508
|
+
|
|
509
|
+
# For subfolder builds, also install semantic-release-commit-filter
|
|
510
|
+
npm install -g semantic-release-commit-filter
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**Usage:**
|
|
514
|
+
```bash
|
|
515
|
+
# Subfolder build - version resolved automatically
|
|
516
|
+
cd src/my_subfolder
|
|
517
|
+
python-package-folder --publish pypi
|
|
518
|
+
|
|
519
|
+
# Main package - version resolved automatically
|
|
520
|
+
python-package-folder --publish pypi
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**Requirements:**
|
|
524
|
+
- Conventional commits (e.g., `fix:`, `feat:`, `BREAKING CHANGE:`) are required for semantic-release to determine version bumps
|
|
525
|
+
- The tool will fall back to requiring `--version` explicitly if semantic-release is not available or determines no release is needed
|
|
526
|
+
|
|
460
527
|
### Subfolder Versioning
|
|
461
528
|
|
|
462
529
|
When building from a subdirectory (not the main `src/` directory), the tool automatically detects the subfolder and sets up the build configuration:
|
|
463
530
|
|
|
464
531
|
```bash
|
|
465
|
-
# Build a subfolder as a separate package
|
|
532
|
+
# Build a subfolder as a separate package with explicit version
|
|
466
533
|
cd my_project/subfolder_to_build
|
|
467
534
|
python-package-folder --version "1.0.0" --publish pypi
|
|
468
535
|
|
|
536
|
+
# Or let semantic-release determine the version automatically
|
|
537
|
+
python-package-folder --publish pypi
|
|
538
|
+
|
|
469
539
|
# With custom package name
|
|
470
540
|
python-package-folder --version "1.0.0" --package-name "my-custom-name" --publish pypi
|
|
471
|
-
|
|
472
|
-
# Version defaults to "0.0.0" if not specified (with a warning)
|
|
473
|
-
python-package-folder --publish pypi
|
|
474
541
|
```
|
|
475
542
|
|
|
476
543
|
For subfolder builds:
|
|
477
544
|
- **Automatic detection**: The tool automatically detects subfolder builds
|
|
545
|
+
- **Version resolution**:
|
|
546
|
+
- If `--version` is provided: Uses the explicit version
|
|
547
|
+
- If `--version` is omitted: Attempts to resolve via semantic-release (requires setup)
|
|
548
|
+
- If semantic-release is unavailable or determines no release: Requires `--version` explicitly
|
|
478
549
|
- **pyproject.toml handling**:
|
|
479
550
|
- If `pyproject.toml` exists in subfolder: Uses that file (copied to project root temporarily)
|
|
480
551
|
- If no `pyproject.toml` in subfolder: Creates temporary one with correct package structure
|
|
481
|
-
- **Version**: Recommended but not required when creating temporary pyproject.toml. If not provided, defaults to `0.0.0` with a warning. Ignored if subfolder has its own `pyproject.toml`.
|
|
482
552
|
- **Package name**: Automatically derived from the subfolder name (e.g., `subfolder_to_build` → `subfolder-to-build`). Only used when creating temporary pyproject.toml.
|
|
483
553
|
- **Restoration**: Original `pyproject.toml` is restored after build
|
|
484
554
|
- **Temporary configuration**: Creates a temporary `pyproject.toml` with:
|
|
485
555
|
- Custom package name (from `--package-name` or derived)
|
|
486
|
-
- Specified version
|
|
556
|
+
- Specified or resolved version
|
|
487
557
|
- Correct package path for hatchling
|
|
488
558
|
- Dependency group from parent (if `--dependency-group` is specified)
|
|
489
559
|
- **Package initialization**: Automatically creates `__init__.py` if the subfolder doesn't have one (required for hatchling)
|
|
@@ -686,7 +756,8 @@ options:
|
|
|
686
756
|
--password PASSWORD Password/token for publishing (will prompt if not provided)
|
|
687
757
|
--skip-existing Skip files that already exist on the repository
|
|
688
758
|
--version VERSION Set a specific version before building (PEP 440 format).
|
|
689
|
-
|
|
759
|
+
Optional: if omitted, version will be resolved via
|
|
760
|
+
semantic-release (requires Node.js and semantic-release setup).
|
|
690
761
|
--package-name PACKAGE_NAME
|
|
691
762
|
Package name for subfolder builds (default: derived from
|
|
692
763
|
source directory name)
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
python_package_folder/__init__.py,sha256=DQt-uldOEKfh0MUqCvKdeNKOnpuOvpb7blYvXMyO9Wc,719
|
|
2
2
|
python_package_folder/__main__.py,sha256=a-__-VLhYw-J7S7CsHdhtEvQr3RiAZxiYDvKhKTgMX4,291
|
|
3
|
+
python_package_folder/_hatch_build.py,sha256=HNuhBz5e6uoDNVPKHFcX-8H23u6qyXNM8KO9DgRGXMM,1844
|
|
3
4
|
python_package_folder/analyzer.py,sha256=cmTNUDCWBIh3XZ_mShlQVG1P9NN_oe3FUBTirVtYfTQ,16709
|
|
4
5
|
python_package_folder/finder.py,sha256=RPidZ7LKCFuQ_KgCFIZdHWPXsZIDor3M4C0hKeYW7EI,11799
|
|
5
6
|
python_package_folder/manager.py,sha256=Z9RPg0ZQ7jZhmEXfCzX9OrD_oiA5p2Pnm5Y9tgW3ObQ,55970
|
|
6
7
|
python_package_folder/publisher.py,sha256=TSjdOvxvnWLbJCnduTK_xZBRfvsrq9kpEH-sfebeWkU,13507
|
|
7
8
|
python_package_folder/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
python_package_folder/python_package_folder.py,sha256=
|
|
9
|
+
python_package_folder/python_package_folder.py,sha256=xSMUD_uiCOVHDDT4WNso9AxAYNyqhKI103G2rJztaXw,17907
|
|
9
10
|
python_package_folder/subfolder_build.py,sha256=oH_KKLJIMByUZCl8y3AyohUO6Om0OvsIQ7Xg1fkd3jE,38782
|
|
10
11
|
python_package_folder/types.py,sha256=3yeSRR5p_3PDKEAaehW_RJ7NwJHexOIeA08bGaT1iSY,2368
|
|
11
12
|
python_package_folder/utils.py,sha256=lIkWsFKeAYAJ9TDUM99T4pUBHJVbUvCdUgkWQN-LUho,3111
|
|
12
13
|
python_package_folder/version.py,sha256=kIDP6S9trEfs9gj7lBYGxrWm4RPssRla24UtlO9Jkh4,9111
|
|
13
|
-
python_package_folder-
|
|
14
|
-
python_package_folder-
|
|
15
|
-
python_package_folder-
|
|
16
|
-
python_package_folder-
|
|
17
|
-
python_package_folder-
|
|
14
|
+
python_package_folder-4.1.0.dist-info/METADATA,sha256=yk49H6KBuadlyqKiHeC589X6pBvUTBVd4YXs6idsnYE,37517
|
|
15
|
+
python_package_folder-4.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
16
|
+
python_package_folder-4.1.0.dist-info/entry_points.txt,sha256=ttu4wAhoYSHGhWQNercLz9IVTTpXxhVlRA9vSTvaLe0,91
|
|
17
|
+
python_package_folder-4.1.0.dist-info/licenses/LICENSE,sha256=vNgRJh8YiecqZoZld7TtwPI5I72HIymKD9g32fiJjCE,1073
|
|
18
|
+
python_package_folder-4.1.0.dist-info/RECORD,,
|
{python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{python_package_folder-3.1.3.dist-info → python_package_folder-4.1.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|