quickpub 1.0.2__tar.gz → 1.0.3__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-1.0.2 → quickpub-1.0.3}/LICENSE +20 -20
- {quickpub-1.0.2/quickpub.egg-info → quickpub-1.0.3}/PKG-INFO +16 -13
- quickpub-1.0.3/README.md +35 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/pyproject.toml +1 -1
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/__main__.py +19 -22
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/qa.py +10 -12
- quickpub-1.0.3/quickpub/strategies/__init__.py +6 -0
- quickpub-1.0.2/quickpub/strategies/build_strategy.py → quickpub-1.0.3/quickpub/strategies/build_schema.py +2 -2
- quickpub-1.0.3/quickpub/strategies/implementations/__init__.py +9 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/strategies/implementations/conda_python_version_manager_strategy.py +4 -4
- quickpub-1.0.2/quickpub/strategies/implementations/git_upload_strategy.py → quickpub-1.0.3/quickpub/strategies/implementations/github_upload_target.py +3 -3
- quickpub-1.0.2/quickpub/strategies/implementations/mypy_qa_strategy.py → quickpub-1.0.3/quickpub/strategies/implementations/mypy_qa_runner.py +4 -4
- quickpub-1.0.2/quickpub/strategies/implementations/pylint_qa_strategy.py → quickpub-1.0.3/quickpub/strategies/implementations/pylint_qa_runner.py +4 -4
- quickpub-1.0.2/quickpub/strategies/implementations/pypirc_upload_strategy.py → quickpub-1.0.3/quickpub/strategies/implementations/pypirc_upload_target.py +5 -5
- quickpub-1.0.3/quickpub/strategies/implementations/pytest_qa_runner.py +95 -0
- quickpub-1.0.2/quickpub/strategies/implementations/setuptools_build_strategy.py → quickpub-1.0.3/quickpub/strategies/implementations/setuptools_build_schema.py +3 -3
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/strategies/implementations/system_interpreter.py +4 -4
- quickpub-1.0.2/quickpub/strategies/implementations/unittest_qa_strategy.py → quickpub-1.0.3/quickpub/strategies/implementations/unittest_qa_runner.py +5 -6
- quickpub-1.0.2/quickpub/strategies/python_version_manager_strategy.py → quickpub-1.0.3/quickpub/strategies/python_provider.py +2 -2
- quickpub-1.0.3/quickpub/strategies/quality_assurance_runner.py +167 -0
- quickpub-1.0.2/quickpub/strategies/upload_strategy.py → quickpub-1.0.3/quickpub/strategies/upload_target.py +2 -2
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/structures/dependency.py +1 -1
- {quickpub-1.0.2 → quickpub-1.0.3/quickpub.egg-info}/PKG-INFO +16 -13
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub.egg-info/SOURCES.txt +11 -11
- quickpub-1.0.2/README.md +0 -32
- quickpub-1.0.2/quickpub/strategies/__init__.py +0 -6
- quickpub-1.0.2/quickpub/strategies/implementations/__init__.py +0 -9
- quickpub-1.0.2/quickpub/strategies/implementations/pytest_qa_strategy.py +0 -1
- quickpub-1.0.2/quickpub/strategies/quality_assurance_strategy.py +0 -98
- {quickpub-1.0.2 → quickpub-1.0.3}/MANIFEST.in +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/__init__.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/classifiers.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/enforcers.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/files.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/functions.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/proxy.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/py.typed +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/strategies/quickpub_strategy.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/structures/__init__.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/structures/bound.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/structures/version.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub/validators.py +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub.egg-info/dependency_links.txt +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub.egg-info/requires.txt +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/quickpub.egg-info/top_level.txt +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/setup.cfg +0 -0
- {quickpub-1.0.2 → quickpub-1.0.3}/setup.py +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2022 danielnachumdev
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 danielnachumdev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: quickpub
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
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
|
|
@@ -34,35 +34,38 @@ Requires-Python: >=3.8.0
|
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
|
|
37
|
-
# quickpub
|
|
37
|
+
# quickpub V1.0.3
|
|
38
38
|
**Tested python versions**: `3.8.0`, `3.9.0`, `3.10.13`,
|
|
39
39
|
|
|
40
40
|
Example usage of how this package was published
|
|
41
41
|
```python
|
|
42
|
-
from quickpub import publish,
|
|
42
|
+
from quickpub import publish, MypyRunner, PylintRunner, UnittestRunner, CondaPythonProvider, \
|
|
43
|
+
PypircUploadTarget, SetuptoolsBuildSchema, GithubUploadTarget
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
def main() -> None:
|
|
46
47
|
publish(
|
|
47
48
|
name="quickpub",
|
|
48
|
-
version="0.
|
|
49
|
+
version="1.0.3",
|
|
49
50
|
author="danielnachumdev",
|
|
50
51
|
author_email="danielnachumdev@gmail.com",
|
|
51
52
|
description="A python package to quickly configure and publish a new package",
|
|
52
53
|
homepage="https://github.com/danielnachumdev/quickpub",
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
build_schemas=[SetuptoolsBuildSchema()],
|
|
55
|
+
upload_targets=[PypircUploadTarget(), GithubUploadTarget()],
|
|
56
|
+
python_interpreter_provider=CondaPythonProvider(["base", "390", "380"]),
|
|
57
|
+
quality_assurance_runners=[
|
|
58
|
+
MypyRunner(bound="<=15", configuration_path="./mypy.ini"),
|
|
59
|
+
PylintRunner(bound=">=0.8", configuration_path="./.pylintrc"),
|
|
60
|
+
UnittestRunner(bound=">=0.8"),
|
|
61
|
+
],
|
|
62
|
+
dependencies=["danielutils>=0.9.90"],
|
|
63
|
+
min_python="3.8.0",
|
|
62
64
|
)
|
|
63
65
|
|
|
64
66
|
|
|
65
67
|
if __name__ == '__main__':
|
|
66
68
|
main()
|
|
67
69
|
|
|
70
|
+
|
|
68
71
|
```
|
quickpub-1.0.3/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# quickpub V1.0.3
|
|
2
|
+
**Tested python versions**: `3.8.0`, `3.9.0`, `3.10.13`,
|
|
3
|
+
|
|
4
|
+
Example usage of how this package was published
|
|
5
|
+
```python
|
|
6
|
+
from quickpub import publish, MypyRunner, PylintRunner, UnittestRunner, CondaPythonProvider, \
|
|
7
|
+
PypircUploadTarget, SetuptoolsBuildSchema, GithubUploadTarget
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
publish(
|
|
12
|
+
name="quickpub",
|
|
13
|
+
version="1.0.3",
|
|
14
|
+
author="danielnachumdev",
|
|
15
|
+
author_email="danielnachumdev@gmail.com",
|
|
16
|
+
description="A python package to quickly configure and publish a new package",
|
|
17
|
+
homepage="https://github.com/danielnachumdev/quickpub",
|
|
18
|
+
build_schemas=[SetuptoolsBuildSchema()],
|
|
19
|
+
upload_targets=[PypircUploadTarget(), GithubUploadTarget()],
|
|
20
|
+
python_interpreter_provider=CondaPythonProvider(["base", "390", "380"]),
|
|
21
|
+
quality_assurance_runners=[
|
|
22
|
+
MypyRunner(bound="<=15", configuration_path="./mypy.ini"),
|
|
23
|
+
PylintRunner(bound=">=0.8", configuration_path="./.pylintrc"),
|
|
24
|
+
UnittestRunner(bound=">=0.8"),
|
|
25
|
+
],
|
|
26
|
+
dependencies=["danielutils>=0.9.90"],
|
|
27
|
+
min_python="3.8.0",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == '__main__':
|
|
32
|
+
main()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
```
|
|
@@ -2,8 +2,7 @@ import argparse
|
|
|
2
2
|
from typing import Optional, Union, List, Any
|
|
3
3
|
from danielutils import warning, file_exists, error
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from strategies import BuildStrategy, UploadStrategy, QualityAssuranceStrategy, PythonVersionManagerStrategy
|
|
5
|
+
from .strategies import BuildSchema, UploadTarget, QualityAssuranceRunner, PythonProvider, DefaultInterpreterProvider
|
|
7
6
|
from .validators import validate_version, validate_python_version, validate_keywords, validate_dependencies, \
|
|
8
7
|
validate_source
|
|
9
8
|
from .structures import Version, Dependency
|
|
@@ -21,22 +20,20 @@ def publish(
|
|
|
21
20
|
description: str,
|
|
22
21
|
homepage: str,
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
build_schemas: List[BuildSchema],
|
|
24
|
+
upload_targets: List[UploadTarget],
|
|
25
|
+
quality_assurance_runners: Optional[List[QualityAssuranceRunner]] = None,
|
|
26
|
+
python_interpreter_provider: PythonProvider = DefaultInterpreterProvider(),
|
|
28
27
|
|
|
29
|
-
explicit_src_folder_path: Optional[str] = None,
|
|
30
|
-
version: Optional[Union[Version, str]] = None,
|
|
31
28
|
readme_file_path: str = "./README.md",
|
|
32
29
|
license_file_path: str = "./LICENSE",
|
|
33
|
-
|
|
30
|
+
version: Optional[Union[Version, str]] = None,
|
|
34
31
|
min_python: Optional[Union[Version, str]] = None,
|
|
35
|
-
|
|
36
|
-
keywords: Optional[List[str]] = None,
|
|
37
32
|
dependencies: Optional[List[Union[str, Dependency]]] = None,
|
|
38
|
-
|
|
33
|
+
keywords: Optional[List[str]] = None,
|
|
34
|
+
explicit_src_folder_path: Optional[str] = None,
|
|
39
35
|
|
|
36
|
+
demo: bool = False,
|
|
40
37
|
config: Optional[Any] = None,
|
|
41
38
|
) -> None:
|
|
42
39
|
"""The main function for publishing a package. It performs all necessary steps to prepare and publish the package.
|
|
@@ -46,10 +43,10 @@ def publish(
|
|
|
46
43
|
:param author_email: The email of the author.
|
|
47
44
|
:param description: A short description of the package.
|
|
48
45
|
:param homepage: The homepage URL for the package (e.g., GitHub repository).
|
|
49
|
-
:param
|
|
50
|
-
:param
|
|
51
|
-
:param
|
|
52
|
-
:param
|
|
46
|
+
:param quality_assurance_runners: Strategies for quality assurance.
|
|
47
|
+
:param build_schemas: Strategies for building the package.
|
|
48
|
+
:param upload_targets: Strategies for uploading the package.
|
|
49
|
+
:param python_interpreter_provider: Strategy for managing Python versions. Defaults to SystemInterpreter().
|
|
53
50
|
:param explicit_src_folder_path: The path to the source code of the package. Defaults to the current working directory/<name>.
|
|
54
51
|
:param version: The version for the new distribution. Defaults to "0.0.1".
|
|
55
52
|
:param readme_file_path: The path to the README file. Defaults to "./README.md".
|
|
@@ -79,12 +76,12 @@ def publish(
|
|
|
79
76
|
validated_dependencies: List[Dependency] = validate_dependencies(dependencies)
|
|
80
77
|
enforce_remote_correct_version(name, version)
|
|
81
78
|
|
|
82
|
-
if
|
|
83
|
-
|
|
79
|
+
if quality_assurance_runners is None:
|
|
80
|
+
quality_assurance_runners = []
|
|
84
81
|
try:
|
|
85
82
|
res = qa(
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
python_interpreter_provider,
|
|
84
|
+
quality_assurance_runners,
|
|
88
85
|
name,
|
|
89
86
|
explicit_src_folder_path,
|
|
90
87
|
validated_dependencies
|
|
@@ -122,9 +119,9 @@ def publish(
|
|
|
122
119
|
)
|
|
123
120
|
create_manifest(name=name)
|
|
124
121
|
if not demo:
|
|
125
|
-
for build_strategy in
|
|
122
|
+
for build_strategy in build_schemas:
|
|
126
123
|
build_strategy.execute_strategy()
|
|
127
|
-
for upload_strategy in
|
|
124
|
+
for upload_strategy in upload_targets:
|
|
128
125
|
upload_strategy.execute_strategy(name=name, version=version)
|
|
129
126
|
|
|
130
127
|
|
|
@@ -4,8 +4,7 @@ from functools import wraps
|
|
|
4
4
|
from typing import Optional, ContextManager, List, Callable, Tuple, Dict, Union
|
|
5
5
|
from danielutils import AttrContext, LayeredCommand, AsciiProgressBar, ColoredText, ProgressBarPool, TemporaryFile
|
|
6
6
|
|
|
7
|
-
from
|
|
8
|
-
from .strategies import PythonVersionManagerStrategy # pylint: disable=relative-beyond-top-level
|
|
7
|
+
from .strategies import PythonProvider, QualityAssuranceRunner # pylint: disable=relative-beyond-top-level
|
|
9
8
|
from .structures import Dependency, Version, Bound # pylint: disable=relative-beyond-top-level
|
|
10
9
|
from .enforcers import exit_if # pylint: disable=relative-beyond-top-level
|
|
11
10
|
|
|
@@ -54,7 +53,7 @@ def global_import_sanity_check(package_name: str, executor: LayeredCommand, is_s
|
|
|
54
53
|
VERSION_REGEX: re.Pattern = re.compile(r"^\d+\.\d+\.\d+$")
|
|
55
54
|
|
|
56
55
|
|
|
57
|
-
def validate_dependencies(python_manager:
|
|
56
|
+
def validate_dependencies(python_manager: PythonProvider, required_dependencies: List[Dependency],
|
|
58
57
|
executor: LayeredCommand,
|
|
59
58
|
env_name: str, err_print_func: Callable) -> None:
|
|
60
59
|
"""
|
|
@@ -86,15 +85,15 @@ def validate_dependencies(python_manager: PythonVersionManagerStrategy, required
|
|
|
86
85
|
(req, "Verion format of dependecy is not currently supported by quickpub"))
|
|
87
86
|
elif isinstance(v, Dependency):
|
|
88
87
|
if not req.is_satisfied_by(v.ver):
|
|
89
|
-
not_installed_properly.append((req, "
|
|
88
|
+
not_installed_properly.append((req, "Invalid version installed"))
|
|
90
89
|
|
|
91
90
|
exit_if(bool(not_installed_properly),
|
|
92
91
|
f"On env '{env_name}' the following dependencies have problems: {(not_installed_properly)}",
|
|
93
92
|
err_func=err_print_func)
|
|
94
93
|
|
|
95
94
|
|
|
96
|
-
def create_progress_bar_pool(python_version_manager:
|
|
97
|
-
quality_assurance_strategies: List[
|
|
95
|
+
def create_progress_bar_pool(python_version_manager: PythonProvider,
|
|
96
|
+
quality_assurance_strategies: List[QualityAssuranceRunner]) -> ProgressBarPool:
|
|
98
97
|
return ProgressBarPool(
|
|
99
98
|
AsciiProgressBar,
|
|
100
99
|
2,
|
|
@@ -123,17 +122,17 @@ def create_pool_print_error(pool: ProgressBarPool):
|
|
|
123
122
|
|
|
124
123
|
|
|
125
124
|
def qa(
|
|
126
|
-
python_version_manager:
|
|
127
|
-
quality_assurance_strategies: List[
|
|
125
|
+
python_version_manager: PythonProvider,
|
|
126
|
+
quality_assurance_strategies: List[QualityAssuranceRunner],
|
|
128
127
|
package_name: str,
|
|
129
128
|
src_folder_path: Optional[str],
|
|
130
129
|
dependencies: list
|
|
131
130
|
) -> bool:
|
|
132
|
-
from .strategies import
|
|
131
|
+
from .strategies import DefaultInterpreterProvider
|
|
133
132
|
result = True
|
|
134
133
|
if python_version_manager is None:
|
|
135
|
-
python_version_manager =
|
|
136
|
-
is_system_interpreter = isinstance(python_version_manager,
|
|
134
|
+
python_version_manager = DefaultInterpreterProvider()
|
|
135
|
+
is_system_interpreter = isinstance(python_version_manager, DefaultInterpreterProvider)
|
|
137
136
|
pool = create_progress_bar_pool(python_version_manager, quality_assurance_strategies)
|
|
138
137
|
pool_err = create_pool_print_error(pool)
|
|
139
138
|
with MultiContext(
|
|
@@ -165,7 +164,6 @@ def qa(
|
|
|
165
164
|
src_folder_path,
|
|
166
165
|
executor,
|
|
167
166
|
use_system_interpreter=is_system_interpreter,
|
|
168
|
-
raise_on_fail=python_version_manager.exit_on_fail,
|
|
169
167
|
print_func=pool_err,
|
|
170
168
|
env_name=env_name
|
|
171
169
|
)
|
|
@@ -3,7 +3,7 @@ from abc import abstractmethod
|
|
|
3
3
|
from .quickpub_strategy import QuickpubStrategy
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class BuildSchema(QuickpubStrategy):
|
|
7
7
|
def __init__(self, verbose: bool = True) -> None:
|
|
8
8
|
self.verbose = verbose
|
|
9
9
|
|
|
@@ -12,5 +12,5 @@ class BuildStrategy(QuickpubStrategy):
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
|
-
"
|
|
15
|
+
"BuildSchema"
|
|
16
16
|
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from .pypirc_upload_target import *
|
|
2
|
+
from .github_upload_target import *
|
|
3
|
+
from .setuptools_build_schema import *
|
|
4
|
+
from .mypy_qa_runner import *
|
|
5
|
+
from .pylint_qa_runner import *
|
|
6
|
+
from .pytest_qa_runner import *
|
|
7
|
+
from .unittest_qa_runner import *
|
|
8
|
+
from .conda_python_version_manager_strategy import *
|
|
9
|
+
from .system_interpreter import *
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
from typing import Tuple, Optional, Set, Iterator, List
|
|
2
2
|
from danielutils import LayeredCommand, warning
|
|
3
3
|
|
|
4
|
-
from ..
|
|
4
|
+
from ..python_provider import PythonProvider
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class
|
|
7
|
+
class CondaPythonProvider(PythonProvider):
|
|
8
8
|
def get_python_executable_name(self) -> str:
|
|
9
9
|
return "python"
|
|
10
10
|
|
|
11
11
|
def __init__(self, env_names: List[str]) -> None:
|
|
12
|
-
|
|
12
|
+
PythonProvider.__init__(self, requested_envs=env_names, explicit_versions=[], exit_on_fail=True)
|
|
13
13
|
self._cached_available_envs: Optional[Set[str]] = None
|
|
14
14
|
|
|
15
15
|
def get_available_envs(self) -> Set[str]:
|
|
@@ -33,5 +33,5 @@ class CondaPythonVersionManagerStrategy(PythonVersionManagerStrategy):
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
__all__ = [
|
|
36
|
-
'
|
|
36
|
+
'CondaPythonProvider',
|
|
37
37
|
]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from danielutils import info
|
|
2
2
|
|
|
3
|
-
from ..
|
|
3
|
+
from ..upload_target import UploadTarget
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class GithubUploadTarget(UploadTarget):
|
|
6
6
|
def execute_strategy(self, version: str, **kwargs) -> None:
|
|
7
7
|
from quickpub.proxy import cm
|
|
8
8
|
from quickpub.enforcers import exit_if
|
|
@@ -22,5 +22,5 @@ class GitUploadStrategy(UploadStrategy):
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
__all__ = [
|
|
25
|
-
"
|
|
25
|
+
"GithubUploadTarget",
|
|
26
26
|
]
|
|
@@ -3,10 +3,10 @@ from typing import Optional, List
|
|
|
3
3
|
|
|
4
4
|
from danielutils import LayeredCommand
|
|
5
5
|
|
|
6
|
-
from ..
|
|
6
|
+
from ..quality_assurance_runner import QualityAssuranceRunner
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class MypyRunner(
|
|
9
|
+
class MypyRunner(QualityAssuranceRunner):
|
|
10
10
|
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
11
11
|
with base:
|
|
12
12
|
base("pip install pylint")
|
|
@@ -23,8 +23,8 @@ class MypyRunner(QualityAssuranceStrategy):
|
|
|
23
23
|
|
|
24
24
|
def __init__(self, bound: str = "<15", configuration_path: Optional[str] = None,
|
|
25
25
|
executable_path: Optional[str] = None) -> None:
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
QualityAssuranceRunner.__init__(self, name="mypy", bound=bound, configuration_path=configuration_path,
|
|
27
|
+
executable_path=executable_path)
|
|
28
28
|
|
|
29
29
|
def _calculate_score(self, ret, lines: List[str], verbose: bool = False) -> float:
|
|
30
30
|
from ...enforcers import exit_if
|
|
@@ -3,10 +3,10 @@ from typing import Optional, List
|
|
|
3
3
|
|
|
4
4
|
from danielutils import LayeredCommand
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from ..quality_assurance_runner import QualityAssuranceRunner
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class PylintRunner(
|
|
9
|
+
class PylintRunner(QualityAssuranceRunner):
|
|
10
10
|
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
11
11
|
with base:
|
|
12
12
|
base("pip install pylint")
|
|
@@ -15,8 +15,8 @@ class PylintRunner(QualityAssuranceStrategy):
|
|
|
15
15
|
|
|
16
16
|
def __init__(self, bound: str = ">=0.8", configuration_path: Optional[str] = None,
|
|
17
17
|
executable_path: Optional[str] = None) -> None:
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
QualityAssuranceRunner.__init__(self, name="pylint", bound=bound, configuration_path=configuration_path,
|
|
19
|
+
executable_path=executable_path)
|
|
20
20
|
|
|
21
21
|
def _build_command(self, target: str, use_system_interpreter: bool = False) -> str:
|
|
22
22
|
command: str = self.get_executable()
|
|
@@ -2,12 +2,12 @@ import re
|
|
|
2
2
|
|
|
3
3
|
from danielutils import file_exists, info
|
|
4
4
|
|
|
5
|
-
from ..
|
|
5
|
+
from ..upload_target import UploadTarget
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class PypircUploadTarget(UploadTarget):
|
|
9
9
|
REGEX_PATTERN: re.Pattern = re.compile(
|
|
10
|
-
r"\[distutils\]\nindex-servers =\n pypi\n testpypi\n\n\[pypi\]\
|
|
10
|
+
r"\[distutils\]\nindex-servers =\n pypi\n testpypi\n\n\[pypi\]\n username = __token__\n password = .+\n\n\[testpypi\]\n username = __token__\n password = .+\n?")
|
|
11
11
|
|
|
12
12
|
def execute_strategy(self, *, name: str, version: str, **kwargs) -> None:
|
|
13
13
|
from quickpub.proxy import cm
|
|
@@ -32,7 +32,7 @@ class PypircUploadStrategy(UploadStrategy):
|
|
|
32
32
|
text = f.read()
|
|
33
33
|
if not self.REGEX_PATTERN.match(text):
|
|
34
34
|
raise RuntimeError(
|
|
35
|
-
f"{self.__class__.__name__} checked the contents of '{self.pypirc_file_path}' and it failed to match the following regex: {self.REGEX_PATTERN.pattern}")
|
|
35
|
+
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}\"")
|
|
36
36
|
|
|
37
37
|
def __init__(self, pypirc_file_path: str = "./.pypirc", verbose: bool = False) -> None:
|
|
38
38
|
super().__init__(verbose)
|
|
@@ -40,5 +40,5 @@ class PypircUploadStrategy(UploadStrategy):
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
__all__ = [
|
|
43
|
-
"
|
|
43
|
+
"PypircUploadTarget"
|
|
44
44
|
]
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import List, Union, Optional
|
|
3
|
+
|
|
4
|
+
from danielutils import LayeredCommand
|
|
5
|
+
|
|
6
|
+
from quickpub import Bound
|
|
7
|
+
from ..quality_assurance_runner import QualityAssuranceRunner
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PytestRunner(QualityAssuranceRunner):
|
|
11
|
+
"""
|
|
12
|
+
PytestRunner is a concrete implementation of QualityAssuranceRunner specifically for running
|
|
13
|
+
pytest-based tests. It includes methods to build the pytest command, install pytest dependencies,
|
|
14
|
+
and calculate the test score based on pytest results.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
PYTEST_REGEX (re.Pattern): A regex pattern to parse pytest results for passed and failed tests.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
PYTEST_REGEX: re.Pattern = re.compile(
|
|
21
|
+
r"=+ (?:(?P<failed>\d+) failed,? )?(?:(?P<passed>\d+) passed )?in [\d\.]+s =+")
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self, *,
|
|
25
|
+
bound: Union[str, Bound] = ">=0.8",
|
|
26
|
+
target: str = "./tests",
|
|
27
|
+
no_output_score: float = 0.0,
|
|
28
|
+
no_tests_score: float = 1.0
|
|
29
|
+
):
|
|
30
|
+
"""
|
|
31
|
+
Initializes the PytestRunner with a bound and target directory for tests.
|
|
32
|
+
|
|
33
|
+
:param bound: The bound representing acceptable limits, either as a string or a Bound object.
|
|
34
|
+
Default is ">=0.8".
|
|
35
|
+
:param target: The target directory containing the tests. Default is "./tests".
|
|
36
|
+
"""
|
|
37
|
+
super().__init__(
|
|
38
|
+
name="pytest",
|
|
39
|
+
bound=bound,
|
|
40
|
+
target=target
|
|
41
|
+
)
|
|
42
|
+
if not (0.0 <= no_tests_score <= 1.0):
|
|
43
|
+
raise RuntimeError("no_tests_score should be between 0.0 and 1.0 (including both).")
|
|
44
|
+
self.no_tests_score = no_tests_score
|
|
45
|
+
|
|
46
|
+
if not (0.0 <= no_output_score <= 1.0):
|
|
47
|
+
raise RuntimeError("no_output_score should be between 0.0 and 1.0 (including both).")
|
|
48
|
+
self.no_output_score = no_output_score
|
|
49
|
+
|
|
50
|
+
def _build_command(self, target: str, use_system_interpreter: bool = False) -> str:
|
|
51
|
+
"""
|
|
52
|
+
Builds the command to run pytest on the specified target.
|
|
53
|
+
|
|
54
|
+
:param target: The target directory containing the tests.
|
|
55
|
+
:param use_system_interpreter: Whether to use the system interpreter. Default is False.
|
|
56
|
+
:return: The command to run pytest as a string.
|
|
57
|
+
"""
|
|
58
|
+
if self.has_config:
|
|
59
|
+
return "pytest"
|
|
60
|
+
return f"pytest {self.target}"
|
|
61
|
+
|
|
62
|
+
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Installs pytest and its dependencies.
|
|
65
|
+
|
|
66
|
+
:param base: The base LayeredCommand object for executing commands.
|
|
67
|
+
"""
|
|
68
|
+
with base:
|
|
69
|
+
base("pip install pytest")
|
|
70
|
+
|
|
71
|
+
def _calculate_score(self, ret: int, command_output: List[str], *, verbose: bool = False) -> float:
|
|
72
|
+
"""
|
|
73
|
+
Calculates the test score based on the pytest command output.
|
|
74
|
+
|
|
75
|
+
:param ret: The return code of the pytest command.
|
|
76
|
+
:param command_output: The output of the pytest command as a list of strings.
|
|
77
|
+
:param verbose: Whether to output verbose logs. Default is False.
|
|
78
|
+
:return: The calculated test score as a float.
|
|
79
|
+
"""
|
|
80
|
+
if len(command_output) == 0:
|
|
81
|
+
return self.no_output_score
|
|
82
|
+
rating_line = command_output[-1]
|
|
83
|
+
if "no tests ran" in rating_line:
|
|
84
|
+
return self.no_tests_score
|
|
85
|
+
if not (m := self.PYTEST_REGEX.match(rating_line)):
|
|
86
|
+
raise SystemExit(1)
|
|
87
|
+
|
|
88
|
+
dct = m.groupdict()
|
|
89
|
+
failed = int(dct["failed"] or "0")
|
|
90
|
+
passed = int(dct["passed"] or "0")
|
|
91
|
+
assert failed >= 0
|
|
92
|
+
assert passed >= 0
|
|
93
|
+
if failed + passed == 0:
|
|
94
|
+
return self.no_tests_score
|
|
95
|
+
return passed / (passed + failed)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from danielutils import info
|
|
2
2
|
|
|
3
|
-
from ..
|
|
3
|
+
from ..build_schema import BuildSchema
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class SetuptoolsBuildSchema(BuildSchema):
|
|
7
7
|
def execute_strategy(self, *args, **kwargs) -> None:
|
|
8
8
|
from quickpub.proxy import cm
|
|
9
9
|
from quickpub.enforcers import exit_if
|
|
@@ -17,5 +17,5 @@ class SetuptoolsBuildStrategy(BuildStrategy):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
__all__ = [
|
|
20
|
-
"
|
|
20
|
+
"SetuptoolsBuildSchema",
|
|
21
21
|
]
|
|
@@ -3,15 +3,15 @@ from typing import Set, Tuple, Iterator
|
|
|
3
3
|
|
|
4
4
|
from danielutils import LayeredCommand
|
|
5
5
|
|
|
6
|
-
from ..
|
|
6
|
+
from ..python_provider import PythonProvider
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class DefaultInterpreterProvider(PythonProvider):
|
|
10
10
|
def get_python_executable_name(self) -> str:
|
|
11
11
|
return sys.executable
|
|
12
12
|
|
|
13
13
|
def __init__(self) -> None:
|
|
14
|
-
|
|
14
|
+
PythonProvider.__init__(self, requested_envs=["system"], explicit_versions=[], exit_on_fail=True)
|
|
15
15
|
|
|
16
16
|
def __iter__(self) -> Iterator[Tuple[str, LayeredCommand]]:
|
|
17
17
|
return iter([("system", LayeredCommand(""))])
|
|
@@ -21,5 +21,5 @@ class SystemInterpreter(PythonVersionManagerStrategy):
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
__all__ = [
|
|
24
|
-
"
|
|
24
|
+
"DefaultInterpreterProvider",
|
|
25
25
|
]
|
|
@@ -3,10 +3,10 @@ import os
|
|
|
3
3
|
from typing import Optional, List
|
|
4
4
|
from danielutils import get_current_working_directory, set_current_working_directory, LayeredCommand, warning
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from ..quality_assurance_runner import QualityAssuranceRunner
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class UnittestRunner(
|
|
9
|
+
class UnittestRunner(QualityAssuranceRunner):
|
|
10
10
|
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
11
11
|
return None
|
|
12
12
|
|
|
@@ -23,7 +23,7 @@ class UnittestRunner(QualityAssuranceStrategy):
|
|
|
23
23
|
RATING_PATTERN: re.Pattern = re.compile(r".*?([\d\.\/]+)")
|
|
24
24
|
|
|
25
25
|
def __init__(self, target: Optional[str] = "./tests", bound: str = ">=0.8") -> None:
|
|
26
|
-
|
|
26
|
+
QualityAssuranceRunner.__init__(self, name="unittest", bound=bound, target=target)
|
|
27
27
|
self._cwd = ""
|
|
28
28
|
|
|
29
29
|
def _build_command(self, src: str, *args, use_system_interpreter: bool = False) -> str:
|
|
@@ -33,7 +33,6 @@ class UnittestRunner(QualityAssuranceStrategy):
|
|
|
33
33
|
return command # f"cd {self.target}; {command}" # f"; cd {self.target}"
|
|
34
34
|
|
|
35
35
|
def _calculate_score(self, ret: int, lines: List[str], *, verbose: bool = False) -> float:
|
|
36
|
-
from ...enforcers import exit_if
|
|
37
36
|
num_tests_line = lines[-3]
|
|
38
37
|
num_failed_line = lines[-1] if lines[-1] != "OK" else "0"
|
|
39
38
|
try:
|
|
@@ -48,8 +47,8 @@ class UnittestRunner(QualityAssuranceStrategy):
|
|
|
48
47
|
|
|
49
48
|
return 1.0 - (float(num_failed) / float(num_tests))
|
|
50
49
|
except:
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
raise SystemExit(f"Failed running Unittest, got exit code {ret}. "
|
|
51
|
+
f"try running manually using: {self._build_command('TARGET')}")
|
|
53
52
|
|
|
54
53
|
|
|
55
54
|
__all__ = [
|
|
@@ -4,7 +4,7 @@ from typing import Tuple, Set, Iterator, List
|
|
|
4
4
|
from danielutils import LayeredCommand
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class
|
|
7
|
+
class PythonProvider(QuickpubStrategy):
|
|
8
8
|
def __init__(self, auto_install_dependencies: bool = True, *, requested_envs: List[str],
|
|
9
9
|
explicit_versions: List[str],
|
|
10
10
|
exit_on_fail: bool = False) -> None:
|
|
@@ -27,5 +27,5 @@ class PythonVersionManagerStrategy(QuickpubStrategy):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
__all__ = [
|
|
30
|
-
'
|
|
30
|
+
'PythonProvider'
|
|
31
31
|
]
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from typing import Union, List, Optional, cast
|
|
4
|
+
from danielutils import LayeredCommand, get_os, OSType, file_exists
|
|
5
|
+
|
|
6
|
+
from quickpub import Bound
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Configurable:
|
|
10
|
+
@property
|
|
11
|
+
def has_config(self) -> bool:
|
|
12
|
+
return self.config_path is not None
|
|
13
|
+
|
|
14
|
+
def __init__(self, config_path: Optional[str] = None):
|
|
15
|
+
self.config_path = config_path
|
|
16
|
+
if self.has_config:
|
|
17
|
+
if not file_exists(self.config_path):
|
|
18
|
+
raise FileNotFoundError(f"Can't find config file {self.config_path}")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class HasOptionalExecutable:
|
|
22
|
+
PYTHON: str = "python" if get_os() == OSType.WINDOWS else "python3"
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def use_executable(self) -> bool:
|
|
26
|
+
return self.executable_path is not None
|
|
27
|
+
|
|
28
|
+
def __init__(self, name, executable_path: Optional[str] = None) -> None:
|
|
29
|
+
self.name = name
|
|
30
|
+
self.executable_path = executable_path
|
|
31
|
+
if self.use_executable:
|
|
32
|
+
if not file_exists(self.executable_path):
|
|
33
|
+
raise FileNotFoundError(f"Executable not found {self.executable_path}")
|
|
34
|
+
|
|
35
|
+
def get_executable(self, use_system_interpreter: bool = False) -> str:
|
|
36
|
+
if self.use_executable:
|
|
37
|
+
return cast(str, self.executable_path)
|
|
38
|
+
|
|
39
|
+
p = self.PYTHON
|
|
40
|
+
if use_system_interpreter:
|
|
41
|
+
p = sys.executable
|
|
42
|
+
return f"{p} -m {self.name}"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
from typing import Optional, Union, List
|
|
46
|
+
from abc import abstractmethod
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class QualityAssuranceRunner(Configurable, HasOptionalExecutable):
|
|
50
|
+
"""
|
|
51
|
+
QualityAssuranceRunner is an abstract base class that handles the execution of quality assurance
|
|
52
|
+
processes. It extends Configurable and HasOptionalExecutable to incorporate configuration and
|
|
53
|
+
optional executable handling functionalities.
|
|
54
|
+
|
|
55
|
+
:param name: The name of the QA runner.
|
|
56
|
+
:param bound: The bound representing acceptable limits, either as a string or a Bound object.
|
|
57
|
+
:param target: The target to be tested, optional.
|
|
58
|
+
:param configuration_path: The path to the configuration file, optional.
|
|
59
|
+
:param executable_path: The path to the executable, optional.
|
|
60
|
+
|
|
61
|
+
Attributes:
|
|
62
|
+
bound (Bound): The bound object that represents the acceptable limits for the QA process.
|
|
63
|
+
target (Optional[str]): The target to be tested.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self, *,
|
|
68
|
+
name: str,
|
|
69
|
+
bound: Union[str, Bound],
|
|
70
|
+
target: Optional[str] = None,
|
|
71
|
+
configuration_path: Optional[str] = None,
|
|
72
|
+
executable_path: Optional[str] = None
|
|
73
|
+
) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Initializes the QualityAssuranceRunner with the given parameters.
|
|
76
|
+
|
|
77
|
+
:param name: The name of the QA runner.
|
|
78
|
+
:param bound: The bound representing acceptable limits, either as a string or a Bound object.
|
|
79
|
+
:param target: The target to be tested, optional.
|
|
80
|
+
:param configuration_path: The path to the configuration file, optional.
|
|
81
|
+
:param executable_path: The path to the executable, optional.
|
|
82
|
+
"""
|
|
83
|
+
Configurable.__init__(self, configuration_path)
|
|
84
|
+
HasOptionalExecutable.__init__(self, name, executable_path)
|
|
85
|
+
self.bound: Bound = bound if isinstance(bound, Bound) else Bound.from_string(bound)
|
|
86
|
+
self.target = target
|
|
87
|
+
|
|
88
|
+
@abstractmethod
|
|
89
|
+
def _build_command(self, target: str, use_system_interpreter: bool = False) -> str:
|
|
90
|
+
"""
|
|
91
|
+
Builds the command to be executed for the QA process.
|
|
92
|
+
|
|
93
|
+
:param target: The target to be tested.
|
|
94
|
+
:param use_system_interpreter: Whether to use the system interpreter, default is False.
|
|
95
|
+
:return: The command to be executed as a string.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Installs the necessary dependencies for the QA process.
|
|
102
|
+
|
|
103
|
+
:param base: The base LayeredCommand object for executing commands.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
def _pre_command(self) -> None:
|
|
107
|
+
"""
|
|
108
|
+
Hook method to be executed before running the main command.
|
|
109
|
+
Can be overridden by subclasses.
|
|
110
|
+
"""
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
def _post_command(self) -> None:
|
|
114
|
+
"""
|
|
115
|
+
Hook method to be executed after running the main command.
|
|
116
|
+
Can be overridden by subclasses.
|
|
117
|
+
"""
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
def run(self, target: str, executor: LayeredCommand, *, verbose: bool = True, # type: ignore
|
|
121
|
+
use_system_interpreter: bool = False, print_func, env_name: str) -> None:
|
|
122
|
+
"""
|
|
123
|
+
Runs the QA process on the specified target.
|
|
124
|
+
|
|
125
|
+
:param target: The target to be tested.
|
|
126
|
+
:param executor: The executor object to run the command.
|
|
127
|
+
:param verbose: Whether to output verbose logs, default is True.
|
|
128
|
+
:param use_system_interpreter: Whether to use the system interpreter, default is False.
|
|
129
|
+
:param print_func: The function to use for printing output.
|
|
130
|
+
:param env_name: The name of the environment in which the QA runner is executed.
|
|
131
|
+
"""
|
|
132
|
+
from quickpub.proxy import os_system # pylint: disable=import-error
|
|
133
|
+
from quickpub.enforcers import exit_if # pylint: disable=import-error
|
|
134
|
+
# =====================================
|
|
135
|
+
# IMPORTANT: need to explicitly override it here
|
|
136
|
+
executor._executor = os_system # pylint: disable=protected-access
|
|
137
|
+
# =====================================
|
|
138
|
+
command = self._build_command(target, use_system_interpreter)
|
|
139
|
+
self._pre_command()
|
|
140
|
+
try:
|
|
141
|
+
ret, out, err = executor(command, command_raise_on_fail=False)
|
|
142
|
+
score = self._calculate_score(ret, "".join(out + err).splitlines(), verbose=verbose)
|
|
143
|
+
exit_if(not self.bound.compare_against(score),
|
|
144
|
+
f"On env '{env_name}' runner '{self.__class__.__name__}' failed to pass its defined bound. Got a score of {score} but expected {self.bound}",
|
|
145
|
+
verbose=verbose, err_func=print_func)
|
|
146
|
+
except Exception as e:
|
|
147
|
+
raise RuntimeError(
|
|
148
|
+
f"On env {env_name}, failed to run {self.__class__.__name__}. Try running manually:\n{executor._build_command(command)}") from e
|
|
149
|
+
finally:
|
|
150
|
+
self._post_command()
|
|
151
|
+
|
|
152
|
+
@abstractmethod
|
|
153
|
+
def _calculate_score(self, ret: int, command_output: List[str], *, verbose: bool = False) -> float:
|
|
154
|
+
"""
|
|
155
|
+
Calculates the score based on the command's return code and output.
|
|
156
|
+
|
|
157
|
+
:param ret: The return code of the executed command.
|
|
158
|
+
:param command_output: The output of the command as a list of strings.
|
|
159
|
+
:param verbose: Whether to output verbose logs, default is False.
|
|
160
|
+
:return: The calculated score as a float.
|
|
161
|
+
"""
|
|
162
|
+
...
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
__all__ = [
|
|
166
|
+
"QualityAssuranceRunner"
|
|
167
|
+
]
|
|
@@ -3,7 +3,7 @@ from abc import abstractmethod
|
|
|
3
3
|
from .quickpub_strategy import QuickpubStrategy
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class UploadTarget(QuickpubStrategy):
|
|
7
7
|
def __init__(self, verbose: bool = True) -> None:
|
|
8
8
|
self.verbose = verbose
|
|
9
9
|
|
|
@@ -12,5 +12,5 @@ class UploadStrategy(QuickpubStrategy):
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
|
-
'
|
|
15
|
+
'UploadTarget',
|
|
16
16
|
]
|
|
@@ -22,7 +22,7 @@ class Dependency:
|
|
|
22
22
|
splits = s.split(op)
|
|
23
23
|
if len(splits) == 2:
|
|
24
24
|
return Dependency(splits[0], op, Version.from_str(splits[-1])) # type:ignore
|
|
25
|
-
|
|
25
|
+
return Dependency(s, ">=", Version(0, 0, 0))
|
|
26
26
|
|
|
27
27
|
def __str__(self) -> str:
|
|
28
28
|
if self.ver == Version(0, 0, 0):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: quickpub
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
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
|
|
@@ -34,35 +34,38 @@ Requires-Python: >=3.8.0
|
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
|
|
37
|
-
# quickpub
|
|
37
|
+
# quickpub V1.0.3
|
|
38
38
|
**Tested python versions**: `3.8.0`, `3.9.0`, `3.10.13`,
|
|
39
39
|
|
|
40
40
|
Example usage of how this package was published
|
|
41
41
|
```python
|
|
42
|
-
from quickpub import publish,
|
|
42
|
+
from quickpub import publish, MypyRunner, PylintRunner, UnittestRunner, CondaPythonProvider, \
|
|
43
|
+
PypircUploadTarget, SetuptoolsBuildSchema, GithubUploadTarget
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
def main() -> None:
|
|
46
47
|
publish(
|
|
47
48
|
name="quickpub",
|
|
48
|
-
version="0.
|
|
49
|
+
version="1.0.3",
|
|
49
50
|
author="danielnachumdev",
|
|
50
51
|
author_email="danielnachumdev@gmail.com",
|
|
51
52
|
description="A python package to quickly configure and publish a new package",
|
|
52
53
|
homepage="https://github.com/danielnachumdev/quickpub",
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
build_schemas=[SetuptoolsBuildSchema()],
|
|
55
|
+
upload_targets=[PypircUploadTarget(), GithubUploadTarget()],
|
|
56
|
+
python_interpreter_provider=CondaPythonProvider(["base", "390", "380"]),
|
|
57
|
+
quality_assurance_runners=[
|
|
58
|
+
MypyRunner(bound="<=15", configuration_path="./mypy.ini"),
|
|
59
|
+
PylintRunner(bound=">=0.8", configuration_path="./.pylintrc"),
|
|
60
|
+
UnittestRunner(bound=">=0.8"),
|
|
61
|
+
],
|
|
62
|
+
dependencies=["danielutils>=0.9.90"],
|
|
63
|
+
min_python="3.8.0",
|
|
62
64
|
)
|
|
63
65
|
|
|
64
66
|
|
|
65
67
|
if __name__ == '__main__':
|
|
66
68
|
main()
|
|
67
69
|
|
|
70
|
+
|
|
68
71
|
```
|
|
@@ -19,21 +19,21 @@ quickpub.egg-info/dependency_links.txt
|
|
|
19
19
|
quickpub.egg-info/requires.txt
|
|
20
20
|
quickpub.egg-info/top_level.txt
|
|
21
21
|
quickpub/strategies/__init__.py
|
|
22
|
-
quickpub/strategies/
|
|
23
|
-
quickpub/strategies/
|
|
24
|
-
quickpub/strategies/
|
|
22
|
+
quickpub/strategies/build_schema.py
|
|
23
|
+
quickpub/strategies/python_provider.py
|
|
24
|
+
quickpub/strategies/quality_assurance_runner.py
|
|
25
25
|
quickpub/strategies/quickpub_strategy.py
|
|
26
|
-
quickpub/strategies/
|
|
26
|
+
quickpub/strategies/upload_target.py
|
|
27
27
|
quickpub/strategies/implementations/__init__.py
|
|
28
28
|
quickpub/strategies/implementations/conda_python_version_manager_strategy.py
|
|
29
|
-
quickpub/strategies/implementations/
|
|
30
|
-
quickpub/strategies/implementations/
|
|
31
|
-
quickpub/strategies/implementations/
|
|
32
|
-
quickpub/strategies/implementations/
|
|
33
|
-
quickpub/strategies/implementations/
|
|
34
|
-
quickpub/strategies/implementations/
|
|
29
|
+
quickpub/strategies/implementations/github_upload_target.py
|
|
30
|
+
quickpub/strategies/implementations/mypy_qa_runner.py
|
|
31
|
+
quickpub/strategies/implementations/pylint_qa_runner.py
|
|
32
|
+
quickpub/strategies/implementations/pypirc_upload_target.py
|
|
33
|
+
quickpub/strategies/implementations/pytest_qa_runner.py
|
|
34
|
+
quickpub/strategies/implementations/setuptools_build_schema.py
|
|
35
35
|
quickpub/strategies/implementations/system_interpreter.py
|
|
36
|
-
quickpub/strategies/implementations/
|
|
36
|
+
quickpub/strategies/implementations/unittest_qa_runner.py
|
|
37
37
|
quickpub/structures/__init__.py
|
|
38
38
|
quickpub/structures/bound.py
|
|
39
39
|
quickpub/structures/dependency.py
|
quickpub-1.0.2/README.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# quickpub V0.8.3
|
|
2
|
-
**Tested python versions**: `3.8.0`, `3.9.0`, `3.10.13`,
|
|
3
|
-
|
|
4
|
-
Example usage of how this package was published
|
|
5
|
-
```python
|
|
6
|
-
from quickpub import publish, AdditionalConfiguration, MypyRunner, PylintRunner, UnittestRunner
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def main() -> None:
|
|
10
|
-
publish(
|
|
11
|
-
name="quickpub",
|
|
12
|
-
version="0.8.0",
|
|
13
|
-
author="danielnachumdev",
|
|
14
|
-
author_email="danielnachumdev@gmail.com",
|
|
15
|
-
description="A python package to quickly configure and publish a new package",
|
|
16
|
-
homepage="https://github.com/danielnachumdev/quickpub",
|
|
17
|
-
dependencies=["twine", "danielutils"],
|
|
18
|
-
min_python="3.9.19",
|
|
19
|
-
config=AdditionalConfiguration(
|
|
20
|
-
runners=[
|
|
21
|
-
MypyRunner(bound="<15"),
|
|
22
|
-
PylintRunner(bound=">=0.8"),
|
|
23
|
-
UnittestRunner(bound=">=0.8"),
|
|
24
|
-
]
|
|
25
|
-
)
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if __name__ == '__main__':
|
|
30
|
-
main()
|
|
31
|
-
|
|
32
|
-
```
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
from .pypirc_upload_strategy import *
|
|
2
|
-
from .git_upload_strategy import *
|
|
3
|
-
from .setuptools_build_strategy import *
|
|
4
|
-
from .mypy_qa_strategy import *
|
|
5
|
-
from .pylint_qa_strategy import *
|
|
6
|
-
from .pytest_qa_strategy import *
|
|
7
|
-
from .unittest_qa_strategy import *
|
|
8
|
-
from .conda_python_version_manager_strategy import *
|
|
9
|
-
from .system_interpreter import *
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# TODO
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from abc import abstractmethod
|
|
3
|
-
from typing import Union, List, Optional, cast
|
|
4
|
-
from danielutils import LayeredCommand, get_os, OSType, file_exists
|
|
5
|
-
|
|
6
|
-
from quickpub import Bound
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Configurable:
|
|
10
|
-
@property
|
|
11
|
-
def has_config(self) -> bool:
|
|
12
|
-
return self.config_path is not None
|
|
13
|
-
|
|
14
|
-
def __init__(self, config_path: Optional[str] = None):
|
|
15
|
-
self.config_path = config_path
|
|
16
|
-
if self.has_config:
|
|
17
|
-
if not file_exists(self.config_path):
|
|
18
|
-
raise FileNotFoundError(f"Can't find config file {self.config_path}")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class HasOptionalExecutable:
|
|
22
|
-
PYTHON: str = "python" if get_os() == OSType.WINDOWS else "python3"
|
|
23
|
-
|
|
24
|
-
@property
|
|
25
|
-
def use_executable(self) -> bool:
|
|
26
|
-
return self.executable_path is not None
|
|
27
|
-
|
|
28
|
-
def __init__(self, name, executable_path: Optional[str] = None) -> None:
|
|
29
|
-
self.name = name
|
|
30
|
-
self.executable_path = executable_path
|
|
31
|
-
if self.use_executable:
|
|
32
|
-
if not file_exists(self.executable_path):
|
|
33
|
-
raise FileNotFoundError(f"Executable not found {self.executable_path}")
|
|
34
|
-
|
|
35
|
-
def get_executable(self, use_system_interpreter: bool = False) -> str:
|
|
36
|
-
if self.use_executable:
|
|
37
|
-
return cast(str, self.executable_path)
|
|
38
|
-
|
|
39
|
-
p = self.PYTHON
|
|
40
|
-
if use_system_interpreter:
|
|
41
|
-
p = sys.executable
|
|
42
|
-
return f"{p} -m {self.name}"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class QualityAssuranceStrategy(Configurable, HasOptionalExecutable):
|
|
46
|
-
|
|
47
|
-
def __init__(self, *, name: str, bound: Union[str, Bound], target: Optional[str] = None,
|
|
48
|
-
configuration_path: Optional[str] = None,
|
|
49
|
-
executable_path: Optional[str] = None) -> None:
|
|
50
|
-
Configurable.__init__(self, configuration_path)
|
|
51
|
-
HasOptionalExecutable.__init__(self, name, executable_path)
|
|
52
|
-
self.bound: Bound = bound if isinstance(bound, Bound) else Bound.from_string(bound)
|
|
53
|
-
self.target = target
|
|
54
|
-
|
|
55
|
-
@abstractmethod
|
|
56
|
-
def _build_command(self, target: str, use_system_interpreter: bool = False) -> str:
|
|
57
|
-
...
|
|
58
|
-
|
|
59
|
-
@abstractmethod
|
|
60
|
-
def _install_dependencies(self, base: LayeredCommand) -> None:
|
|
61
|
-
...
|
|
62
|
-
|
|
63
|
-
def _pre_command(self) -> None:
|
|
64
|
-
pass
|
|
65
|
-
|
|
66
|
-
def _post_command(self) -> None:
|
|
67
|
-
pass
|
|
68
|
-
|
|
69
|
-
def run(self, target: str, executor: LayeredCommand, *_, verbose: bool = True, # type: ignore
|
|
70
|
-
use_system_interpreter: bool = False, raise_on_fail: bool = False, print_func, env_name: str) -> None:
|
|
71
|
-
# =====================================
|
|
72
|
-
# IMPORTANT: need to explicitly override it here
|
|
73
|
-
from quickpub.proxy import os_system
|
|
74
|
-
from quickpub.enforcers import exit_if
|
|
75
|
-
executor._executor = os_system
|
|
76
|
-
# =====================================
|
|
77
|
-
command = self._build_command(target, use_system_interpreter)
|
|
78
|
-
self._pre_command()
|
|
79
|
-
try:
|
|
80
|
-
ret, out, err = executor(command, command_raise_on_fail=False)
|
|
81
|
-
score = self._calculate_score(ret, "".join(out + err).splitlines(), verbose=verbose)
|
|
82
|
-
exit_if(not self.bound.compare_against(score),
|
|
83
|
-
f"On env '{env_name}' runner '{self.__class__.__name__}' failed to pass it's defined bound. Got a score of {score} but expected {self.bound}",
|
|
84
|
-
verbose=verbose, err_func=print_func)
|
|
85
|
-
except Exception as e:
|
|
86
|
-
raise RuntimeError(
|
|
87
|
-
f"On env {env_name}, failed to run {self.__class__.__name__}. Try running manually:\n{executor._build_command(command)}") from e
|
|
88
|
-
finally:
|
|
89
|
-
self._post_command()
|
|
90
|
-
|
|
91
|
-
@abstractmethod
|
|
92
|
-
def _calculate_score(self, ret: int, command_output: List[str], *, verbose: bool = False) -> float:
|
|
93
|
-
...
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
__all__ = [
|
|
97
|
-
"QualityAssuranceStrategy"
|
|
98
|
-
]
|
|
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
|