python-package-folder 5.1.5__tar.gz → 5.1.6__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.1.5 → python_package_folder-5.1.6}/PKG-INFO +1 -1
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/pyproject.toml +1 -1
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/publisher.py +60 -14
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.copier-answers.yml +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.cursor/plans/optional_version_+_semantic-release_efed88a6.plan.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.cursor/plans/replace_node.js_semantic-release_with_custom_python_implementation_64e05e1a.plan.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.cursor/rules/general.mdc +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.cursor/rules/python.mdc +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.github/workflows/ci.yml +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.github/workflows/publish.yml +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.gitignore +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/.vscode/settings.json +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/LICENSE +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/MANIFEST.in +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/Makefile +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/README.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/coverage.svg +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/development.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/docs/DEVELOPMENT.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/docs/INSTALLATION.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/docs/PUBLISHING.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/docs/REFERENCE.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/docs/USAGE.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/docs/VERSION_RESOLUTION.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/installation.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/publishing.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/__init__.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/__main__.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/analyzer.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/finder.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/manager.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/py.typed +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/python_package_folder.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/subfolder_build.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/types.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/utils.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/version.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/version_calculator.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/conftest.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/some_globals.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/subfolder_to_build/README.md +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/subfolder_to_build/__init__.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/subfolder_to_build/some_function.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/subfolder_to_build/some_globals.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/utility_folder/_SS/some_superseded_file.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/folder_structure/utility_folder/some_utility.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_build_with_external_deps.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_exclude_patterns.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_linting.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_preserve_directory_structure.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_publisher.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_shared_subdirectory_imports.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_spreadsheet_creation_imports.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_subfolder_build.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_third_party_dependencies.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_utils.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_version_calculator.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_version_manager.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/tests.py +0 -0
- {python_package_folder-5.1.5 → python_package_folder-5.1.6}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-package-folder
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.6
|
|
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.1.5 → python_package_folder-5.1.6}/src/python_package_folder/publisher.py
RENAMED
|
@@ -8,6 +8,7 @@ repositories including PyPI, PyPI Test, and Azure Artifacts.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import getpass
|
|
11
|
+
import os
|
|
11
12
|
import subprocess
|
|
12
13
|
import sys
|
|
13
14
|
from enum import Enum
|
|
@@ -19,6 +20,18 @@ except ImportError:
|
|
|
19
20
|
keyring = None
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
def _is_non_interactive() -> bool:
|
|
24
|
+
"""Check if running in a non-interactive environment (CI/CD)."""
|
|
25
|
+
# Check for common CI environment variables
|
|
26
|
+
ci_vars = ["GITHUB_ACTIONS", "CI", "CONTINUOUS_INTEGRATION", "TF_BUILD"]
|
|
27
|
+
if any(os.getenv(var) for var in ci_vars):
|
|
28
|
+
return True
|
|
29
|
+
# Check if stdin is not a TTY (non-interactive)
|
|
30
|
+
if not sys.stdin.isatty():
|
|
31
|
+
return True
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
|
|
22
35
|
class Repository(Enum):
|
|
23
36
|
"""
|
|
24
37
|
Supported package repositories.
|
|
@@ -112,9 +125,9 @@ class Publisher:
|
|
|
112
125
|
"""
|
|
113
126
|
Get credentials for publishing.
|
|
114
127
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
128
|
+
Prompts for username and password/token if not already provided.
|
|
129
|
+
In non-interactive environments (CI/CD), checks environment variables
|
|
130
|
+
or raises an error if credentials are missing.
|
|
118
131
|
|
|
119
132
|
Returns:
|
|
120
133
|
Tuple of (username, password/token)
|
|
@@ -122,21 +135,54 @@ class Publisher:
|
|
|
122
135
|
username = self.username
|
|
123
136
|
password = self.password
|
|
124
137
|
|
|
125
|
-
|
|
126
|
-
|
|
138
|
+
is_non_interactive_env = _is_non_interactive()
|
|
139
|
+
|
|
140
|
+
# Get username
|
|
127
141
|
if not username:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
142
|
+
if is_non_interactive_env:
|
|
143
|
+
# Check environment variables
|
|
144
|
+
username = os.getenv("TWINE_USERNAME") or os.getenv("PYPI_USERNAME")
|
|
145
|
+
if not username:
|
|
146
|
+
raise ValueError(
|
|
147
|
+
f"Username is required for publishing to {self.repository.value} in CI/CD. "
|
|
148
|
+
"Please provide --username argument or set TWINE_USERNAME/PYPI_USERNAME environment variable."
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
username = input(f"Enter username for {self.repository.value}: ").strip()
|
|
152
|
+
if not username:
|
|
153
|
+
raise ValueError("Username is required")
|
|
131
154
|
|
|
155
|
+
# Get password
|
|
132
156
|
if not password:
|
|
133
|
-
if
|
|
134
|
-
|
|
157
|
+
if is_non_interactive_env:
|
|
158
|
+
# Check environment variables (common names used by twine and CI/CD)
|
|
159
|
+
password = (
|
|
160
|
+
os.getenv("TWINE_PASSWORD")
|
|
161
|
+
or os.getenv("PYPI_PASSWORD")
|
|
162
|
+
or os.getenv("AZURE_ARTIFACTS_TOKEN") # For Azure
|
|
163
|
+
)
|
|
164
|
+
if not password:
|
|
165
|
+
raise ValueError(
|
|
166
|
+
f"Password/token is required for publishing to {self.repository.value} in CI/CD. "
|
|
167
|
+
"Please provide --password argument or set one of: "
|
|
168
|
+
"TWINE_PASSWORD, PYPI_PASSWORD, or AZURE_ARTIFACTS_TOKEN environment variable."
|
|
169
|
+
)
|
|
135
170
|
else:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
171
|
+
if self.repository == Repository.AZURE:
|
|
172
|
+
prompt = f"Enter Azure Artifacts token for {username}: "
|
|
173
|
+
else:
|
|
174
|
+
prompt = f"Enter PyPI token for {username} (or __token__ for API token): "
|
|
175
|
+
try:
|
|
176
|
+
password = getpass.getpass(prompt)
|
|
177
|
+
except (EOFError, OSError):
|
|
178
|
+
# Handle non-interactive environments gracefully
|
|
179
|
+
raise ValueError(
|
|
180
|
+
f"Password/token is required for publishing to {self.repository.value}. "
|
|
181
|
+
"Cannot prompt for password in non-interactive environment. "
|
|
182
|
+
"Please provide --password argument or set TWINE_PASSWORD/PYPI_PASSWORD environment variable."
|
|
183
|
+
)
|
|
184
|
+
if not password:
|
|
185
|
+
raise ValueError("Password/token is required")
|
|
140
186
|
|
|
141
187
|
# Auto-detect if password is an API token and adjust username
|
|
142
188
|
if password.startswith("pypi-") or password.startswith("pypi_Ag"):
|
|
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.1.5 → python_package_folder-5.1.6}/src/python_package_folder/__init__.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/__main__.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/analyzer.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/finder.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/manager.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/types.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/utils.py
RENAMED
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/src/python_package_folder/version.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/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.1.5 → python_package_folder-5.1.6}/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.1.5 → python_package_folder-5.1.6}/tests/test_third_party_dependencies.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_package_folder-5.1.5 → python_package_folder-5.1.6}/tests/test_version_calculator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|