python-package-folder 4.1.0__py3-none-any.whl → 4.1.2__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/python_package_folder.py +166 -37
- {python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/METADATA +1 -1
- {python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/RECORD +6 -6
- {python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/WHEEL +0 -0
- {python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/entry_points.txt +0 -0
- {python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,6 +10,8 @@ It can be invoked via:
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import os
|
|
14
|
+
import shutil
|
|
13
15
|
import subprocess
|
|
14
16
|
import sys
|
|
15
17
|
from pathlib import Path
|
|
@@ -23,13 +25,23 @@ from .manager import BuildManager
|
|
|
23
25
|
from .utils import find_project_root, find_source_directory
|
|
24
26
|
|
|
25
27
|
|
|
28
|
+
def is_github_actions() -> bool:
|
|
29
|
+
"""Check if running in GitHub Actions."""
|
|
30
|
+
return os.getenv("GITHUB_ACTIONS") == "true"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def check_node_available() -> bool:
|
|
34
|
+
"""Check if Node.js is available."""
|
|
35
|
+
return shutil.which("node") is not None
|
|
36
|
+
|
|
37
|
+
|
|
26
38
|
def resolve_version_via_semantic_release(
|
|
27
39
|
project_root: Path,
|
|
28
40
|
subfolder_path: Path | None = None,
|
|
29
41
|
package_name: str | None = None,
|
|
30
42
|
repository: str | None = None,
|
|
31
43
|
repository_url: str | None = None,
|
|
32
|
-
) -> str | None:
|
|
44
|
+
) -> tuple[str | None, str | None]:
|
|
33
45
|
"""
|
|
34
46
|
Resolve the next version using semantic-release via Node.js script.
|
|
35
47
|
|
|
@@ -41,8 +53,34 @@ def resolve_version_via_semantic_release(
|
|
|
41
53
|
repository_url: Optional repository URL (required for Azure Artifacts)
|
|
42
54
|
|
|
43
55
|
Returns:
|
|
44
|
-
|
|
56
|
+
Tuple of (version string if a release is determined, error message if any)
|
|
57
|
+
Returns (None, None) if no release or no error, (None, error_msg) on error
|
|
45
58
|
"""
|
|
59
|
+
# Note: Node.js availability should be checked before calling this function
|
|
60
|
+
# This check is a safety fallback
|
|
61
|
+
if not check_node_available():
|
|
62
|
+
if is_github_actions():
|
|
63
|
+
error_msg = """Node.js is not available in this GitHub Actions workflow.
|
|
64
|
+
|
|
65
|
+
To fix this, add the following steps BEFORE running python-package-folder:
|
|
66
|
+
|
|
67
|
+
- name: Setup Node.js
|
|
68
|
+
uses: actions/setup-node@v4
|
|
69
|
+
with:
|
|
70
|
+
node-version: '20'
|
|
71
|
+
|
|
72
|
+
- name: Install semantic-release
|
|
73
|
+
run: |
|
|
74
|
+
npm install -g semantic-release semantic-release-commit-filter
|
|
75
|
+
|
|
76
|
+
Alternatively, provide --version explicitly to skip automatic version resolution."""
|
|
77
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
78
|
+
return None, error_msg
|
|
79
|
+
else:
|
|
80
|
+
error_msg = "Node.js not found. Cannot resolve version via semantic-release."
|
|
81
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
82
|
+
return None, error_msg
|
|
83
|
+
|
|
46
84
|
# Try to find the script in multiple locations:
|
|
47
85
|
# 1. Project root / scripts (for development or when script is in repo)
|
|
48
86
|
# 2. Package installation directory / scripts (for installed package)
|
|
@@ -60,37 +98,70 @@ def resolve_version_via_semantic_release(
|
|
|
60
98
|
else:
|
|
61
99
|
# Try to locate script in installed package using importlib.resources
|
|
62
100
|
script_path = None
|
|
101
|
+
diagnostic_info = []
|
|
102
|
+
|
|
103
|
+
# Try importlib.resources approach
|
|
63
104
|
try:
|
|
64
105
|
package = resources.files("python_package_folder")
|
|
65
106
|
script_resource = package / "scripts" / "get-next-version.cjs"
|
|
107
|
+
|
|
108
|
+
diagnostic_info.append(f"Checked importlib.resources: python_package_folder/scripts/get-next-version.cjs")
|
|
109
|
+
|
|
66
110
|
if script_resource.is_file():
|
|
67
111
|
# Try direct path conversion first (normal file system install)
|
|
68
112
|
try:
|
|
69
113
|
script_path_candidate = Path(str(script_resource))
|
|
70
114
|
if script_path_candidate.exists():
|
|
71
115
|
script_path = script_path_candidate
|
|
72
|
-
|
|
73
|
-
|
|
116
|
+
diagnostic_info.append(f"Found via direct path: {script_path}")
|
|
117
|
+
except (TypeError, ValueError) as e:
|
|
118
|
+
diagnostic_info.append(f"Direct path conversion failed: {e}")
|
|
74
119
|
|
|
75
120
|
# If direct path didn't work, try as_file() for zip/pex installs
|
|
76
121
|
if script_path is None:
|
|
77
122
|
try:
|
|
78
123
|
temp_script_context = resources.as_file(script_resource)
|
|
79
124
|
script_path = temp_script_context.__enter__()
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
125
|
+
diagnostic_info.append(f"Found via as_file() (temp): {script_path}")
|
|
126
|
+
except (TypeError, ValueError, OSError) as e:
|
|
127
|
+
diagnostic_info.append(f"as_file() extraction failed: {e}")
|
|
128
|
+
else:
|
|
129
|
+
# Try to list what's actually in the scripts directory
|
|
130
|
+
try:
|
|
131
|
+
scripts_dir = package / "scripts"
|
|
132
|
+
if scripts_dir.is_dir():
|
|
133
|
+
available_files = list(scripts_dir.iterdir())
|
|
134
|
+
diagnostic_info.append(f"Scripts directory exists. Available files: {[f.name for f in available_files]}")
|
|
135
|
+
else:
|
|
136
|
+
diagnostic_info.append("Scripts directory does not exist in package")
|
|
137
|
+
except Exception as e:
|
|
138
|
+
diagnostic_info.append(f"Could not list scripts directory: {e}")
|
|
139
|
+
except (ImportError, ModuleNotFoundError, TypeError, AttributeError, OSError) as e:
|
|
140
|
+
diagnostic_info.append(f"importlib.resources failed: {type(e).__name__}: {e}")
|
|
84
141
|
|
|
85
142
|
# Fallback: try relative to package directory
|
|
86
143
|
if script_path is None:
|
|
87
144
|
package_dir = Path(__file__).parent
|
|
88
145
|
fallback_script = package_dir / "scripts" / "get-next-version.cjs"
|
|
146
|
+
diagnostic_info.append(f"Checked fallback path: {fallback_script}")
|
|
89
147
|
if fallback_script.exists():
|
|
90
148
|
script_path = fallback_script
|
|
149
|
+
diagnostic_info.append(f"Found via fallback: {script_path}")
|
|
150
|
+
else:
|
|
151
|
+
diagnostic_info.append(f"Fallback path does not exist")
|
|
91
152
|
|
|
92
153
|
if not script_path:
|
|
93
|
-
|
|
154
|
+
error_msg = "Could not locate get-next-version.cjs script"
|
|
155
|
+
error_msg += "\n\nDiagnostic information:"
|
|
156
|
+
for info in diagnostic_info:
|
|
157
|
+
error_msg += f"\n - {info}"
|
|
158
|
+
error_msg += (
|
|
159
|
+
"\n\nThis usually means the script was not included in the installed package."
|
|
160
|
+
"\nPlease ensure you're using the latest version of python-package-folder."
|
|
161
|
+
"\nIf the issue persists, report this as a bug."
|
|
162
|
+
)
|
|
163
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
164
|
+
return None, error_msg
|
|
94
165
|
|
|
95
166
|
# Build command arguments
|
|
96
167
|
cmd = ["node", str(script_path), str(project_root)]
|
|
@@ -123,38 +194,53 @@ def resolve_version_via_semantic_release(
|
|
|
123
194
|
)
|
|
124
195
|
|
|
125
196
|
if result.returncode != 0:
|
|
126
|
-
#
|
|
197
|
+
# Collect error details
|
|
198
|
+
error_details = []
|
|
127
199
|
if result.stderr:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return None
|
|
200
|
+
error_details.append(f"stderr: {result.stderr}")
|
|
201
|
+
if result.stdout:
|
|
202
|
+
error_details.append(f"stdout: {result.stdout}")
|
|
203
|
+
|
|
204
|
+
error_msg = "semantic-release version resolution failed"
|
|
205
|
+
if error_details:
|
|
206
|
+
error_msg += f": {'; '.join(error_details)}"
|
|
207
|
+
|
|
208
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
209
|
+
return None, error_msg
|
|
138
210
|
|
|
139
211
|
version = result.stdout.strip()
|
|
140
212
|
if version and version != "none":
|
|
141
|
-
return version
|
|
213
|
+
return version, None
|
|
142
214
|
|
|
143
|
-
return None
|
|
215
|
+
return None, None
|
|
144
216
|
except FileNotFoundError:
|
|
145
|
-
# Node.js not found
|
|
146
|
-
|
|
147
|
-
"
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
217
|
+
# Node.js not found (shouldn't happen if check_node_available() passed, but handle gracefully)
|
|
218
|
+
if is_github_actions():
|
|
219
|
+
error_msg = """Node.js is not available in this GitHub Actions workflow.
|
|
220
|
+
|
|
221
|
+
To fix this, add the following steps BEFORE running python-package-folder:
|
|
222
|
+
|
|
223
|
+
- name: Setup Node.js
|
|
224
|
+
uses: actions/setup-node@v4
|
|
225
|
+
with:
|
|
226
|
+
node-version: '20'
|
|
227
|
+
|
|
228
|
+
- name: Install semantic-release
|
|
229
|
+
run: |
|
|
230
|
+
npm install -g semantic-release semantic-release-commit-filter
|
|
231
|
+
|
|
232
|
+
Alternatively, provide --version explicitly to skip automatic version resolution."""
|
|
233
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
234
|
+
return None, error_msg
|
|
235
|
+
else:
|
|
236
|
+
error_msg = "Node.js not found. Cannot resolve version via semantic-release."
|
|
237
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
238
|
+
return None, error_msg
|
|
151
239
|
except Exception as e:
|
|
152
240
|
# Other errors (e.g., permission issues, script not found)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
)
|
|
157
|
-
return None
|
|
241
|
+
error_msg = f"Error resolving version via semantic-release: {e}"
|
|
242
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
243
|
+
return None, error_msg
|
|
158
244
|
finally:
|
|
159
245
|
# Clean up temporary file if we extracted from zip/pex
|
|
160
246
|
# This must be at function level to ensure cleanup even on early return
|
|
@@ -311,6 +397,46 @@ def main() -> int:
|
|
|
311
397
|
# Version is needed for subfolder builds or when publishing main package
|
|
312
398
|
if is_subfolder or args.publish:
|
|
313
399
|
print("No --version provided, attempting to resolve via semantic-release...")
|
|
400
|
+
|
|
401
|
+
# Check Node.js availability upfront
|
|
402
|
+
if not check_node_available():
|
|
403
|
+
if is_github_actions():
|
|
404
|
+
error_msg = """Node.js is not available in this GitHub Actions workflow.
|
|
405
|
+
|
|
406
|
+
To fix this, add the following steps BEFORE running python-package-folder:
|
|
407
|
+
|
|
408
|
+
- name: Setup Node.js
|
|
409
|
+
uses: actions/setup-node@v4
|
|
410
|
+
with:
|
|
411
|
+
node-version: '20'
|
|
412
|
+
|
|
413
|
+
- name: Install semantic-release
|
|
414
|
+
run: |
|
|
415
|
+
npm install -g semantic-release semantic-release-commit-filter
|
|
416
|
+
|
|
417
|
+
Alternatively, provide --version explicitly to skip automatic version resolution."""
|
|
418
|
+
print(f"Error: {error_msg}", file=sys.stderr)
|
|
419
|
+
else:
|
|
420
|
+
print(
|
|
421
|
+
"Error: Node.js is not available. Cannot resolve version via semantic-release.",
|
|
422
|
+
file=sys.stderr,
|
|
423
|
+
)
|
|
424
|
+
print(
|
|
425
|
+
"Please install Node.js or provide --version explicitly.",
|
|
426
|
+
file=sys.stderr,
|
|
427
|
+
)
|
|
428
|
+
return 1
|
|
429
|
+
|
|
430
|
+
# Log that Node.js is available (for debugging)
|
|
431
|
+
node_version = subprocess.run(
|
|
432
|
+
["node", "--version"],
|
|
433
|
+
capture_output=True,
|
|
434
|
+
text=True,
|
|
435
|
+
check=False,
|
|
436
|
+
)
|
|
437
|
+
if node_version.returncode == 0:
|
|
438
|
+
print(f"Node.js detected: {node_version.stdout.strip()}")
|
|
439
|
+
|
|
314
440
|
# Get repository info if publishing
|
|
315
441
|
repository = args.publish if args.publish else None
|
|
316
442
|
repository_url = args.repository_url if args.publish else None
|
|
@@ -322,7 +448,7 @@ def main() -> int:
|
|
|
322
448
|
" ", "-"
|
|
323
449
|
).lower().strip("-")
|
|
324
450
|
subfolder_rel_path = src_dir.relative_to(project_root)
|
|
325
|
-
resolved_version = resolve_version_via_semantic_release(
|
|
451
|
+
resolved_version, error_details = resolve_version_via_semantic_release(
|
|
326
452
|
project_root,
|
|
327
453
|
subfolder_rel_path,
|
|
328
454
|
package_name,
|
|
@@ -344,7 +470,7 @@ def main() -> int:
|
|
|
344
470
|
except Exception:
|
|
345
471
|
pass
|
|
346
472
|
|
|
347
|
-
resolved_version = resolve_version_via_semantic_release(
|
|
473
|
+
resolved_version, error_details = resolve_version_via_semantic_release(
|
|
348
474
|
project_root,
|
|
349
475
|
subfolder_path=None,
|
|
350
476
|
package_name=package_name_for_registry,
|
|
@@ -360,8 +486,11 @@ def main() -> int:
|
|
|
360
486
|
"This could mean:\n"
|
|
361
487
|
" - No release is needed (no relevant commits)\n"
|
|
362
488
|
" - semantic-release is not installed or configured\n"
|
|
363
|
-
|
|
364
|
-
|
|
489
|
+
)
|
|
490
|
+
if error_details:
|
|
491
|
+
error_msg += f"\nDetails: {error_details}\n"
|
|
492
|
+
error_msg += (
|
|
493
|
+
"\nPlease either:\n"
|
|
365
494
|
" - Install semantic-release: npm install -g semantic-release"
|
|
366
495
|
)
|
|
367
496
|
if is_subfolder:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-package-folder
|
|
3
|
-
Version: 4.1.
|
|
3
|
+
Version: 4.1.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>
|
|
@@ -6,13 +6,13 @@ python_package_folder/finder.py,sha256=RPidZ7LKCFuQ_KgCFIZdHWPXsZIDor3M4C0hKeYW7
|
|
|
6
6
|
python_package_folder/manager.py,sha256=Z9RPg0ZQ7jZhmEXfCzX9OrD_oiA5p2Pnm5Y9tgW3ObQ,55970
|
|
7
7
|
python_package_folder/publisher.py,sha256=TSjdOvxvnWLbJCnduTK_xZBRfvsrq9kpEH-sfebeWkU,13507
|
|
8
8
|
python_package_folder/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
python_package_folder/python_package_folder.py,sha256=
|
|
9
|
+
python_package_folder/python_package_folder.py,sha256=cwc-o96qG3drhdhiTNomdR3jVOABLSP8T8rgtTxxXNE,23854
|
|
10
10
|
python_package_folder/subfolder_build.py,sha256=oH_KKLJIMByUZCl8y3AyohUO6Om0OvsIQ7Xg1fkd3jE,38782
|
|
11
11
|
python_package_folder/types.py,sha256=3yeSRR5p_3PDKEAaehW_RJ7NwJHexOIeA08bGaT1iSY,2368
|
|
12
12
|
python_package_folder/utils.py,sha256=lIkWsFKeAYAJ9TDUM99T4pUBHJVbUvCdUgkWQN-LUho,3111
|
|
13
13
|
python_package_folder/version.py,sha256=kIDP6S9trEfs9gj7lBYGxrWm4RPssRla24UtlO9Jkh4,9111
|
|
14
|
-
python_package_folder-4.1.
|
|
15
|
-
python_package_folder-4.1.
|
|
16
|
-
python_package_folder-4.1.
|
|
17
|
-
python_package_folder-4.1.
|
|
18
|
-
python_package_folder-4.1.
|
|
14
|
+
python_package_folder-4.1.2.dist-info/METADATA,sha256=VfbnD998xzZY883EYPQlKAgmWEocNeLl_FVm7YvBsGU,37517
|
|
15
|
+
python_package_folder-4.1.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
16
|
+
python_package_folder-4.1.2.dist-info/entry_points.txt,sha256=ttu4wAhoYSHGhWQNercLz9IVTTpXxhVlRA9vSTvaLe0,91
|
|
17
|
+
python_package_folder-4.1.2.dist-info/licenses/LICENSE,sha256=vNgRJh8YiecqZoZld7TtwPI5I72HIymKD9g32fiJjCE,1073
|
|
18
|
+
python_package_folder-4.1.2.dist-info/RECORD,,
|
|
File without changes
|
{python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{python_package_folder-4.1.0.dist-info → python_package_folder-4.1.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|