winipedia-utils 0.4.34__tar.gz → 0.4.38__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.

Potentially problematic release.


This version of winipedia-utils might be problematic. Click here for more details.

Files changed (96) hide show
  1. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/PKG-INFO +1 -1
  2. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/pyproject.toml +1 -1
  3. winipedia_utils-0.4.38/winipedia_utils/git/github/github.py +31 -0
  4. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/repo/protect.py +1 -1
  5. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/projects/poetry/config.py +66 -16
  6. winipedia_utils-0.4.38/winipedia_utils/projects/poetry/poetry.py +129 -0
  7. winipedia_utils-0.4.38/winipedia_utils/testing/skip.py +19 -0
  8. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/utils/utils.py +0 -23
  9. winipedia_utils-0.4.34/winipedia_utils/projects/poetry/poetry.py +0 -42
  10. winipedia_utils-0.4.34/winipedia_utils/testing/skip.py +0 -10
  11. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/LICENSE +0 -0
  12. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/README.md +0 -0
  13. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/__init__.py +0 -0
  14. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/concurrent/__init__.py +0 -0
  15. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/concurrent/concurrent.py +0 -0
  16. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/concurrent/multiprocessing.py +0 -0
  17. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/concurrent/multithreading.py +0 -0
  18. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/data/__init__.py +0 -0
  19. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/data/dataframe/__init__.py +0 -0
  20. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/data/dataframe/cleaning.py +0 -0
  21. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/data/structures/__init__.py +0 -0
  22. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/data/structures/dicts.py +0 -0
  23. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/__init__.py +0 -0
  24. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/__init__.py +0 -0
  25. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/repo/__init__.py +0 -0
  26. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/repo/repo.py +0 -0
  27. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/workflows/__init__.py +0 -0
  28. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/workflows/base/__init__.py +0 -0
  29. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/workflows/base/base.py +0 -0
  30. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/workflows/health_check.py +0 -0
  31. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/workflows/publish.py +0 -0
  32. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/github/workflows/release.py +0 -0
  33. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/gitignore/__init__.py +0 -0
  34. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/gitignore/config.py +0 -0
  35. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/gitignore/gitignore.py +0 -0
  36. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/pre_commit/__init__.py +0 -0
  37. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/pre_commit/config.py +0 -0
  38. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/pre_commit/hooks.py +0 -0
  39. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/git/pre_commit/run_hooks.py +0 -0
  40. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/iterating/__init__.py +0 -0
  41. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/iterating/iterate.py +0 -0
  42. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/logging/__init__.py +0 -0
  43. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/logging/ansi.py +0 -0
  44. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/logging/config.py +0 -0
  45. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/logging/logger.py +0 -0
  46. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/modules/__init__.py +0 -0
  47. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/modules/class_.py +0 -0
  48. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/modules/function.py +0 -0
  49. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/modules/module.py +0 -0
  50. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/modules/package.py +0 -0
  51. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/oop/__init__.py +0 -0
  52. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/oop/mixins/__init__.py +0 -0
  53. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/oop/mixins/meta.py +0 -0
  54. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/oop/mixins/mixin.py +0 -0
  55. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/os/__init__.py +0 -0
  56. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/os/os.py +0 -0
  57. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/projects/__init__.py +0 -0
  58. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/projects/poetry/__init__.py +0 -0
  59. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/projects/project.py +0 -0
  60. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/py.typed +0 -0
  61. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/__init__.py +0 -0
  62. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/__init__.py +0 -0
  63. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/delete_garbage_can.svg +0 -0
  64. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/download_arrow.svg +0 -0
  65. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/exit_fullscreen_icon.svg +0 -0
  66. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/fullscreen_icon.svg +0 -0
  67. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/menu_icon.svg +0 -0
  68. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/pause_icon.svg +0 -0
  69. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/play_icon.svg +0 -0
  70. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/plus_icon.svg +0 -0
  71. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/resources/svgs/svg.py +0 -0
  72. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/security/__init__.py +0 -0
  73. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/security/cryptography.py +0 -0
  74. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/security/keyring.py +0 -0
  75. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/setup.py +0 -0
  76. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/__init__.py +0 -0
  77. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/assertions.py +0 -0
  78. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/config.py +0 -0
  79. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/convention.py +0 -0
  80. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/create_tests.py +0 -0
  81. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/fixtures.py +0 -0
  82. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/__init__.py +0 -0
  83. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/__init__.py +0 -0
  84. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -0
  85. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/fixture.py +0 -0
  86. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -0
  87. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/scopes/class_.py +0 -0
  88. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/scopes/function.py +0 -0
  89. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/scopes/module.py +0 -0
  90. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/scopes/package.py +0 -0
  91. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/fixtures/scopes/session.py +0 -0
  92. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/base/utils/__init__.py +0 -0
  93. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/testing/tests/conftest.py +0 -0
  94. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/text/__init__.py +0 -0
  95. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/text/config.py +0 -0
  96. {winipedia_utils-0.4.34 → winipedia_utils-0.4.38}/winipedia_utils/text/string.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: winipedia-utils
3
- Version: 0.4.34
3
+ Version: 0.4.38
4
4
  Summary: A package with many utility functions
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -1,7 +1,7 @@
1
1
  # Project section
2
2
  [project]
3
3
  name = "winipedia-utils"
4
- version = "0.4.34"
4
+ version = "0.4.38"
5
5
  description = "A package with many utility functions"
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.12"
@@ -0,0 +1,31 @@
1
+ """GitHub utilities for working with GitHub repositories."""
2
+
3
+ import os
4
+
5
+ from winipedia_utils.text.config import DotEnvConfigFile
6
+
7
+
8
+ def get_github_repo_token() -> str:
9
+ """Get the GitHub token."""
10
+ # try os env first
11
+ token = os.getenv("REPO_TOKEN")
12
+ if token:
13
+ return token
14
+
15
+ # try .env next
16
+ dotenv_path = DotEnvConfigFile.get_path()
17
+ if not dotenv_path.exists():
18
+ msg = f"Expected {dotenv_path} to exist"
19
+ raise ValueError(msg)
20
+ dotenv = DotEnvConfigFile.load()
21
+ token = dotenv.get("REPO_TOKEN")
22
+ if token:
23
+ return token
24
+
25
+ msg = f"Expected REPO_TOKEN in {dotenv_path}"
26
+ raise ValueError(msg)
27
+
28
+
29
+ def running_in_github_action() -> bool:
30
+ """Check if we are running in a GitHub action."""
31
+ return os.getenv("GITHUB_ACTIONS", "false") == "true"
@@ -2,6 +2,7 @@
2
2
 
3
3
  from typing import Any
4
4
 
5
+ from winipedia_utils.git.github.github import get_github_repo_token
5
6
  from winipedia_utils.git.github.repo.repo import (
6
7
  DEFAULT_BRANCH,
7
8
  DEFAULT_RULESET_NAME,
@@ -12,7 +13,6 @@ from winipedia_utils.git.github.repo.repo import (
12
13
  from winipedia_utils.git.github.workflows.health_check import HealthCheckWorkflow
13
14
  from winipedia_utils.modules.package import get_src_package
14
15
  from winipedia_utils.projects.poetry.config import PyprojectConfigFile
15
- from winipedia_utils.testing.tests.base.utils.utils import get_github_repo_token
16
16
 
17
17
 
18
18
  def protect_repository() -> None:
@@ -3,10 +3,8 @@
3
3
  from pathlib import Path
4
4
  from typing import Any, cast
5
5
 
6
- from packaging.specifiers import SpecifierSet
7
- from packaging.version import Version
8
-
9
6
  from winipedia_utils.modules.package import get_src_package, make_name_from_package
7
+ from winipedia_utils.projects.poetry.poetry import VersionConstraint
10
8
  from winipedia_utils.testing.convention import TESTS_PACKAGE_NAME
11
9
  from winipedia_utils.text.config import ConfigFile, TomlConfigFile
12
10
 
@@ -137,19 +135,30 @@ class PyprojectConfigFile(TomlConfigFile):
137
135
  def get_latest_possible_python_version(cls) -> str:
138
136
  """Get the latest possible python version."""
139
137
  constraint = cls.load()["project"]["requires-python"]
140
- spec = constraint.strip().strip('"').strip("'")
141
- sset = SpecifierSet(spec)
142
- # find upper bound specifiers
143
- uppers = [Version(sp.version) for sp in sset if sp.operator in ("<", "<=")]
144
- if uppers:
145
- top = max(uppers)
146
- # if strict "<", we might treat it as “one less” in minor
147
- if any(sp.operator == "<" and Version(sp.version) == top for sp in sset):
148
- # subtract one minor
149
- return f"{top.major}.{top.minor - 1}"
150
- return f"{top.major}.{top.minor}"
151
- # no upper bound “3.x”
152
- return "3.x"
138
+ version_constraint = VersionConstraint(constraint)
139
+ upper = version_constraint.get_upper_exclusive()
140
+ if upper is None:
141
+ return "3.x"
142
+
143
+ # convert to inclusive
144
+ if upper.micro != 0:
145
+ micro = upper.micro - 1
146
+ return f"{upper.major}.{upper.minor}" + (f".{micro}" if micro != 0 else "")
147
+ if upper.minor != 0:
148
+ minor = upper.minor - 1
149
+ return f"{upper.major}" + (f".{minor}" if minor != 0 else "")
150
+ return f"{upper.major - 1}.x"
151
+
152
+ @classmethod
153
+ def get_first_supported_python_version(cls) -> str:
154
+ """Get the first supported python version."""
155
+ constraint = cls.load()["project"]["requires-python"]
156
+ version_constraint = VersionConstraint(constraint)
157
+ lower = version_constraint.get_lower_inclusive()
158
+ if lower is None:
159
+ msg = "Need a lower bound for python version"
160
+ raise ValueError(msg)
161
+ return str(lower)
153
162
 
154
163
 
155
164
  class TypedConfigFile(ConfigFile):
@@ -185,3 +194,44 @@ class PyTypedConfigFile(ConfigFile):
185
194
  def get_parent_path(cls) -> Path:
186
195
  """Get the path to the config file."""
187
196
  return Path(PyprojectConfigFile.get_package_name())
197
+
198
+
199
+ class DotPythonVersionConfigFile(ConfigFile):
200
+ """Config file for .python-version."""
201
+
202
+ VERSION_KEY = "version"
203
+
204
+ @classmethod
205
+ def get_filename(cls) -> str:
206
+ """Get the filename of the config file."""
207
+ return "" # so it builds the path .python-version
208
+
209
+ @classmethod
210
+ def get_file_extension(cls) -> str:
211
+ """Get the file extension of the config file."""
212
+ return "python-version"
213
+
214
+ @classmethod
215
+ def get_parent_path(cls) -> Path:
216
+ """Get the path to the config file."""
217
+ return Path()
218
+
219
+ @classmethod
220
+ def get_configs(cls) -> dict[str, Any]:
221
+ """Get the config."""
222
+ return {
223
+ cls.VERSION_KEY: PyprojectConfigFile.get_first_supported_python_version()
224
+ }
225
+
226
+ @classmethod
227
+ def load(cls) -> dict[str, Any]:
228
+ """Load the config file."""
229
+ return {cls.VERSION_KEY: cls.get_path().read_text()}
230
+
231
+ @classmethod
232
+ def dump(cls, config: dict[str, Any] | list[Any]) -> None:
233
+ """Dump the config file."""
234
+ if not isinstance(config, dict):
235
+ msg = f"Cannot dump {config} to .python-version file."
236
+ raise TypeError(msg)
237
+ cls.get_path().write_text(config[cls.VERSION_KEY])
@@ -0,0 +1,129 @@
1
+ """Project utilities for introspection and manipulation.
2
+
3
+ This module provides utility functions for working with Python projects
4
+ """
5
+
6
+ from collections.abc import Iterable
7
+ from types import ModuleType
8
+
9
+ from packaging.specifiers import SpecifierSet
10
+ from packaging.version import Version
11
+
12
+ from winipedia_utils.logging.logger import get_logger
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ POETRY_ARG = "poetry"
18
+
19
+ POETRY_RUN_ARGS = [POETRY_ARG, "run"]
20
+
21
+ RUN_PYTHON_MODULE_ARGS = ["python", "-m"]
22
+
23
+
24
+ def get_script_from_args(args: Iterable[str]) -> str:
25
+ """Get the script from args."""
26
+ return " ".join(args)
27
+
28
+
29
+ def get_run_python_module_args(module: ModuleType) -> list[str]:
30
+ """Get the args to run a module."""
31
+ from winipedia_utils.modules.module import ( # noqa: PLC0415 # avoid circular import
32
+ make_obj_importpath,
33
+ )
34
+
35
+ return [*RUN_PYTHON_MODULE_ARGS, make_obj_importpath(module)]
36
+
37
+
38
+ def get_python_module_script(module: ModuleType) -> str:
39
+ """Get the script to run a module."""
40
+ return get_script_from_args(get_run_python_module_args(module))
41
+
42
+
43
+ def get_poetry_run_module_script(module: ModuleType) -> str:
44
+ """Get the script to run a module."""
45
+ return get_script_from_args([*POETRY_RUN_ARGS, *get_run_python_module_args(module)])
46
+
47
+
48
+ class VersionConstraint:
49
+ """Version class."""
50
+
51
+ def __init__(self, constraint: str) -> None:
52
+ """Initialize the version."""
53
+ self.constraint = constraint
54
+ self.spec = self.constraint.strip().strip('"').strip("'")
55
+ self.sset = SpecifierSet(self.spec)
56
+
57
+ self.lowers_inclusive = [
58
+ Version(s.version) for s in self.sset if s.operator == ">="
59
+ ]
60
+ self.lowers_exclusive = [
61
+ Version(s.version) for s in self.sset if s.operator == ">"
62
+ ]
63
+ # increment the last number of exclusive, so
64
+ # >3.4.1 to >=3.4.2; <3.4.0 to <=3.4.1; 3.0.0 to <=3.0.1
65
+ self.lowers_exclusive_to_inclusive = [
66
+ Version(f"{v.major}.{v.minor}.{v.micro + 1}") for v in self.lowers_exclusive
67
+ ]
68
+ self.lowers_inclusive = (
69
+ self.lowers_inclusive + self.lowers_exclusive_to_inclusive
70
+ )
71
+
72
+ self.uppers_inclusive = [
73
+ Version(s.version) for s in self.sset if s.operator == "<="
74
+ ]
75
+ self.uppers_exclusive = [
76
+ Version(s.version) for s in self.sset if s.operator == "<"
77
+ ]
78
+
79
+ # increment the last number of inclusive, so
80
+ # <=3.4.1 to <3.4.2; >=3.4.0 to >3.4.1; 3.0.0 to >3.0.1
81
+ self.uppers_inclusive_to_exclusive = [
82
+ Version(f"{v.major}.{v.minor}.{v.micro + 1}") for v in self.uppers_inclusive
83
+ ]
84
+ self.uppers_exclusive = (
85
+ self.uppers_inclusive_to_exclusive + self.uppers_exclusive
86
+ )
87
+
88
+ self.upper_exclusive = (
89
+ min(self.uppers_exclusive) if self.uppers_exclusive else None
90
+ )
91
+ self.lower_inclusive = (
92
+ max(self.lowers_inclusive) if self.lowers_inclusive else None
93
+ )
94
+
95
+ def get_lower_inclusive(self, default: str | None = None) -> Version | None:
96
+ """Get the minimum version.
97
+
98
+ Is given inclusive. E.g. >=3.8, <3.12 -> 3.8
99
+ if >3.7, <3.12 -> 3.7.1
100
+
101
+ E.g. >=3.8, <3.12 -> 3.8
102
+
103
+ Args:
104
+ default: The default value to return if there is no minimum version
105
+
106
+ Returns:
107
+ The minimum version
108
+ """
109
+ if self.lower_inclusive is None:
110
+ return Version(default) if default else None
111
+
112
+ return self.lower_inclusive
113
+
114
+ def get_upper_exclusive(self, default: str | None = None) -> Version | None:
115
+ """Get the maximum version.
116
+
117
+ Is given exclusive. E.g. >=3.8, <3.12 -> 3.12
118
+ if >=3.8, <=3.12 -> 3.12.1
119
+
120
+ Args:
121
+ default: The default value to return if there is no maximum version
122
+
123
+ Returns:
124
+ The maximum version
125
+ """
126
+ if self.upper_exclusive is None:
127
+ return Version(default) if default else None
128
+
129
+ return self.upper_exclusive
@@ -0,0 +1,19 @@
1
+ """Has utils towards skipping tests."""
2
+
3
+ import functools
4
+
5
+ import pytest
6
+
7
+ from winipedia_utils.git.github.github import running_in_github_action
8
+
9
+ skip_fixture_test: pytest.MarkDecorator = functools.partial(
10
+ pytest.mark.skip,
11
+ reason="Fixtures are not testable bc they cannot be called directly.",
12
+ )()
13
+
14
+
15
+ skip_in_github_actions: pytest.MarkDecorator = functools.partial(
16
+ pytest.mark.skipif,
17
+ running_in_github_action(),
18
+ reason="Test cannot run in GitHub action.",
19
+ )()
@@ -9,7 +9,6 @@ Returns:
9
9
 
10
10
  """
11
11
 
12
- import os
13
12
  from collections.abc import Callable
14
13
  from types import ModuleType
15
14
  from typing import Any
@@ -26,7 +25,6 @@ from winipedia_utils.testing.convention import (
26
25
  make_test_obj_importpath_from_obj,
27
26
  make_untested_summary_error_msg,
28
27
  )
29
- from winipedia_utils.text.config import DotEnvConfigFile
30
28
 
31
29
  logger = get_logger(__name__)
32
30
 
@@ -81,24 +79,3 @@ def assert_isabstrct_method(method: Any) -> None:
81
79
  is_abstractmethod(method),
82
80
  f"Expected {method} to be abstract method",
83
81
  )
84
-
85
-
86
- def get_github_repo_token() -> str:
87
- """Get the GitHub token."""
88
- # try os env first
89
- token = os.getenv("REPO_TOKEN")
90
- if token:
91
- return token
92
-
93
- # try .env next
94
- dotenv_path = DotEnvConfigFile.get_path()
95
- if not dotenv_path.exists():
96
- msg = f"Expected {dotenv_path} to exist"
97
- raise ValueError(msg)
98
- dotenv = DotEnvConfigFile.load()
99
- token = dotenv.get("REPO_TOKEN")
100
- if token:
101
- return token
102
-
103
- msg = f"Expected REPO_TOKEN in {dotenv_path}"
104
- raise ValueError(msg)
@@ -1,42 +0,0 @@
1
- """Project utilities for introspection and manipulation.
2
-
3
- This module provides utility functions for working with Python projects
4
- """
5
-
6
- from collections.abc import Iterable
7
- from types import ModuleType
8
-
9
- from winipedia_utils.logging.logger import get_logger
10
-
11
- logger = get_logger(__name__)
12
-
13
-
14
- POETRY_ARG = "poetry"
15
-
16
- POETRY_RUN_ARGS = [POETRY_ARG, "run"]
17
-
18
- RUN_PYTHON_MODULE_ARGS = ["python", "-m"]
19
-
20
-
21
- def get_script_from_args(args: Iterable[str]) -> str:
22
- """Get the script from args."""
23
- return " ".join(args)
24
-
25
-
26
- def get_run_python_module_args(module: ModuleType) -> list[str]:
27
- """Get the args to run a module."""
28
- from winipedia_utils.modules.module import ( # noqa: PLC0415 # avoid circular import
29
- make_obj_importpath,
30
- )
31
-
32
- return [*RUN_PYTHON_MODULE_ARGS, make_obj_importpath(module)]
33
-
34
-
35
- def get_python_module_script(module: ModuleType) -> str:
36
- """Get the script to run a module."""
37
- return get_script_from_args(get_run_python_module_args(module))
38
-
39
-
40
- def get_poetry_run_module_script(module: ModuleType) -> str:
41
- """Get the script to run a module."""
42
- return get_script_from_args([*POETRY_RUN_ARGS, *get_run_python_module_args(module)])
@@ -1,10 +0,0 @@
1
- """Has utils towards skipping tests."""
2
-
3
- import functools
4
-
5
- import pytest
6
-
7
- skip_fixture_test: pytest.MarkDecorator = functools.partial(
8
- pytest.mark.skip,
9
- reason="Fixtures are not testable bc they cannot be called directly.",
10
- )()