quickpub 3.0.61__tar.gz → 3.1.0__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.
Files changed (58) hide show
  1. {quickpub-3.0.61/quickpub.egg-info → quickpub-3.1.0}/PKG-INFO +2 -2
  2. {quickpub-3.0.61 → quickpub-3.1.0}/pyproject.toml +5 -2
  3. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/__init__.py +1 -1
  4. quickpub-3.1.0/quickpub/__main__.py +156 -0
  5. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/classifiers.py +6 -2
  6. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/enforcers.py +9 -7
  7. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/files.py +43 -26
  8. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/functions.py +34 -39
  9. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/logging_.py +4 -7
  10. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/proxy.py +11 -11
  11. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/qa.py +145 -76
  12. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/build_schema.py +3 -4
  13. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/constraint_enforcer.py +3 -4
  14. quickpub-3.1.0/quickpub/strategies/implementations/build_schemas/__init__.py +1 -0
  15. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/build_schemas/setuptools_build_schema.py +14 -5
  16. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/constraint_enforcers/license_enforcer.py +1 -0
  17. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/constraint_enforcers/local_version_enforcer.py +18 -8
  18. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/constraint_enforcers/pypi_remote_version_enforcer.py +20 -12
  19. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/constraint_enforcers/pypirc_enforcer.py +6 -2
  20. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/python_providers/conda_python_provider.py +9 -7
  21. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/python_providers/default_python_provider.py +8 -3
  22. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/quality_assurance_runners/mypy_qa_runner.py +29 -11
  23. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/quality_assurance_runners/pylint_qa_runner.py +30 -11
  24. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/quality_assurance_runners/pytest_qa_runner.py +44 -21
  25. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/quality_assurance_runners/unittest_qa_runner.py +50 -24
  26. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/upload_targets/github_upload_target.py +18 -9
  27. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/upload_targets/pypirc_upload_target.py +34 -24
  28. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/python_provider.py +11 -13
  29. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/quality_assurance_runner.py +76 -39
  30. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/quickpub_strategy.py +2 -1
  31. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/upload_target.py +3 -2
  32. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/structures/bound.py +8 -7
  33. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/structures/dependency.py +19 -10
  34. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/structures/version.py +12 -6
  35. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/validators.py +9 -7
  36. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/worker_pool.py +1 -1
  37. {quickpub-3.0.61 → quickpub-3.1.0/quickpub.egg-info}/PKG-INFO +2 -2
  38. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub.egg-info/SOURCES.txt +1 -0
  39. quickpub-3.1.0/quickpub.egg-info/entry_points.txt +2 -0
  40. quickpub-3.0.61/quickpub/__main__.py +0 -133
  41. quickpub-3.0.61/quickpub/strategies/implementations/build_schemas/__init__.py +0 -1
  42. {quickpub-3.0.61 → quickpub-3.1.0}/LICENSE +0 -0
  43. {quickpub-3.0.61 → quickpub-3.1.0}/MANIFEST.in +0 -0
  44. {quickpub-3.0.61 → quickpub-3.1.0}/README.md +0 -0
  45. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/py.typed +0 -0
  46. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/__init__.py +0 -0
  47. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/__init__.py +0 -0
  48. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/constraint_enforcers/__init__.py +0 -0
  49. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/constraint_enforcers/readme_enforcer.py +0 -0
  50. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/python_providers/__init__.py +0 -0
  51. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/quality_assurance_runners/__init__.py +0 -0
  52. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/strategies/implementations/upload_targets/__init__.py +0 -0
  53. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub/structures/__init__.py +0 -0
  54. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub.egg-info/dependency_links.txt +0 -0
  55. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub.egg-info/requires.txt +0 -0
  56. {quickpub-3.0.61 → quickpub-3.1.0}/quickpub.egg-info/top_level.txt +0 -0
  57. {quickpub-3.0.61 → quickpub-3.1.0}/setup.cfg +0 -0
  58. {quickpub-3.0.61 → quickpub-3.1.0}/setup.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quickpub
3
- Version: 3.0.61
4
- Summary: A python package to quickly configure and publish a new package
3
+ Version: 3.1.0
4
+ Summary: A local CI/CD simulation tool that runs quality checks, tests, and validations locally before publishing Python packages, ensuring higher build pass rates and faster feedback loops
5
5
  Author-email: danielnachumdev <danielnachumdev@gmail.com>
6
6
  License: MIT License
7
7
 
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quickpub"
7
- version = "3.0.61"
7
+ version = "3.1.0"
8
8
  authors = [
9
9
  { name = "danielnachumdev", email = "danielnachumdev@gmail.com" },
10
10
  ]
11
11
  dependencies = ['danielutils>=1.0.0', 'requests', 'fire']
12
12
  keywords = []
13
13
  license = { "file" = "./LICENSE" }
14
- description = "A python package to quickly configure and publish a new package"
14
+ description = "A local CI/CD simulation tool that runs quality checks, tests, and validations locally before publishing Python packages, ensuring higher build pass rates and faster feedback loops"
15
15
  readme = {file = "./README.md", content-type = "text/markdown"}
16
16
  requires-python = ">=3.8.0"
17
17
  classifiers = [
@@ -20,9 +20,12 @@ classifiers = [
20
20
  "Programming Language :: Python :: 3",
21
21
  "Operating System :: Microsoft :: Windows"
22
22
  ]
23
+ [project.scripts]
24
+ quickpub = "quickpub.__main__:main"
23
25
 
24
26
  [tool.setuptools]
25
27
  packages = ["quickpub"]
28
+
26
29
  [tool.setuptools.package-data]
27
30
  "quickpub" = ["py.typed"]
28
31
 
@@ -3,4 +3,4 @@ from .strategies import *
3
3
  from .enforcers import ExitEarlyError
4
4
  from .qa import SupportsProgress
5
5
  from .logging_ import set_log_level
6
- from .__main__ import publish
6
+ from .__main__ import publish, main
@@ -0,0 +1,156 @@
1
+ import asyncio
2
+ from typing import Optional, Union, List, Any, Dict, Callable
3
+
4
+ import fire
5
+ from danielutils import warning, error
6
+
7
+ from quickpub import ExitEarlyError
8
+ from .strategies import (
9
+ BuildSchema,
10
+ ConstraintEnforcer,
11
+ UploadTarget,
12
+ QualityAssuranceRunner,
13
+ PythonProvider,
14
+ DefaultPythonProvider,
15
+ )
16
+ from .validators import (
17
+ validate_version,
18
+ validate_python_version,
19
+ validate_keywords,
20
+ validate_dependencies,
21
+ validate_source,
22
+ )
23
+ from .structures import Version, Dependency
24
+ from .files import create_toml, create_setup, create_manifest
25
+ from .classifiers import *
26
+ from .qa import qa, SupportsProgress
27
+ from .logging_ import setup_logging
28
+
29
+ setup_logging()
30
+
31
+
32
+ def publish(
33
+ *,
34
+ name: str,
35
+ author: str,
36
+ author_email: str,
37
+ description: str,
38
+ homepage: str,
39
+ build_schemas: List[BuildSchema],
40
+ upload_targets: List[UploadTarget],
41
+ enforcers: Optional[List[ConstraintEnforcer]] = None,
42
+ global_quality_assurance_runners: Optional[List[QualityAssuranceRunner]] = None,
43
+ python_interpreter_provider: PythonProvider = DefaultPythonProvider(),
44
+ readme_file_path: str = "./README.md",
45
+ license_file_path: str = "./LICENSE",
46
+ version: Optional[Union[Version, str]] = None,
47
+ min_python: Optional[Union[Version, str]] = None,
48
+ dependencies: Optional[List[Union[str, Dependency]]] = None,
49
+ keywords: Optional[List[str]] = None,
50
+ explicit_src_folder_path: Optional[str] = None,
51
+ scripts: Optional[Dict[str, Callable]] = None,
52
+ # ========== QA Parameters ==========
53
+ pbar: Optional[SupportsProgress] = None, # tqdm
54
+ demo: bool = False,
55
+ config: Optional[Any] = None,
56
+ ) -> None:
57
+ """The main function for publishing a package. It performs all necessary steps to prepare and publish the package.
58
+
59
+
60
+ :param name: The name of the package.
61
+ :param author: The name of the author.
62
+ :param author_email: The email of the author.
63
+ :param description: A short description of the package.
64
+ :param homepage: The homepage URL for the package (e.g., GitHub repository).
65
+ :param global_quality_assurance_runners: Strategies for quality assurance. These will run on all Envs supplies by the supplier.
66
+ :param build_schemas: Strategies for building the package.
67
+ :param upload_targets: Strategies for uploading the package.
68
+ :param python_interpreter_provider: Strategy for managing Python versions. Defaults to SystemInterpreter().
69
+ :param explicit_src_folder_path: The path to the source code of the package. Defaults to <current working directory>/<name>.
70
+ :param version: The version for the new distribution. Defaults to "0.0.1".
71
+ :param readme_file_path: The path to the README file. Defaults to "./README.md".
72
+ :param license_file_path: The path to the license file. Defaults to "./LICENSE".
73
+ :param min_python: The minimum Python version required for the package. Defaults to the Python version running this script.
74
+ :param keywords: A list of keywords describing areas of interest for the package. Defaults to None.
75
+ :param dependencies: A list of dependencies for the package. Defaults to None.
76
+ :param scripts: Optional dictionary mapping script names to functions for [project.scripts] section. Each entry will create an executable entry point.
77
+ :param log: A function to receive log statements about the process and print them (or do something else idk)
78
+ :param pbar: and object that can be notified about an update of progress like a tqdm progress bar.
79
+ :param demo: Whether to perform checks without making any changes. Defaults to False.
80
+ :param config: Reserved for future use. Defaults to None.
81
+
82
+ Returns:
83
+ None
84
+ """
85
+ version = validate_version(version)
86
+ explicit_src_folder_path = validate_source(name, explicit_src_folder_path)
87
+ if explicit_src_folder_path != f"./{name}":
88
+ warning(
89
+ "The source folder's name is different from the package's name. this may not be currently supported correctly"
90
+ )
91
+ min_python = validate_python_version(min_python) # type:ignore
92
+ keywords = validate_keywords(keywords)
93
+ validated_dependencies: List[Dependency] = validate_dependencies(dependencies)
94
+ for enforcer in enforcers or []:
95
+ enforcer.enforce(name=name, version=version, demo=demo)
96
+ try:
97
+ res = asyncio.get_event_loop().run_until_complete(
98
+ qa(
99
+ python_interpreter_provider,
100
+ global_quality_assurance_runners or [],
101
+ name,
102
+ explicit_src_folder_path,
103
+ validated_dependencies,
104
+ pbar,
105
+ )
106
+ )
107
+ if not res:
108
+ error(
109
+ f"quickpub.publish exited early as '{name}' "
110
+ "did not pass quality assurance step, see above "
111
+ "logs to pass this step."
112
+ )
113
+ raise ExitEarlyError("QA step Failed")
114
+ except ExitEarlyError as e:
115
+ raise e
116
+ except Exception as e:
117
+ raise RuntimeError("Quality assurance stage has failed", e) from e
118
+
119
+ create_setup()
120
+ create_toml(
121
+ name=name,
122
+ src_folder_path=explicit_src_folder_path,
123
+ readme_file_path=readme_file_path,
124
+ license_file_path=license_file_path,
125
+ version=version,
126
+ author=author,
127
+ author_email=author_email,
128
+ description=description,
129
+ homepage=homepage,
130
+ keywords=keywords,
131
+ dependencies=validated_dependencies,
132
+ classifiers=[
133
+ DevelopmentStatusClassifier.Alpha,
134
+ IntendedAudienceClassifier.Developers,
135
+ ProgrammingLanguageClassifier.Python3,
136
+ OperatingSystemClassifier.MicrosoftWindows,
137
+ ],
138
+ min_python=min_python,
139
+ scripts=scripts,
140
+ )
141
+ create_manifest(name=name)
142
+ if not demo:
143
+ for schema in build_schemas:
144
+ schema.build()
145
+ for target in upload_targets:
146
+ target.upload(name=name, version=version)
147
+
148
+
149
+ def main() -> None:
150
+ fire.Fire(publish)
151
+
152
+
153
+ if __name__ == "__main__":
154
+ main()
155
+
156
+ __all__ = ["main", "publish"]
@@ -15,7 +15,7 @@ class Classifier(Enum):
15
15
  @staticmethod
16
16
  def _split_name(name: str) -> str:
17
17
  words = []
18
- current_word = ''
18
+ current_word = ""
19
19
 
20
20
  for char in name:
21
21
  # Check if the character is uppercase
@@ -47,6 +47,7 @@ class DevelopmentStatusClassifier(Classifier):
47
47
  """
48
48
  An enum class for specifying the development state of the package
49
49
  """
50
+
50
51
  # https://pypi.org/classifiers/
51
52
  Planning = 1
52
53
  PreAlpha = 2
@@ -65,6 +66,7 @@ class IntendedAudienceClassifier(Classifier):
65
66
  """
66
67
  An enum class for specifying the intended audience
67
68
  """
69
+
68
70
  CustomerService = "CustomerService"
69
71
  Developers = "Developers"
70
72
 
@@ -73,6 +75,7 @@ class ProgrammingLanguageClassifier(Classifier):
73
75
  """
74
76
  An enum class for specifying the target language level
75
77
  """
78
+
76
79
  Python3 = "Python :: 3"
77
80
 
78
81
 
@@ -80,6 +83,7 @@ class OperatingSystemClassifier(Classifier):
80
83
  """
81
84
  An enum class for specifying the target operating system
82
85
  """
86
+
83
87
  MicrosoftWindows = "Microsoft :: Windows"
84
88
 
85
89
 
@@ -88,5 +92,5 @@ __all__ = [
88
92
  "DevelopmentStatusClassifier",
89
93
  "IntendedAudienceClassifier",
90
94
  "ProgrammingLanguageClassifier",
91
- "OperatingSystemClassifier"
95
+ "OperatingSystemClassifier",
92
96
  ]
@@ -11,22 +11,24 @@ class ExitEarlyError(Exception):
11
11
 
12
12
 
13
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
14
+ predicate: Union[bool, Callable[[], bool]],
15
+ msg: str,
16
+ *,
17
+ verbose: bool = True,
18
+ err_func: Callable[[str], None] = error,
19
19
  ) -> None:
20
20
  """
21
21
  Exit the program if the given predicate is true.
22
-
22
+
23
23
  :param predicate: Boolean value or callable that returns a boolean
24
24
  :param msg: Error message to display
25
25
  :param verbose: Whether to display the error message
26
26
  :param err_func: Function to call for error display
27
27
  :raises ExitEarlyError: When the predicate condition is met
28
28
  """
29
- if (isinstance(predicate, bool) and predicate) or (callable(predicate) and predicate()):
29
+ if (isinstance(predicate, bool) and predicate) or (
30
+ callable(predicate) and predicate()
31
+ ):
30
32
  logger.error("Exit condition met: %s", msg)
31
33
  if verbose:
32
34
  err_func(msg)
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import List
2
+ from typing import List, Optional, Dict, Callable
3
3
  from danielutils import get_files
4
4
 
5
5
  from .classifiers import Classifier
@@ -9,24 +9,25 @@ logger = logging.getLogger(__name__)
9
9
 
10
10
 
11
11
  def create_toml(
12
- *,
13
- name: str,
14
- src_folder_path: str,
15
- readme_file_path: str,
16
- license_file_path: str,
17
- version: Version,
18
- author: str,
19
- author_email: str,
20
- description: str,
21
- homepage: str,
22
- keywords: List[str],
23
- min_python: Version,
24
- dependencies: List[Dependency],
25
- classifiers: List[Classifier]
12
+ *,
13
+ name: str,
14
+ src_folder_path: str,
15
+ readme_file_path: str,
16
+ license_file_path: str,
17
+ version: Version,
18
+ author: str,
19
+ author_email: str,
20
+ description: str,
21
+ homepage: str,
22
+ keywords: List[str],
23
+ min_python: Version,
24
+ dependencies: List[Dependency],
25
+ classifiers: List[Classifier],
26
+ scripts: Optional[Dict[str, Callable]] = None,
26
27
  ) -> None:
27
28
  """
28
29
  Create a pyproject.toml file for the package.
29
-
30
+
30
31
  :param name: Package name
31
32
  :param src_folder_path: Path to source folder
32
33
  :param readme_file_path: Path to README file
@@ -40,9 +41,11 @@ def create_toml(
40
41
  :param min_python: Minimum Python version required
41
42
  :param dependencies: List of package dependencies
42
43
  :param classifiers: List of package classifiers
44
+ :param scripts: Optional dictionary mapping script names to functions for [project.scripts] section
43
45
  """
44
- logger.info("Creating pyproject.toml for package '%s' version '%s'", name, version)
45
- classifiers_string = ",\n\t".join([f"\"{str(c)}\"" for c in classifiers])
46
+ logger.info(
47
+ "Creating pyproject.toml for package '%s' version '%s'", name, version)
48
+ classifiers_string = ",\n\t".join([f'"{str(c)}"' for c in classifiers])
46
49
  if len(classifiers_string) > 0:
47
50
  classifiers_string = f"\n\t{classifiers_string}\n"
48
51
  py_typed = ""
@@ -50,9 +53,26 @@ def create_toml(
50
53
  if file == "py.typed":
51
54
  py_typed = f"""[tool.setuptools.package-data]
52
55
  "{name}" = ["py.typed"]"""
53
- logger.debug("Found py.typed file, adding package-data configuration")
56
+ logger.debug(
57
+ "Found py.typed file, adding package-data configuration")
54
58
  break
55
59
 
60
+ scripts_section = ""
61
+ if scripts:
62
+ logger.debug(
63
+ "Adding [project.scripts] section with %d entries", len(scripts))
64
+ scripts_entries = []
65
+ for script_name, func in scripts.items():
66
+ module = func.__module__
67
+ func_name = func.__name__
68
+ # If module is __main__, prefix it with package name
69
+ if module == "__main__":
70
+ module = f"{name}.__main__"
71
+ entry_point = f"{module}:{func_name}"
72
+ scripts_entries.append(f' {script_name} = "{entry_point}"')
73
+ scripts_section = "\n[project.scripts]\n" + \
74
+ "\n".join(scripts_entries) + "\n"
75
+
56
76
  s = f"""[build-system]
57
77
  requires = ["setuptools>=61.0"]
58
78
  build-backend = "setuptools.build_meta"
@@ -69,10 +89,10 @@ license = {{ "file" = "{license_file_path}" }}
69
89
  description = "{description}"
70
90
  readme = {{file = "{readme_file_path}", content-type = "text/markdown"}}
71
91
  requires-python = ">={min_python}"
72
- classifiers = [{classifiers_string}]
73
-
92
+ classifiers = [{classifiers_string}]{scripts_section}
74
93
  [tool.setuptools]
75
94
  packages = ["{name}"]
95
+
76
96
  {py_typed}
77
97
 
78
98
  [project.urls]
@@ -95,7 +115,7 @@ def create_setup() -> None:
95
115
  def create_manifest(*, name: str) -> None:
96
116
  """
97
117
  Create a MANIFEST.in file for the package.
98
-
118
+
99
119
  :param name: Package name
100
120
  """
101
121
  logger.info("Creating MANIFEST.in for package '%s'", name)
@@ -104,7 +124,4 @@ def create_manifest(*, name: str) -> None:
104
124
  logger.info("Successfully created MANIFEST.in")
105
125
 
106
126
 
107
- __all__ = [
108
- "create_setup",
109
- "create_toml"
110
- ]
127
+ __all__ = ["create_setup", "create_toml"]
@@ -8,13 +8,10 @@ import quickpub.proxy
8
8
  logger = logging.getLogger(__name__)
9
9
 
10
10
 
11
- def build(
12
- *,
13
- verbose: bool = True
14
- ) -> None:
11
+ def build(*, verbose: bool = True) -> None:
15
12
  """
16
13
  Build the package distribution.
17
-
14
+
18
15
  :param verbose: Whether to display verbose output
19
16
  """
20
17
  logger.info("Starting build process")
@@ -25,24 +22,18 @@ def build(
25
22
  ret, stdout, stderr = quickpub.proxy.cm("python", "setup.py", "sdist")
26
23
 
27
24
  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")
25
+ logger.error(
26
+ "Build failed with return code %d: %s", ret, stderr.decode(encoding="utf8")
32
27
  )
28
+ exit_if(ret != 0, stderr.decode(encoding="utf8"))
33
29
 
34
30
  logger.info("Build completed successfully")
35
31
 
36
32
 
37
- def upload(
38
- *,
39
- name: str,
40
- version: Version,
41
- verbose: bool = True
42
- ) -> None:
33
+ def upload(*, name: str, version: Version, verbose: bool = True) -> None:
43
34
  """
44
35
  Upload the package to PyPI.
45
-
36
+
46
37
  :param name: Package name
47
38
  :param version: Package version
48
39
  :param verbose: Whether to display verbose output
@@ -52,27 +43,26 @@ def upload(
52
43
  info("Uploading")
53
44
  logger.info("Uploading package to PyPI")
54
45
 
55
- ret, stdout, stderr = quickpub.proxy.cm("twine", "upload", "--config-file", ".pypirc",
56
- f"dist/{name}-{version}.tar.gz")
46
+ ret, stdout, stderr = quickpub.proxy.cm(
47
+ "twine", "upload", "--config-file", ".pypirc", f"dist/{name}-{version}.tar.gz"
48
+ )
57
49
 
58
50
  if ret != 0:
59
- logger.error("Upload failed with return code %d: %s", ret, stderr.decode(encoding='utf8'))
51
+ logger.error(
52
+ "Upload failed with return code %d: %s", ret, stderr.decode(encoding="utf8")
53
+ )
60
54
  exit_if(
61
55
  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"
56
+ 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
57
  )
64
58
 
65
59
  logger.info("Successfully uploaded package '%s' version '%s'", name, version)
66
60
 
67
61
 
68
- def commit(
69
- *,
70
- version: Version,
71
- verbose: bool = True
72
- ) -> None:
62
+ def commit(*, version: Version, verbose: bool = True) -> None:
73
63
  """
74
64
  Commit and push changes to Git repository.
75
-
65
+
76
66
  :param version: Package version
77
67
  :param verbose: Whether to display verbose output
78
68
  """
@@ -85,23 +75,27 @@ def commit(
85
75
 
86
76
  ret, stdout, stderr = quickpub.proxy.cm("git add .")
87
77
  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")
78
+ logger.error(
79
+ "Git add failed with return code %d: %s",
80
+ ret,
81
+ stderr.decode(encoding="utf8"),
92
82
  )
83
+ exit_if(ret != 0, stderr.decode(encoding="utf8"))
93
84
 
94
85
  if verbose:
95
86
  info("\tCommitting")
96
87
  logger.info("Committing changes with message 'updated to version %s'", version)
97
88
 
98
- ret, stdout, stderr = quickpub.proxy.cm(f"git commit -m \"updated to version {version}\"")
89
+ ret, stdout, stderr = quickpub.proxy.cm(
90
+ f'git commit -m "updated to version {version}"'
91
+ )
99
92
  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")
93
+ logger.error(
94
+ "Git commit failed with return code %d: %s",
95
+ ret,
96
+ stderr.decode(encoding="utf8"),
104
97
  )
98
+ exit_if(ret != 0, stderr.decode(encoding="utf8"))
105
99
 
106
100
  if verbose:
107
101
  info("\tPushing")
@@ -109,11 +103,12 @@ def commit(
109
103
 
110
104
  ret, stdout, stderr = quickpub.proxy.cm("git push")
111
105
  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")
106
+ logger.error(
107
+ "Git push failed with return code %d: %s",
108
+ ret,
109
+ stderr.decode(encoding="utf8"),
116
110
  )
111
+ exit_if(ret != 0, stderr.decode(encoding="utf8"))
117
112
 
118
113
  logger.info("Successfully committed and pushed version '%s'", version)
119
114
 
@@ -11,7 +11,7 @@ class QuickpubLogFilter(logging.Filter):
11
11
  """
12
12
 
13
13
  def filter(self, record):
14
- return record.name.startswith('quickpub')
14
+ return record.name.startswith("quickpub")
15
15
 
16
16
 
17
17
  class TqdmLoggingHandler(logging.Handler):
@@ -26,6 +26,7 @@ class TqdmLoggingHandler(logging.Handler):
26
26
  def emit(self, record):
27
27
  try:
28
28
  import tqdm
29
+
29
30
  msg = self.format(record)
30
31
  tqdm.tqdm.write(msg, file=sys.stdout)
31
32
  except ImportError:
@@ -63,7 +64,7 @@ def setup_logging(level: int = None):
63
64
  # Common formatter for both handlers
64
65
  # Example output: 2024-01-15 10:30:45,123 - INFO - [quickpub.some_module - some_module.py:42] - This is a log message
65
66
  formatter = logging.Formatter(
66
- '%(asctime)s - %(levelname)s - [%(name)s - %(filename)s:%(lineno)d] - %(message)s'
67
+ "%(asctime)s - %(levelname)s - [%(name)s - %(filename)s:%(lineno)d] - %(message)s"
67
68
  )
68
69
 
69
70
  try:
@@ -104,8 +105,4 @@ def set_log_level(level: int):
104
105
  handler.setLevel(level)
105
106
 
106
107
 
107
- __all__ = [
108
- "setup_logging",
109
- "set_log_level",
110
- "QuickpubLogFilter"
111
- ]
108
+ __all__ = ["setup_logging", "set_log_level", "QuickpubLogFilter"]
@@ -11,12 +11,12 @@ logger = logging.getLogger(__name__)
11
11
  def cm(*args, **kwargs) -> Tuple[int, bytes, bytes]:
12
12
  """
13
13
  Execute a command and return the result.
14
-
14
+
15
15
  :param args: Command arguments
16
16
  :param kwargs: Additional keyword arguments
17
17
  :return: Tuple of (return_code, stdout, stderr)
18
18
  """
19
- logger.debug("Executing command: %s", ' '.join(args))
19
+ logger.debug("Executing command: %s", " ".join(args))
20
20
  result = danielutils.cm(*args, **kwargs)
21
21
  logger.debug("Command completed with return code: %d", result[0])
22
22
  return result
@@ -25,7 +25,7 @@ def cm(*args, **kwargs) -> Tuple[int, bytes, bytes]:
25
25
  def os_system(command) -> int:
26
26
  """
27
27
  Execute a system command.
28
-
28
+
29
29
  :param command: Command to execute
30
30
  :return: Return code of the command
31
31
  """
@@ -38,19 +38,19 @@ def os_system(command) -> int:
38
38
  def get(*args, **kwargs) -> requests.models.Response:
39
39
  """
40
40
  Make an HTTP GET request.
41
-
41
+
42
42
  :param args: Request arguments
43
43
  :param kwargs: Additional keyword arguments
44
44
  :return: Response object
45
45
  """
46
- logger.debug("Making HTTP GET request to: %s", args[0] if args else 'URL not provided')
46
+ logger.debug(
47
+ "Making HTTP GET request to: %s", args[0] if args else "URL not provided"
48
+ )
47
49
  response = requests.get(*args, **kwargs)
48
- logger.debug("HTTP GET request completed with status code: %d", response.status_code)
50
+ logger.debug(
51
+ "HTTP GET request completed with status code: %d", response.status_code
52
+ )
49
53
  return response
50
54
 
51
55
 
52
- __all__ = [
53
- "cm",
54
- 'os_system',
55
- "get"
56
- ]
56
+ __all__ = ["cm", "os_system", "get"]