quickpub 3.0.5__tar.gz → 3.0.61__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.
- {quickpub-3.0.5/quickpub.egg-info → quickpub-3.0.61}/PKG-INFO +2 -2
- {quickpub-3.0.5 → quickpub-3.0.61}/README.md +1 -1
- {quickpub-3.0.5 → quickpub-3.0.61}/pyproject.toml +1 -1
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/logging_.py +16 -10
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/quality_assurance_runners/unittest_qa_runner.py +116 -108
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/upload_targets/github_upload_target.py +13 -7
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/upload_targets/pypirc_upload_target.py +75 -65
- {quickpub-3.0.5 → quickpub-3.0.61/quickpub.egg-info}/PKG-INFO +2 -2
- {quickpub-3.0.5 → quickpub-3.0.61}/LICENSE +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/MANIFEST.in +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/__main__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/classifiers.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/enforcers.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/files.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/functions.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/proxy.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/py.typed +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/qa.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/build_schema.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/constraint_enforcer.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/build_schemas/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/build_schemas/setuptools_build_schema.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/constraint_enforcers/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/constraint_enforcers/license_enforcer.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/constraint_enforcers/local_version_enforcer.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/constraint_enforcers/pypi_remote_version_enforcer.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/constraint_enforcers/pypirc_enforcer.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/constraint_enforcers/readme_enforcer.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/python_providers/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/python_providers/conda_python_provider.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/python_providers/default_python_provider.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/quality_assurance_runners/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/quality_assurance_runners/mypy_qa_runner.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/quality_assurance_runners/pylint_qa_runner.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/quality_assurance_runners/pytest_qa_runner.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/upload_targets/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/python_provider.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/quality_assurance_runner.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/quickpub_strategy.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/upload_target.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/structures/__init__.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/structures/bound.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/structures/dependency.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/structures/version.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/validators.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub/worker_pool.py +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub.egg-info/SOURCES.txt +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub.egg-info/dependency_links.txt +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub.egg-info/requires.txt +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/quickpub.egg-info/top_level.txt +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/setup.cfg +0 -0
- {quickpub-3.0.5 → quickpub-3.0.61}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quickpub
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.61
|
|
4
4
|
Summary: A python package to quickly configure and publish a new package
|
|
5
5
|
Author-email: danielnachumdev <danielnachumdev@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -38,7 +38,7 @@ Requires-Dist: requests
|
|
|
38
38
|
Requires-Dist: fire
|
|
39
39
|
Dynamic: license-file
|
|
40
40
|
|
|
41
|
-
# QuickPub v3.0.
|
|
41
|
+
# QuickPub v3.0.61
|
|
42
42
|
|
|
43
43
|
[](https://www.python.org/downloads/)
|
|
44
44
|
[](LICENSE)
|
|
@@ -4,14 +4,16 @@ import sys
|
|
|
4
4
|
# Global log level that can be modified by users
|
|
5
5
|
_LOG_LEVEL = logging.INFO
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
class QuickpubLogFilter(logging.Filter):
|
|
8
9
|
"""
|
|
9
10
|
Filter that only allows logs from the quickpub package.
|
|
10
11
|
"""
|
|
11
|
-
|
|
12
|
+
|
|
12
13
|
def filter(self, record):
|
|
13
14
|
return record.name.startswith('quickpub')
|
|
14
15
|
|
|
16
|
+
|
|
15
17
|
class TqdmLoggingHandler(logging.Handler):
|
|
16
18
|
"""
|
|
17
19
|
Custom logging handler that uses tqdm.write to avoid conflicts with progress bars.
|
|
@@ -32,6 +34,7 @@ class TqdmLoggingHandler(logging.Handler):
|
|
|
32
34
|
except Exception:
|
|
33
35
|
self.handleError(record)
|
|
34
36
|
|
|
37
|
+
|
|
35
38
|
def setup_logging(level: int = None):
|
|
36
39
|
"""
|
|
37
40
|
Set up logging with appropriate handler based on tqdm availability.
|
|
@@ -46,11 +49,11 @@ def setup_logging(level: int = None):
|
|
|
46
49
|
Configured logger instance
|
|
47
50
|
"""
|
|
48
51
|
global _LOG_LEVEL
|
|
49
|
-
|
|
52
|
+
|
|
50
53
|
# Use provided level or fall back to global constant
|
|
51
54
|
if level is not None:
|
|
52
55
|
_LOG_LEVEL = level
|
|
53
|
-
|
|
56
|
+
|
|
54
57
|
logger = logging.getLogger()
|
|
55
58
|
logger.setLevel(_LOG_LEVEL)
|
|
56
59
|
|
|
@@ -58,8 +61,9 @@ def setup_logging(level: int = None):
|
|
|
58
61
|
logger.handlers.clear()
|
|
59
62
|
|
|
60
63
|
# Common formatter for both handlers
|
|
64
|
+
# Example output: 2024-01-15 10:30:45,123 - INFO - [quickpub.some_module - some_module.py:42] - This is a log message
|
|
61
65
|
formatter = logging.Formatter(
|
|
62
|
-
'%(asctime)s - %(
|
|
66
|
+
'%(asctime)s - %(levelname)s - [%(name)s - %(filename)s:%(lineno)d] - %(message)s'
|
|
63
67
|
)
|
|
64
68
|
|
|
65
69
|
try:
|
|
@@ -71,33 +75,35 @@ def setup_logging(level: int = None):
|
|
|
71
75
|
handler = logging.StreamHandler(sys.stdout)
|
|
72
76
|
handler.setLevel(_LOG_LEVEL)
|
|
73
77
|
handler.setFormatter(formatter)
|
|
74
|
-
|
|
78
|
+
|
|
75
79
|
# Add filter to only allow quickpub logs
|
|
76
80
|
handler.addFilter(QuickpubLogFilter())
|
|
77
|
-
|
|
81
|
+
|
|
78
82
|
logger.addHandler(handler)
|
|
79
83
|
|
|
84
|
+
|
|
80
85
|
def set_log_level(level: int):
|
|
81
86
|
"""
|
|
82
87
|
Set the logging level for the root logger and all its handlers.
|
|
83
|
-
|
|
88
|
+
|
|
84
89
|
This function allows end users to dynamically change the log level
|
|
85
90
|
after logging has been set up. It also updates the global _LOG_LEVEL
|
|
86
91
|
constant so that future calls to setup_logging() will use this level.
|
|
87
|
-
|
|
92
|
+
|
|
88
93
|
Args:
|
|
89
94
|
level: Logging level (e.g., logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR)
|
|
90
95
|
"""
|
|
91
96
|
global _LOG_LEVEL
|
|
92
97
|
_LOG_LEVEL = level
|
|
93
|
-
|
|
98
|
+
|
|
94
99
|
logger = logging.getLogger()
|
|
95
100
|
logger.setLevel(level)
|
|
96
|
-
|
|
101
|
+
|
|
97
102
|
# Update all handlers to use the new level
|
|
98
103
|
for handler in logger.handlers:
|
|
99
104
|
handler.setLevel(level)
|
|
100
105
|
|
|
106
|
+
|
|
101
107
|
__all__ = [
|
|
102
108
|
"setup_logging",
|
|
103
109
|
"set_log_level",
|
|
@@ -1,108 +1,116 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import re
|
|
3
|
-
import os
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Optional, List
|
|
6
|
-
from danielutils import get_current_working_directory, set_current_working_directory, LayeredCommand, warning
|
|
7
|
-
|
|
8
|
-
from ....enforcers import ExitEarlyError
|
|
9
|
-
from ...quality_assurance_runner import QualityAssuranceRunner
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def _removesuffix(string: str, suffix: str) -> str:
|
|
15
|
-
"""Remove a suffix from a string.
|
|
16
|
-
|
|
17
|
-
Replace this with str.removesuffix() from stdlib when minimum Python
|
|
18
|
-
version is 3.9.
|
|
19
|
-
"""
|
|
20
|
-
if suffix and string.endswith(suffix):
|
|
21
|
-
return string[: -len(suffix)]
|
|
22
|
-
return string
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class UnittestRunner(QualityAssuranceRunner):
|
|
26
|
-
"""Quality assurance runner for unittest testing."""
|
|
27
|
-
NUM_TESTS_PATTERN: re.Pattern = re.compile(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
r"FAILED \((?:
|
|
31
|
-
r"FAILED \((?:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
command
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
num_failed = int(
|
|
87
|
-
num_errors = int(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Optional, List
|
|
6
|
+
from danielutils import get_current_working_directory, set_current_working_directory, LayeredCommand, warning
|
|
7
|
+
|
|
8
|
+
from ....enforcers import ExitEarlyError
|
|
9
|
+
from ...quality_assurance_runner import QualityAssuranceRunner
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _removesuffix(string: str, suffix: str) -> str:
|
|
15
|
+
"""Remove a suffix from a string.
|
|
16
|
+
|
|
17
|
+
Replace this with str.removesuffix() from stdlib when minimum Python
|
|
18
|
+
version is 3.9.
|
|
19
|
+
"""
|
|
20
|
+
if suffix and string.endswith(suffix):
|
|
21
|
+
return string[: -len(suffix)]
|
|
22
|
+
return string
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UnittestRunner(QualityAssuranceRunner):
|
|
26
|
+
"""Quality assurance runner for unittest testing."""
|
|
27
|
+
NUM_TESTS_PATTERN: re.Pattern = re.compile(
|
|
28
|
+
r"Ran (\d+) tests? in \d+\.\d+s")
|
|
29
|
+
NUM_FAILED_PATTERN: re.Pattern = re.compile(
|
|
30
|
+
r"FAILED \((?:failures=(\d+))?(?:, )?(?:errors=(\d+))?(?:, )?(?:skipped=(\d+))?\)|"
|
|
31
|
+
r"FAILED \((?:errors=(\d+))?(?:, )?(?:failures=(\d+))?(?:, )?(?:skipped=(\d+))?\)|"
|
|
32
|
+
r"FAILED \((?:skipped=(\d+))?(?:, )?(?:failures=(\d+))?(?:, )?(?:errors=(\d+))?\)")
|
|
33
|
+
|
|
34
|
+
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
def _pre_command(self) -> None:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
def _post_command(self):
|
|
41
|
+
pass
|
|
42
|
+
# set_current_working_directory(self._cwd)
|
|
43
|
+
|
|
44
|
+
def __init__(self, target: Optional[str] = "./tests", bound: str = ">=0.8", no_tests_score: float = 0) -> None:
|
|
45
|
+
QualityAssuranceRunner.__init__(
|
|
46
|
+
self, name="unittest", bound=bound, target=target)
|
|
47
|
+
self.no_tests_score = no_tests_score
|
|
48
|
+
logger.info("Initialized UnittestRunner with target='%s', bound='%s', no_tests_score=%s", target, bound,
|
|
49
|
+
no_tests_score)
|
|
50
|
+
|
|
51
|
+
def _build_command(self, src: str, *args, use_system_interpreter: bool = False) -> str:
|
|
52
|
+
command: str = self.get_executable()
|
|
53
|
+
rel = _removesuffix(os.path.relpath(
|
|
54
|
+
src, self.target), src.lstrip("./\\"))
|
|
55
|
+
command += f" discover -s {rel}"
|
|
56
|
+
normalized_target_path = Path(
|
|
57
|
+
os.path.join(os.getcwd(), self.target)).resolve()
|
|
58
|
+
# This is for concurrency reasons
|
|
59
|
+
return f"cd {normalized_target_path} & {command} & cd {Path(os.getcwd()).resolve()}"
|
|
60
|
+
|
|
61
|
+
def _calculate_score(self, ret: int, lines: List[str], *, verbose: bool = False) -> float:
|
|
62
|
+
logger.debug("Calculating unittest score from test results")
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
num_tests_ran_line = lines[-3]
|
|
66
|
+
num_tests_failed_line = lines[-1]
|
|
67
|
+
num_tests = int(self.NUM_TESTS_PATTERN.match(
|
|
68
|
+
num_tests_ran_line).group(1))
|
|
69
|
+
if num_tests == 0:
|
|
70
|
+
logger.debug(
|
|
71
|
+
"No tests found, returning no_tests_score: %s", self.no_tests_score)
|
|
72
|
+
return self.no_tests_score
|
|
73
|
+
|
|
74
|
+
num_failed = 0
|
|
75
|
+
num_errors = 0
|
|
76
|
+
if num_tests_failed_line != "OK":
|
|
77
|
+
if num_tests_failed_line.startswith("FAILED"):
|
|
78
|
+
m = self.NUM_FAILED_PATTERN.match(num_tests_failed_line)
|
|
79
|
+
if m:
|
|
80
|
+
# Handle different group positions based on the pattern that matched
|
|
81
|
+
groups = m.groups()
|
|
82
|
+
if groups[0] is not None: # failures= first pattern
|
|
83
|
+
num_failed = int(groups[0] or "0")
|
|
84
|
+
num_errors = int(groups[1] or "0")
|
|
85
|
+
elif groups[3] is not None: # errors= first pattern
|
|
86
|
+
num_failed = int(groups[4] or "0")
|
|
87
|
+
num_errors = int(groups[3] or "0")
|
|
88
|
+
elif groups[6] is not None: # skipped= first pattern
|
|
89
|
+
num_failed = int(groups[7] or "0")
|
|
90
|
+
num_errors = int(groups[8] or "0")
|
|
91
|
+
else:
|
|
92
|
+
# Fallback to original logic if no groups match
|
|
93
|
+
num_failed = int(m.group(1) or "0")
|
|
94
|
+
num_errors = int(m.group(2) or "0")
|
|
95
|
+
else:
|
|
96
|
+
# If regex doesn't match, treat as malformed
|
|
97
|
+
raise ValueError(
|
|
98
|
+
f"Failed to parse FAILED line: {num_tests_failed_line}")
|
|
99
|
+
elif num_tests_failed_line.startswith("OK"):
|
|
100
|
+
# 'OK (skipped=3)' could it also be other stuff?
|
|
101
|
+
pass
|
|
102
|
+
|
|
103
|
+
score = 1 - ((num_failed + num_errors) / num_tests)
|
|
104
|
+
logger.debug("Unittest score calculated: %.3f (tests: %d, failed: %d, errors: %d)", score, num_tests,
|
|
105
|
+
num_failed, num_errors)
|
|
106
|
+
return score
|
|
107
|
+
|
|
108
|
+
except Exception as e:
|
|
109
|
+
logger.error("Failed to calculate unittest score: %s", e)
|
|
110
|
+
raise ExitEarlyError(f"Failed running Unittest, got exit code {ret}. "
|
|
111
|
+
f"try running manually using: {self._build_command('TARGET')}") from e
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
__all__ = [
|
|
115
|
+
'UnittestRunner',
|
|
116
|
+
]
|
|
@@ -7,6 +7,7 @@ logger = logging.getLogger(__name__)
|
|
|
7
7
|
|
|
8
8
|
class GithubUploadTarget(UploadTarget):
|
|
9
9
|
"""Upload target implementation for GitHub releases."""
|
|
10
|
+
|
|
10
11
|
def upload(self, version: str, **kwargs) -> None: # type: ignore
|
|
11
12
|
from quickpub.proxy import cm
|
|
12
13
|
from quickpub.enforcers import exit_if
|
|
@@ -14,27 +15,32 @@ class GithubUploadTarget(UploadTarget):
|
|
|
14
15
|
logger.info("Starting GitHub upload for version '%s'", version)
|
|
15
16
|
|
|
16
17
|
if self.verbose:
|
|
17
|
-
logger.
|
|
18
|
+
logger.debug("Staging files for Git commit")
|
|
18
19
|
|
|
19
20
|
ret, stdout, stderr = cm("git add .")
|
|
20
21
|
if ret != 0:
|
|
21
|
-
logger.error("Git add failed with return code %d: %s",
|
|
22
|
+
logger.error("Git add failed with return code %d: %s",
|
|
23
|
+
ret, stderr.decode(encoding='utf8'))
|
|
22
24
|
exit_if(ret != 0, stderr.decode(encoding="utf8"))
|
|
23
25
|
|
|
24
26
|
if self.verbose:
|
|
25
|
-
logger.
|
|
27
|
+
logger.debug(
|
|
28
|
+
"Committing changes with message 'updated to version %s'", version)
|
|
26
29
|
|
|
27
|
-
ret, stdout, stderr = cm(
|
|
30
|
+
ret, stdout, stderr = cm(
|
|
31
|
+
f"git commit -m \"updated to version {version}\"")
|
|
28
32
|
if ret != 0:
|
|
29
|
-
logger.error("Git commit failed with return code %d: %s",
|
|
33
|
+
logger.error("Git commit failed with return code %d: %s",
|
|
34
|
+
ret, stderr.decode(encoding='utf8'))
|
|
30
35
|
exit_if(ret != 0, stderr.decode(encoding="utf8"))
|
|
31
36
|
|
|
32
37
|
if self.verbose:
|
|
33
|
-
logger.
|
|
38
|
+
logger.debug("Pushing changes to GitHub")
|
|
34
39
|
|
|
35
40
|
ret, stdout, stderr = cm("git push")
|
|
36
41
|
if ret != 0:
|
|
37
|
-
logger.error("Git push failed with return code %d: %s",
|
|
42
|
+
logger.error("Git push failed with return code %d: %s",
|
|
43
|
+
ret, stderr.decode(encoding='utf8'))
|
|
38
44
|
exit_if(ret != 0, stderr.decode(encoding="utf8"))
|
|
39
45
|
|
|
40
46
|
logger.info("Successfully uploaded version '%s' to GitHub", version)
|
|
@@ -1,65 +1,75 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
from danielutils import file_exists
|
|
5
|
-
|
|
6
|
-
from ..constraint_enforcers import PypircEnforcer
|
|
7
|
-
from ...upload_target import UploadTarget
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class PypircUploadTarget(UploadTarget):
|
|
13
|
-
"""Upload target implementation using .pypirc configuration."""
|
|
14
|
-
REGEX_PATTERN: re.Pattern = PypircEnforcer.PYPIRC_REGEX
|
|
15
|
-
|
|
16
|
-
def upload(self, name: str, version: str, **kwargs) -> None: # type: ignore
|
|
17
|
-
from quickpub.proxy import cm
|
|
18
|
-
from quickpub.enforcers import exit_if
|
|
19
|
-
|
|
20
|
-
logger.info(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
self.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from danielutils import file_exists
|
|
5
|
+
|
|
6
|
+
from ..constraint_enforcers import PypircEnforcer
|
|
7
|
+
from ...upload_target import UploadTarget
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PypircUploadTarget(UploadTarget):
|
|
13
|
+
"""Upload target implementation using .pypirc configuration."""
|
|
14
|
+
REGEX_PATTERN: re.Pattern = PypircEnforcer.PYPIRC_REGEX
|
|
15
|
+
|
|
16
|
+
def upload(self, name: str, version: str, **kwargs) -> None: # type: ignore
|
|
17
|
+
from quickpub.proxy import cm
|
|
18
|
+
from quickpub.enforcers import exit_if
|
|
19
|
+
|
|
20
|
+
logger.info(
|
|
21
|
+
"Starting PyPI upload for package '%s' version '%s'", name, version)
|
|
22
|
+
|
|
23
|
+
self._validate_file_exists()
|
|
24
|
+
self._validate_file_contents()
|
|
25
|
+
|
|
26
|
+
if self.verbose:
|
|
27
|
+
logger.info("Uploading package to PyPI")
|
|
28
|
+
|
|
29
|
+
ret, stdout, stderr = cm("twine", "upload", "--config-file", ".pypirc",
|
|
30
|
+
f"dist/{name}-{version}.tar.gz")
|
|
31
|
+
|
|
32
|
+
if ret != 0:
|
|
33
|
+
logger.error(
|
|
34
|
+
"PyPI upload failed with return code %d: %s", ret, stderr)
|
|
35
|
+
exit_if(
|
|
36
|
+
ret != 0,
|
|
37
|
+
f"Failed uploading the package to pypi. Try running the following command manually:\n\ttwine upload --config-file .pypirc dist/{name}-{version}.tar.gz"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
logger.info(
|
|
41
|
+
"Successfully uploaded package '%s' version '%s' to PyPI", name, version)
|
|
42
|
+
|
|
43
|
+
def _validate_file_exists(self) -> None:
|
|
44
|
+
logger.debug("Validating .pypirc file exists at '%s'",
|
|
45
|
+
self.pypirc_file_path)
|
|
46
|
+
if not file_exists(self.pypirc_file_path):
|
|
47
|
+
logger.error(".pypirc file not found at '%s'",
|
|
48
|
+
self.pypirc_file_path)
|
|
49
|
+
raise RuntimeError(
|
|
50
|
+
f"{self.__class__.__name__} can't find pypirc file at '{self.pypirc_file_path}'")
|
|
51
|
+
logger.debug(".pypirc file found at '%s'", self.pypirc_file_path)
|
|
52
|
+
|
|
53
|
+
def _validate_file_contents(self) -> None:
|
|
54
|
+
logger.debug("Validating .pypirc file contents at '%s'",
|
|
55
|
+
self.pypirc_file_path)
|
|
56
|
+
with open(self.pypirc_file_path, "r", encoding="utf8") as f:
|
|
57
|
+
text = f.read()
|
|
58
|
+
if not self.REGEX_PATTERN.match(text):
|
|
59
|
+
logger.error(
|
|
60
|
+
".pypirc file contents validation failed for '%s'", self.pypirc_file_path)
|
|
61
|
+
raise RuntimeError(
|
|
62
|
+
f"{self.__class__.__name__} checked the contents of '{self.pypirc_file_path}' and it failed to match the following regex: r\"{self.REGEX_PATTERN.pattern}\"")
|
|
63
|
+
logger.debug(
|
|
64
|
+
".pypirc file contents validation passed for '%s'", self.pypirc_file_path)
|
|
65
|
+
|
|
66
|
+
def __init__(self, pypirc_file_path: str = "./.pypirc", verbose: bool = False) -> None:
|
|
67
|
+
super().__init__(verbose)
|
|
68
|
+
self.pypirc_file_path = pypirc_file_path
|
|
69
|
+
logger.info("Initialized PypircUploadTarget with pypirc_file_path='%s', verbose=%s",
|
|
70
|
+
pypirc_file_path, verbose)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
__all__ = [
|
|
74
|
+
"PypircUploadTarget"
|
|
75
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quickpub
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.61
|
|
4
4
|
Summary: A python package to quickly configure and publish a new package
|
|
5
5
|
Author-email: danielnachumdev <danielnachumdev@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -38,7 +38,7 @@ Requires-Dist: requests
|
|
|
38
38
|
Requires-Dist: fire
|
|
39
39
|
Dynamic: license-file
|
|
40
40
|
|
|
41
|
-
# QuickPub v3.0.
|
|
41
|
+
# QuickPub v3.0.61
|
|
42
42
|
|
|
43
43
|
[](https://www.python.org/downloads/)
|
|
44
44
|
[](LICENSE)
|
|
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
|
{quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/build_schemas/__init__.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
|
{quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/python_providers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickpub-3.0.5 → quickpub-3.0.61}/quickpub/strategies/implementations/upload_targets/__init__.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
|
|
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
|