quickpub 3.0.1__tar.gz → 3.0.5__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.1/quickpub.egg-info → quickpub-3.0.5}/PKG-INFO +1 -1
- {quickpub-3.0.1 → quickpub-3.0.5}/pyproject.toml +1 -1
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/__init__.py +1 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/__main__.py +3 -3
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/classifiers.py +6 -2
- quickpub-3.0.5/quickpub/enforcers.py +39 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/files.py +33 -0
- quickpub-3.0.5/quickpub/functions.py +125 -0
- quickpub-3.0.5/quickpub/logging_.py +105 -0
- quickpub-3.0.5/quickpub/proxy.py +56 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/qa.py +114 -33
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/__init__.py +1 -1
- quickpub-3.0.5/quickpub/strategies/build_schema.py +28 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/constraint_enforcer.py +8 -1
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/build_schemas/setuptools_build_schema.py +19 -2
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/constraint_enforcers/license_enforcer.py +9 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/constraint_enforcers/local_version_enforcer.py +12 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/constraint_enforcers/pypi_remote_version_enforcer.py +12 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/constraint_enforcers/pypirc_enforcer.py +11 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/constraint_enforcers/readme_enforcer.py +9 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/python_providers/conda_python_provider.py +20 -2
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/python_providers/default_python_provider.py +12 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/quality_assurance_runners/mypy_qa_runner.py +17 -1
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/quality_assurance_runners/pylint_qa_runner.py +19 -1
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/quality_assurance_runners/pytest_qa_runner.py +21 -2
- quickpub-3.0.5/quickpub/strategies/implementations/quality_assurance_runners/unittest_qa_runner.py +108 -0
- quickpub-3.0.5/quickpub/strategies/implementations/upload_targets/github_upload_target.py +45 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/upload_targets/pypirc_upload_target.py +27 -6
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/python_provider.py +17 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/quality_assurance_runner.py +65 -9
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/quickpub_strategy.py +1 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/upload_target.py +8 -1
- quickpub-3.0.5/quickpub/structures/bound.py +60 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/structures/dependency.py +27 -3
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/structures/version.py +15 -1
- quickpub-3.0.5/quickpub/validators.py +113 -0
- quickpub-3.0.5/quickpub/worker_pool.py +15 -0
- {quickpub-3.0.1 → quickpub-3.0.5/quickpub.egg-info}/PKG-INFO +1 -1
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub.egg-info/SOURCES.txt +2 -0
- quickpub-3.0.1/quickpub/enforcers.py +0 -27
- quickpub-3.0.1/quickpub/functions.py +0 -72
- quickpub-3.0.1/quickpub/proxy.py +0 -24
- quickpub-3.0.1/quickpub/strategies/build_schema.py +0 -17
- quickpub-3.0.1/quickpub/strategies/implementations/quality_assurance_runners/unittest_qa_runner.py +0 -69
- quickpub-3.0.1/quickpub/strategies/implementations/upload_targets/github_upload_target.py +0 -26
- quickpub-3.0.1/quickpub/structures/bound.py +0 -37
- quickpub-3.0.1/quickpub/validators.py +0 -51
- {quickpub-3.0.1 → quickpub-3.0.5}/LICENSE +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/MANIFEST.in +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/README.md +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/py.typed +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/build_schemas/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/constraint_enforcers/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/python_providers/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/quality_assurance_runners/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/strategies/implementations/upload_targets/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub/structures/__init__.py +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub.egg-info/dependency_links.txt +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub.egg-info/requires.txt +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/quickpub.egg-info/top_level.txt +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/setup.cfg +0 -0
- {quickpub-3.0.1 → quickpub-3.0.5}/setup.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from typing import Optional, Union, List, Any
|
|
2
|
+
from typing import Optional, Union, List, Any
|
|
3
3
|
|
|
4
4
|
import fire
|
|
5
5
|
from danielutils import warning, error
|
|
@@ -13,7 +13,9 @@ from .structures import Version, Dependency
|
|
|
13
13
|
from .files import create_toml, create_setup, create_manifest
|
|
14
14
|
from .classifiers import *
|
|
15
15
|
from .qa import qa, SupportsProgress
|
|
16
|
+
from .logging_ import setup_logging
|
|
16
17
|
|
|
18
|
+
setup_logging()
|
|
17
19
|
|
|
18
20
|
def publish(
|
|
19
21
|
*,
|
|
@@ -37,7 +39,6 @@ def publish(
|
|
|
37
39
|
keywords: Optional[List[str]] = None,
|
|
38
40
|
explicit_src_folder_path: Optional[str] = None,
|
|
39
41
|
# ========== QA Parameters ==========
|
|
40
|
-
log: Optional[Callable[[Any], None]] = None,
|
|
41
42
|
pbar: Optional[SupportsProgress] = None, # tqdm
|
|
42
43
|
|
|
43
44
|
demo: bool = False,
|
|
@@ -87,7 +88,6 @@ def publish(
|
|
|
87
88
|
name,
|
|
88
89
|
explicit_src_folder_path,
|
|
89
90
|
validated_dependencies,
|
|
90
|
-
log,
|
|
91
91
|
pbar
|
|
92
92
|
))
|
|
93
93
|
if not res:
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import logging
|
|
2
2
|
from enum import Enum
|
|
3
3
|
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
class Classifier(Enum):
|
|
6
8
|
"""
|
|
@@ -36,7 +38,9 @@ class Classifier(Enum):
|
|
|
36
38
|
def __str__(self) -> str:
|
|
37
39
|
name = Classifier._split_name(self.__class__.__qualname__)
|
|
38
40
|
value = self._str()
|
|
39
|
-
|
|
41
|
+
result = f"{name} :: {value}"
|
|
42
|
+
logger.debug("Classifier string representation: %s", result)
|
|
43
|
+
return result
|
|
40
44
|
|
|
41
45
|
|
|
42
46
|
class DevelopmentStatusClassifier(Classifier):
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Union, Callable
|
|
3
|
+
|
|
4
|
+
from danielutils import error
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ExitEarlyError(Exception):
|
|
10
|
+
"""Custom exception raised when early exit conditions are met."""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def exit_if(
|
|
14
|
+
predicate: Union[bool, Callable[[], bool]],
|
|
15
|
+
msg: str,
|
|
16
|
+
*,
|
|
17
|
+
verbose: bool = True,
|
|
18
|
+
err_func: Callable[[str], None] = error
|
|
19
|
+
) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Exit the program if the given predicate is true.
|
|
22
|
+
|
|
23
|
+
:param predicate: Boolean value or callable that returns a boolean
|
|
24
|
+
:param msg: Error message to display
|
|
25
|
+
:param verbose: Whether to display the error message
|
|
26
|
+
:param err_func: Function to call for error display
|
|
27
|
+
:raises ExitEarlyError: When the predicate condition is met
|
|
28
|
+
"""
|
|
29
|
+
if (isinstance(predicate, bool) and predicate) or (callable(predicate) and predicate()):
|
|
30
|
+
logger.error("Exit condition met: %s", msg)
|
|
31
|
+
if verbose:
|
|
32
|
+
err_func(msg)
|
|
33
|
+
raise ExitEarlyError(msg)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"exit_if",
|
|
38
|
+
"ExitEarlyError",
|
|
39
|
+
]
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from typing import List
|
|
2
3
|
from danielutils import get_files
|
|
3
4
|
|
|
4
5
|
from .classifiers import Classifier
|
|
5
6
|
from .structures import Version, Dependency
|
|
6
7
|
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
def create_toml(
|
|
9
12
|
*,
|
|
@@ -21,6 +24,24 @@ def create_toml(
|
|
|
21
24
|
dependencies: List[Dependency],
|
|
22
25
|
classifiers: List[Classifier]
|
|
23
26
|
) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Create a pyproject.toml file for the package.
|
|
29
|
+
|
|
30
|
+
:param name: Package name
|
|
31
|
+
:param src_folder_path: Path to source folder
|
|
32
|
+
:param readme_file_path: Path to README file
|
|
33
|
+
:param license_file_path: Path to LICENSE file
|
|
34
|
+
:param version: Package version
|
|
35
|
+
:param author: Author name
|
|
36
|
+
:param author_email: Author email
|
|
37
|
+
:param description: Package description
|
|
38
|
+
:param homepage: Package homepage URL
|
|
39
|
+
:param keywords: List of package keywords
|
|
40
|
+
:param min_python: Minimum Python version required
|
|
41
|
+
:param dependencies: List of package dependencies
|
|
42
|
+
:param classifiers: List of package classifiers
|
|
43
|
+
"""
|
|
44
|
+
logger.info("Creating pyproject.toml for package '%s' version '%s'", name, version)
|
|
24
45
|
classifiers_string = ",\n\t".join([f"\"{str(c)}\"" for c in classifiers])
|
|
25
46
|
if len(classifiers_string) > 0:
|
|
26
47
|
classifiers_string = f"\n\t{classifiers_string}\n"
|
|
@@ -29,6 +50,7 @@ def create_toml(
|
|
|
29
50
|
if file == "py.typed":
|
|
30
51
|
py_typed = f"""[tool.setuptools.package-data]
|
|
31
52
|
"{name}" = ["py.typed"]"""
|
|
53
|
+
logger.debug("Found py.typed file, adding package-data configuration")
|
|
32
54
|
break
|
|
33
55
|
|
|
34
56
|
s = f"""[build-system]
|
|
@@ -59,16 +81,27 @@ packages = ["{name}"]
|
|
|
59
81
|
"""
|
|
60
82
|
with open("pyproject.toml", "w", encoding="utf8") as f:
|
|
61
83
|
f.write(s)
|
|
84
|
+
logger.info("Successfully created pyproject.toml")
|
|
62
85
|
|
|
63
86
|
|
|
64
87
|
def create_setup() -> None:
|
|
88
|
+
"""Create a basic setup.py file for the package."""
|
|
89
|
+
logger.info("Creating setup.py file")
|
|
65
90
|
with open("./setup.py", "w", encoding="utf8") as f:
|
|
66
91
|
f.write("from setuptools import setup\n\nsetup()\n")
|
|
92
|
+
logger.info("Successfully created setup.py")
|
|
67
93
|
|
|
68
94
|
|
|
69
95
|
def create_manifest(*, name: str) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Create a MANIFEST.in file for the package.
|
|
98
|
+
|
|
99
|
+
:param name: Package name
|
|
100
|
+
"""
|
|
101
|
+
logger.info("Creating MANIFEST.in for package '%s'", name)
|
|
70
102
|
with open("./MANIFEST.in", "w", encoding="utf8") as f:
|
|
71
103
|
f.write(f"recursive-include {name} *.py")
|
|
104
|
+
logger.info("Successfully created MANIFEST.in")
|
|
72
105
|
|
|
73
106
|
|
|
74
107
|
__all__ = [
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from danielutils import info
|
|
3
|
+
|
|
4
|
+
from .enforcers import exit_if
|
|
5
|
+
from .structures import Version
|
|
6
|
+
import quickpub.proxy
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build(
|
|
12
|
+
*,
|
|
13
|
+
verbose: bool = True
|
|
14
|
+
) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Build the package distribution.
|
|
17
|
+
|
|
18
|
+
:param verbose: Whether to display verbose output
|
|
19
|
+
"""
|
|
20
|
+
logger.info("Starting build process")
|
|
21
|
+
if verbose:
|
|
22
|
+
info("Creating new distribution...")
|
|
23
|
+
logger.info("Creating new distribution...")
|
|
24
|
+
|
|
25
|
+
ret, stdout, stderr = quickpub.proxy.cm("python", "setup.py", "sdist")
|
|
26
|
+
|
|
27
|
+
if ret != 0:
|
|
28
|
+
logger.error("Build failed with return code %d: %s", ret, stderr.decode(encoding='utf8'))
|
|
29
|
+
exit_if(
|
|
30
|
+
ret != 0,
|
|
31
|
+
stderr.decode(encoding="utf8")
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
logger.info("Build completed successfully")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def upload(
|
|
38
|
+
*,
|
|
39
|
+
name: str,
|
|
40
|
+
version: Version,
|
|
41
|
+
verbose: bool = True
|
|
42
|
+
) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Upload the package to PyPI.
|
|
45
|
+
|
|
46
|
+
:param name: Package name
|
|
47
|
+
:param version: Package version
|
|
48
|
+
:param verbose: Whether to display verbose output
|
|
49
|
+
"""
|
|
50
|
+
logger.info("Starting upload process for package '%s' version '%s'", name, version)
|
|
51
|
+
if verbose:
|
|
52
|
+
info("Uploading")
|
|
53
|
+
logger.info("Uploading package to PyPI")
|
|
54
|
+
|
|
55
|
+
ret, stdout, stderr = quickpub.proxy.cm("twine", "upload", "--config-file", ".pypirc",
|
|
56
|
+
f"dist/{name}-{version}.tar.gz")
|
|
57
|
+
|
|
58
|
+
if ret != 0:
|
|
59
|
+
logger.error("Upload failed with return code %d: %s", ret, stderr.decode(encoding='utf8'))
|
|
60
|
+
exit_if(
|
|
61
|
+
ret != 0,
|
|
62
|
+
f"Failed uploading the package to pypi. Try running the following command manually:\n\ttwine upload --config-file .pypirc dist/{name}-{version}.tar.gz"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
logger.info("Successfully uploaded package '%s' version '%s'", name, version)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def commit(
|
|
69
|
+
*,
|
|
70
|
+
version: Version,
|
|
71
|
+
verbose: bool = True
|
|
72
|
+
) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Commit and push changes to Git repository.
|
|
75
|
+
|
|
76
|
+
:param version: Package version
|
|
77
|
+
:param verbose: Whether to display verbose output
|
|
78
|
+
"""
|
|
79
|
+
logger.info("Starting Git commit process for version '%s'", version)
|
|
80
|
+
|
|
81
|
+
if verbose:
|
|
82
|
+
info("Git")
|
|
83
|
+
info("\tStaging")
|
|
84
|
+
logger.info("Staging files for Git commit")
|
|
85
|
+
|
|
86
|
+
ret, stdout, stderr = quickpub.proxy.cm("git add .")
|
|
87
|
+
if ret != 0:
|
|
88
|
+
logger.error("Git add failed with return code %d: %s", ret, stderr.decode(encoding='utf8'))
|
|
89
|
+
exit_if(
|
|
90
|
+
ret != 0,
|
|
91
|
+
stderr.decode(encoding="utf8")
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if verbose:
|
|
95
|
+
info("\tCommitting")
|
|
96
|
+
logger.info("Committing changes with message 'updated to version %s'", version)
|
|
97
|
+
|
|
98
|
+
ret, stdout, stderr = quickpub.proxy.cm(f"git commit -m \"updated to version {version}\"")
|
|
99
|
+
if ret != 0:
|
|
100
|
+
logger.error("Git commit failed with return code %d: %s", ret, stderr.decode(encoding='utf8'))
|
|
101
|
+
exit_if(
|
|
102
|
+
ret != 0,
|
|
103
|
+
stderr.decode(encoding="utf8")
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
if verbose:
|
|
107
|
+
info("\tPushing")
|
|
108
|
+
logger.info("Pushing changes to remote repository")
|
|
109
|
+
|
|
110
|
+
ret, stdout, stderr = quickpub.proxy.cm("git push")
|
|
111
|
+
if ret != 0:
|
|
112
|
+
logger.error("Git push failed with return code %d: %s", ret, stderr.decode(encoding='utf8'))
|
|
113
|
+
exit_if(
|
|
114
|
+
ret != 0,
|
|
115
|
+
stderr.decode(encoding="utf8")
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
logger.info("Successfully committed and pushed version '%s'", version)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
__all__ = [
|
|
122
|
+
"build",
|
|
123
|
+
"upload",
|
|
124
|
+
"commit",
|
|
125
|
+
]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# Global log level that can be modified by users
|
|
5
|
+
_LOG_LEVEL = logging.INFO
|
|
6
|
+
|
|
7
|
+
class QuickpubLogFilter(logging.Filter):
|
|
8
|
+
"""
|
|
9
|
+
Filter that only allows logs from the quickpub package.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def filter(self, record):
|
|
13
|
+
return record.name.startswith('quickpub')
|
|
14
|
+
|
|
15
|
+
class TqdmLoggingHandler(logging.Handler):
|
|
16
|
+
"""
|
|
17
|
+
Custom logging handler that uses tqdm.write to avoid conflicts with progress bars.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, level: int = logging.NOTSET):
|
|
21
|
+
super().__init__(level)
|
|
22
|
+
self._tqdm = None
|
|
23
|
+
|
|
24
|
+
def emit(self, record):
|
|
25
|
+
try:
|
|
26
|
+
import tqdm
|
|
27
|
+
msg = self.format(record)
|
|
28
|
+
tqdm.tqdm.write(msg, file=sys.stdout)
|
|
29
|
+
except ImportError:
|
|
30
|
+
# Fallback if tqdm becomes unavailable
|
|
31
|
+
print(self.format(record), file=sys.stdout)
|
|
32
|
+
except Exception:
|
|
33
|
+
self.handleError(record)
|
|
34
|
+
|
|
35
|
+
def setup_logging(level: int = None):
|
|
36
|
+
"""
|
|
37
|
+
Set up logging with appropriate handler based on tqdm availability.
|
|
38
|
+
|
|
39
|
+
If tqdm is installed, uses tqdm.write for output to avoid conflicts with progress bars.
|
|
40
|
+
If tqdm is not installed, uses a standard StreamHandler to stdout.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
level: Logging level (default: uses the global _LOG_LEVEL constant)
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Configured logger instance
|
|
47
|
+
"""
|
|
48
|
+
global _LOG_LEVEL
|
|
49
|
+
|
|
50
|
+
# Use provided level or fall back to global constant
|
|
51
|
+
if level is not None:
|
|
52
|
+
_LOG_LEVEL = level
|
|
53
|
+
|
|
54
|
+
logger = logging.getLogger()
|
|
55
|
+
logger.setLevel(_LOG_LEVEL)
|
|
56
|
+
|
|
57
|
+
# Clear any existing handlers
|
|
58
|
+
logger.handlers.clear()
|
|
59
|
+
|
|
60
|
+
# Common formatter for both handlers
|
|
61
|
+
formatter = logging.Formatter(
|
|
62
|
+
'%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
import tqdm
|
|
67
|
+
|
|
68
|
+
# Use tqdm.write if tqdm is available
|
|
69
|
+
handler = TqdmLoggingHandler()
|
|
70
|
+
except ImportError:
|
|
71
|
+
handler = logging.StreamHandler(sys.stdout)
|
|
72
|
+
handler.setLevel(_LOG_LEVEL)
|
|
73
|
+
handler.setFormatter(formatter)
|
|
74
|
+
|
|
75
|
+
# Add filter to only allow quickpub logs
|
|
76
|
+
handler.addFilter(QuickpubLogFilter())
|
|
77
|
+
|
|
78
|
+
logger.addHandler(handler)
|
|
79
|
+
|
|
80
|
+
def set_log_level(level: int):
|
|
81
|
+
"""
|
|
82
|
+
Set the logging level for the root logger and all its handlers.
|
|
83
|
+
|
|
84
|
+
This function allows end users to dynamically change the log level
|
|
85
|
+
after logging has been set up. It also updates the global _LOG_LEVEL
|
|
86
|
+
constant so that future calls to setup_logging() will use this level.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
level: Logging level (e.g., logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR)
|
|
90
|
+
"""
|
|
91
|
+
global _LOG_LEVEL
|
|
92
|
+
_LOG_LEVEL = level
|
|
93
|
+
|
|
94
|
+
logger = logging.getLogger()
|
|
95
|
+
logger.setLevel(level)
|
|
96
|
+
|
|
97
|
+
# Update all handlers to use the new level
|
|
98
|
+
for handler in logger.handlers:
|
|
99
|
+
handler.setLevel(level)
|
|
100
|
+
|
|
101
|
+
__all__ = [
|
|
102
|
+
"setup_logging",
|
|
103
|
+
"set_log_level",
|
|
104
|
+
"QuickpubLogFilter"
|
|
105
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from typing import Tuple
|
|
4
|
+
import requests
|
|
5
|
+
import danielutils
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# need it like this for the testing
|
|
11
|
+
def cm(*args, **kwargs) -> Tuple[int, bytes, bytes]:
|
|
12
|
+
"""
|
|
13
|
+
Execute a command and return the result.
|
|
14
|
+
|
|
15
|
+
:param args: Command arguments
|
|
16
|
+
:param kwargs: Additional keyword arguments
|
|
17
|
+
:return: Tuple of (return_code, stdout, stderr)
|
|
18
|
+
"""
|
|
19
|
+
logger.debug("Executing command: %s", ' '.join(args))
|
|
20
|
+
result = danielutils.cm(*args, **kwargs)
|
|
21
|
+
logger.debug("Command completed with return code: %d", result[0])
|
|
22
|
+
return result
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def os_system(command) -> int:
|
|
26
|
+
"""
|
|
27
|
+
Execute a system command.
|
|
28
|
+
|
|
29
|
+
:param command: Command to execute
|
|
30
|
+
:return: Return code of the command
|
|
31
|
+
"""
|
|
32
|
+
logger.debug("Executing system command: %s", command)
|
|
33
|
+
result = os.system(command)
|
|
34
|
+
logger.debug("System command completed with return code: %d", result)
|
|
35
|
+
return result
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get(*args, **kwargs) -> requests.models.Response:
|
|
39
|
+
"""
|
|
40
|
+
Make an HTTP GET request.
|
|
41
|
+
|
|
42
|
+
:param args: Request arguments
|
|
43
|
+
:param kwargs: Additional keyword arguments
|
|
44
|
+
:return: Response object
|
|
45
|
+
"""
|
|
46
|
+
logger.debug("Making HTTP GET request to: %s", args[0] if args else 'URL not provided')
|
|
47
|
+
response = requests.get(*args, **kwargs)
|
|
48
|
+
logger.debug("HTTP GET request completed with status code: %d", response.status_code)
|
|
49
|
+
return response
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
"cm",
|
|
54
|
+
'os_system',
|
|
55
|
+
"get"
|
|
56
|
+
]
|