winipedia-utils 0.4.43__py3-none-any.whl → 0.7.1__py3-none-any.whl
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.
- winipedia_utils/artifacts/build.py +27 -0
- winipedia_utils/dev/artifacts/build.py +62 -0
- winipedia_utils/{text → dev/configs/base}/config.py +16 -11
- winipedia_utils/{git/gitignore/config.py → dev/configs/gitignore.py} +2 -2
- winipedia_utils/{git/pre_commit/config.py → dev/configs/pre_commit.py} +6 -6
- winipedia_utils/{projects/poetry/config.py → dev/configs/pyproject.py} +120 -32
- winipedia_utils/{testing/config.py → dev/configs/testing.py} +7 -4
- winipedia_utils/dev/configs/workflows/base/base.py +907 -0
- winipedia_utils/dev/configs/workflows/health_check.py +69 -0
- winipedia_utils/dev/configs/workflows/publish.py +51 -0
- winipedia_utils/dev/configs/workflows/release.py +91 -0
- winipedia_utils/dev/git/github/repo/__init__.py +1 -0
- winipedia_utils/{git → dev/git}/github/repo/protect.py +5 -5
- winipedia_utils/dev/git/pre_commit/hooks.py +85 -0
- winipedia_utils/{git → dev/git}/pre_commit/run_hooks.py +23 -13
- winipedia_utils/dev/projects/poetry/dev_deps.py +21 -0
- winipedia_utils/dev/projects/poetry/poetry.py +248 -0
- winipedia_utils/{projects → dev/projects}/project.py +6 -7
- winipedia_utils/dev/testing/__init__.py +1 -0
- winipedia_utils/{testing → dev/testing}/convention.py +1 -1
- winipedia_utils/{testing → dev/testing}/create_tests.py +14 -14
- winipedia_utils/dev/testing/tests/__init__.py +1 -0
- winipedia_utils/dev/testing/tests/base/__init__.py +1 -0
- winipedia_utils/dev/testing/tests/base/fixtures/__init__.py +1 -0
- winipedia_utils/{testing → dev/testing}/tests/base/fixtures/fixture.py +1 -1
- winipedia_utils/dev/testing/tests/base/fixtures/scopes/__init__.py +1 -0
- winipedia_utils/{testing → dev/testing}/tests/base/fixtures/scopes/class_.py +2 -2
- winipedia_utils/{testing → dev/testing}/tests/base/fixtures/scopes/module.py +2 -2
- winipedia_utils/{testing → dev/testing}/tests/base/fixtures/scopes/session.py +10 -10
- winipedia_utils/dev/testing/tests/base/utils/__init__.py +1 -0
- winipedia_utils/dev/testing/tests/base/utils/utils.py +1 -0
- winipedia_utils/{testing → dev/testing}/tests/conftest.py +2 -2
- winipedia_utils/{testing/tests/base/utils → dev/testing}/utils.py +7 -24
- winipedia_utils/setup.py +9 -5
- winipedia_utils/utils/__init__.py +1 -0
- winipedia_utils/utils/data/dataframe/__init__.py +1 -0
- winipedia_utils/{data → utils/data}/dataframe/cleaning.py +1 -1
- winipedia_utils/utils/data/structures/__init__.py +1 -0
- winipedia_utils/{text → utils/data/structures/text}/string.py +36 -3
- winipedia_utils/utils/git/__init__.py +1 -0
- winipedia_utils/utils/git/github/__init__.py +1 -0
- winipedia_utils/{git → utils/git}/github/github.py +1 -1
- winipedia_utils/utils/git/github/repo/__init__.py +1 -0
- winipedia_utils/{git → utils/git}/github/repo/repo.py +1 -1
- winipedia_utils/{git → utils/git}/gitignore/gitignore.py +2 -2
- winipedia_utils/{concurrent → utils/iterating/concurrent}/concurrent.py +4 -4
- winipedia_utils/{concurrent → utils/iterating/concurrent}/multiprocessing.py +2 -2
- winipedia_utils/{concurrent → utils/iterating/concurrent}/multithreading.py +1 -1
- winipedia_utils/{logging → utils/logging}/logger.py +1 -1
- winipedia_utils/{modules → utils/modules}/class_.py +15 -8
- winipedia_utils/{modules → utils/modules}/function.py +10 -4
- winipedia_utils/utils/modules/inspection.py +56 -0
- winipedia_utils/{modules → utils/modules}/module.py +27 -32
- winipedia_utils/{modules → utils/modules}/package.py +100 -34
- winipedia_utils/{oop → utils/oop}/mixins/meta.py +4 -4
- winipedia_utils/{oop → utils/oop}/mixins/mixin.py +2 -2
- winipedia_utils/{os → utils/os}/os.py +2 -2
- winipedia_utils/utils/resources/__init__.py +1 -0
- winipedia_utils/utils/resources/svgs/__init__.py +1 -0
- winipedia_utils/{resources → utils/resources}/svgs/svg.py +1 -1
- winipedia_utils/utils/testing/__init__.py +1 -0
- winipedia_utils/{testing → utils/testing}/assertions.py +18 -0
- winipedia_utils/{testing → utils/testing}/skip.py +1 -1
- {winipedia_utils-0.4.43.dist-info → winipedia_utils-0.7.1.dist-info}/METADATA +71 -36
- winipedia_utils-0.7.1.dist-info/RECORD +109 -0
- winipedia_utils/git/github/workflows/base/base.py +0 -294
- winipedia_utils/git/github/workflows/health_check.py +0 -57
- winipedia_utils/git/github/workflows/publish.py +0 -49
- winipedia_utils/git/github/workflows/release.py +0 -45
- winipedia_utils/git/pre_commit/hooks.py +0 -147
- winipedia_utils/projects/poetry/poetry.py +0 -129
- winipedia_utils/testing/__init__.py +0 -1
- winipedia_utils/testing/tests/__init__.py +0 -1
- winipedia_utils/testing/tests/base/__init__.py +0 -1
- winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -1
- winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -1
- winipedia_utils/testing/tests/base/utils/__init__.py +0 -1
- winipedia_utils-0.4.43.dist-info/RECORD +0 -94
- /winipedia_utils/{data/dataframe → artifacts}/__init__.py +0 -0
- /winipedia_utils/{data/structures → dev}/__init__.py +0 -0
- /winipedia_utils/{git/github → dev/artifacts}/__init__.py +0 -0
- /winipedia_utils/{git/github/repo → dev/configs}/__init__.py +0 -0
- /winipedia_utils/{git/github/workflows → dev/configs}/base/__init__.py +0 -0
- /winipedia_utils/{git/github → dev/configs}/workflows/__init__.py +0 -0
- /winipedia_utils/{resources → dev/configs/workflows/base}/__init__.py +0 -0
- /winipedia_utils/{git → dev/git}/__init__.py +0 -0
- /winipedia_utils/{resources/svgs → dev/git/github}/__init__.py +0 -0
- /winipedia_utils/{git → dev/git}/pre_commit/__init__.py +0 -0
- /winipedia_utils/{projects → dev/projects}/__init__.py +0 -0
- /winipedia_utils/{projects → dev/projects}/poetry/__init__.py +0 -0
- /winipedia_utils/{testing → dev/testing}/tests/base/fixtures/scopes/function.py +0 -0
- /winipedia_utils/{testing → dev/testing}/tests/base/fixtures/scopes/package.py +0 -0
- /winipedia_utils/{data → utils/data}/__init__.py +0 -0
- /winipedia_utils/{data → utils/data}/structures/dicts.py +0 -0
- /winipedia_utils/{text → utils/data/structures/text}/__init__.py +0 -0
- /winipedia_utils/{git → utils/git}/gitignore/__init__.py +0 -0
- /winipedia_utils/{iterating → utils/iterating}/__init__.py +0 -0
- /winipedia_utils/{concurrent → utils/iterating/concurrent}/__init__.py +0 -0
- /winipedia_utils/{iterating → utils/iterating}/iterate.py +0 -0
- /winipedia_utils/{logging → utils/logging}/__init__.py +0 -0
- /winipedia_utils/{logging → utils/logging}/ansi.py +0 -0
- /winipedia_utils/{logging → utils/logging}/config.py +0 -0
- /winipedia_utils/{modules → utils/modules}/__init__.py +0 -0
- /winipedia_utils/{oop → utils/oop}/__init__.py +0 -0
- /winipedia_utils/{oop → utils/oop}/mixins/__init__.py +0 -0
- /winipedia_utils/{os → utils/os}/__init__.py +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/delete_garbage_can.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/download_arrow.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/exit_fullscreen_icon.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/fullscreen_icon.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/menu_icon.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/pause_icon.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/play_icon.svg +0 -0
- /winipedia_utils/{resources → utils/resources}/svgs/plus_icon.svg +0 -0
- /winipedia_utils/{security → utils/security}/__init__.py +0 -0
- /winipedia_utils/{security → utils/security}/cryptography.py +0 -0
- /winipedia_utils/{security → utils/security}/keyring.py +0 -0
- /winipedia_utils/{testing → utils/testing}/fixtures.py +0 -0
- {winipedia_utils-0.4.43.dist-info → winipedia_utils-0.7.1.dist-info}/WHEEL +0 -0
- {winipedia_utils-0.4.43.dist-info → winipedia_utils-0.7.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Build utilities for creating and managing project builds.
|
|
2
|
+
|
|
3
|
+
This module provides functions for building and managing project artifacts,
|
|
4
|
+
including creating build scripts, configuring build environments, and
|
|
5
|
+
handling build dependencies. These utilities help with the packaging and
|
|
6
|
+
distribution of project code.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from winipedia_utils.dev.artifacts.build import Build
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WinipediaUtilsBuild(Build):
|
|
15
|
+
"""Build script for winipedia_utils."""
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def get_artifacts(cls) -> list[Path]:
|
|
19
|
+
"""Build the project."""
|
|
20
|
+
paths = [cls.ARTIFACTS_PATH / "build.txt"]
|
|
21
|
+
for path in paths:
|
|
22
|
+
path.write_text("Hello World!")
|
|
23
|
+
return paths
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if __name__ == "__main__":
|
|
27
|
+
WinipediaUtilsBuild()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Build utilities for creating and managing project builds.
|
|
2
|
+
|
|
3
|
+
This module provides functions for building and managing project artifacts,
|
|
4
|
+
including creating build scripts, configuring build environments, and
|
|
5
|
+
handling build dependencies. These utilities help with the packaging and
|
|
6
|
+
distribution of project code.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import platform
|
|
10
|
+
from abc import abstractmethod
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from winipedia_utils.dev.configs.workflows.base.base import Workflow
|
|
14
|
+
from winipedia_utils.utils.oop.mixins.mixin import ABCLoggingMixin
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Build(ABCLoggingMixin):
|
|
18
|
+
"""Base class for build scripts.
|
|
19
|
+
|
|
20
|
+
Subclass this class and implement the get_artifacts method to create
|
|
21
|
+
a build script for your project. The build method will be called
|
|
22
|
+
automatically when the class is initialized. At the end of the file add
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
YourBuildClass()
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
ARTIFACTS_PATH = Workflow.ARTIFACTS_PATH
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def get_artifacts(cls) -> list[Path]:
|
|
32
|
+
"""Build the project.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
list[Path]: List of paths to the built artifacts
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def __init__(cls) -> None:
|
|
40
|
+
"""Initialize the build script."""
|
|
41
|
+
cls.build()
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def build(cls) -> None:
|
|
45
|
+
"""Build the project.
|
|
46
|
+
|
|
47
|
+
This method is called by the __init__ method.
|
|
48
|
+
It takes all the files and renames them with -platform.system()
|
|
49
|
+
and puts them in the artifacts folder.
|
|
50
|
+
"""
|
|
51
|
+
cls.ARTIFACTS_PATH.mkdir(parents=True, exist_ok=True)
|
|
52
|
+
artifacts = cls.get_artifacts()
|
|
53
|
+
for artifact in artifacts:
|
|
54
|
+
parent = artifact.parent
|
|
55
|
+
if parent != cls.ARTIFACTS_PATH:
|
|
56
|
+
msg = f"You must create {artifact} in {cls.ARTIFACTS_PATH}"
|
|
57
|
+
raise FileNotFoundError(msg)
|
|
58
|
+
|
|
59
|
+
# rename the files with -platform.system()
|
|
60
|
+
new_name = f"{artifact.stem}-{platform.system()}{artifact.suffix}"
|
|
61
|
+
new_path = cls.ARTIFACTS_PATH / new_name
|
|
62
|
+
artifact.rename(new_path)
|
|
@@ -9,14 +9,13 @@ import tomlkit
|
|
|
9
9
|
import yaml
|
|
10
10
|
from dotenv import dotenv_values
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
from winipedia_utils.modules.class_ import init_all_nonabstract_subclasses
|
|
15
|
-
from winipedia_utils.modules.package import get_src_package
|
|
16
|
-
from winipedia_utils.projects.poetry.poetry import (
|
|
17
|
-
get_python_module_script,
|
|
12
|
+
from winipedia_utils.dev.projects.poetry.poetry import (
|
|
13
|
+
get_poetry_run_module_script,
|
|
18
14
|
)
|
|
19
|
-
from winipedia_utils.text.string import split_on_uppercase
|
|
15
|
+
from winipedia_utils.utils.data.structures.text.string import split_on_uppercase
|
|
16
|
+
from winipedia_utils.utils.iterating.iterate import nested_structure_is_subset
|
|
17
|
+
from winipedia_utils.utils.modules.class_ import init_all_nonabstract_subclasses
|
|
18
|
+
from winipedia_utils.utils.modules.package import DependencyGraph, get_src_package
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
class ConfigFile(ABC):
|
|
@@ -149,15 +148,21 @@ class ConfigFile(ABC):
|
|
|
149
148
|
@classmethod
|
|
150
149
|
def init_config_files(cls) -> None:
|
|
151
150
|
"""Initialize all subclasses."""
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
pkgs_depending_on_winipedia_utils = (
|
|
152
|
+
DependencyGraph().get_all_depending_on_winipedia_utils(
|
|
153
|
+
include_winipedia_utils=True
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
pkgs_depending_on_winipedia_utils.add(get_src_package())
|
|
157
|
+
for pkg in pkgs_depending_on_winipedia_utils:
|
|
158
|
+
init_all_nonabstract_subclasses(cls, load_package_before=pkg)
|
|
154
159
|
|
|
155
160
|
@staticmethod
|
|
156
|
-
def
|
|
161
|
+
def get_poetry_run_setup_script() -> str:
|
|
157
162
|
"""Get the poetry run setup script."""
|
|
158
163
|
from winipedia_utils import setup # noqa: PLC0415 # avoid circular import
|
|
159
164
|
|
|
160
|
-
return
|
|
165
|
+
return get_poetry_run_module_script(setup)
|
|
161
166
|
|
|
162
167
|
|
|
163
168
|
class YamlConfigFile(ConfigFile):
|
|
@@ -5,8 +5,8 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
import requests
|
|
7
7
|
|
|
8
|
-
from winipedia_utils.
|
|
9
|
-
from winipedia_utils.
|
|
8
|
+
from winipedia_utils.dev.configs.base.config import ConfigFile, DotEnvConfigFile
|
|
9
|
+
from winipedia_utils.dev.configs.testing import ExperimentConfigFile
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class GitIgnoreConfigFile(ConfigFile):
|
|
@@ -4,10 +4,10 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
6
|
import winipedia_utils
|
|
7
|
-
from winipedia_utils.
|
|
8
|
-
from winipedia_utils.
|
|
9
|
-
from winipedia_utils.
|
|
10
|
-
from winipedia_utils.
|
|
7
|
+
from winipedia_utils.dev.configs.base.config import YamlConfigFile
|
|
8
|
+
from winipedia_utils.utils.data.structures.text.string import make_name_from_obj
|
|
9
|
+
from winipedia_utils.utils.logging.logger import get_logger
|
|
10
|
+
from winipedia_utils.utils.os.os import run_subprocess
|
|
11
11
|
|
|
12
12
|
logger = get_logger(__name__)
|
|
13
13
|
|
|
@@ -29,7 +29,7 @@ class PreCommitConfigConfigFile(YamlConfigFile):
|
|
|
29
29
|
@classmethod
|
|
30
30
|
def get_configs(cls) -> dict[str, Any]:
|
|
31
31
|
"""Get the config."""
|
|
32
|
-
hook_name =
|
|
32
|
+
hook_name = make_name_from_obj(winipedia_utils, capitalize=False)
|
|
33
33
|
return {
|
|
34
34
|
"repos": [
|
|
35
35
|
{
|
|
@@ -38,7 +38,7 @@ class PreCommitConfigConfigFile(YamlConfigFile):
|
|
|
38
38
|
{
|
|
39
39
|
"id": hook_name,
|
|
40
40
|
"name": hook_name,
|
|
41
|
-
"entry": cls.
|
|
41
|
+
"entry": cls.get_poetry_run_setup_script(),
|
|
42
42
|
"language": "system",
|
|
43
43
|
"always_run": True,
|
|
44
44
|
"pass_filenames": False,
|
|
@@ -1,30 +1,62 @@
|
|
|
1
1
|
"""Config utilities for poetry and pyproject.toml."""
|
|
2
2
|
|
|
3
|
+
from functools import cache
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Any, cast
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
from
|
|
8
|
-
|
|
9
|
-
from winipedia_utils.
|
|
7
|
+
import requests
|
|
8
|
+
from packaging.version import Version
|
|
9
|
+
|
|
10
|
+
from winipedia_utils.dev.configs.base.config import ConfigFile, TomlConfigFile
|
|
11
|
+
from winipedia_utils.dev.configs.testing import ExperimentConfigFile
|
|
12
|
+
from winipedia_utils.dev.projects.poetry.dev_deps import DEV_DEPENDENCIES
|
|
13
|
+
from winipedia_utils.dev.projects.poetry.poetry import POETRY_ARG, VersionConstraint
|
|
14
|
+
from winipedia_utils.dev.testing.convention import TESTS_PACKAGE_NAME
|
|
15
|
+
from winipedia_utils.utils.data.structures.text.string import make_name_from_obj
|
|
16
|
+
from winipedia_utils.utils.os.os import run_subprocess
|
|
10
17
|
|
|
11
18
|
|
|
12
19
|
class PyprojectConfigFile(TomlConfigFile):
|
|
13
20
|
"""Config file for pyproject.toml."""
|
|
14
21
|
|
|
22
|
+
@classmethod
|
|
23
|
+
def dump(cls, config: dict[str, Any] | list[Any]) -> None:
|
|
24
|
+
"""Dump the config file.
|
|
25
|
+
|
|
26
|
+
We remove the wrong dependencies from the config before dumping.
|
|
27
|
+
So we do not want dependencies under tool.poetry.dependencies but
|
|
28
|
+
under project.dependencies. And we do not want dev dependencies under
|
|
29
|
+
tool.poetry.dev-dependencies but under tool.poetry.group.dev.dependencies.
|
|
30
|
+
"""
|
|
31
|
+
if not isinstance(config, dict):
|
|
32
|
+
msg = f"Cannot dump {config} to pyproject.toml file."
|
|
33
|
+
raise TypeError(msg)
|
|
34
|
+
config = cls.remove_wrong_dependencies(config)
|
|
35
|
+
super().dump(config)
|
|
36
|
+
|
|
15
37
|
@classmethod
|
|
16
38
|
def get_parent_path(cls) -> Path:
|
|
17
39
|
"""Get the path to the config file."""
|
|
18
40
|
return Path()
|
|
19
41
|
|
|
42
|
+
@classmethod
|
|
43
|
+
def get_repository_name(cls) -> str:
|
|
44
|
+
"""Get the repository name.
|
|
45
|
+
|
|
46
|
+
Is the parent folder the project ives in and should be the same as the
|
|
47
|
+
project name.
|
|
48
|
+
"""
|
|
49
|
+
cwd = Path.cwd()
|
|
50
|
+
return cwd.name
|
|
51
|
+
|
|
20
52
|
@classmethod
|
|
21
53
|
def get_configs(cls) -> dict[str, Any]:
|
|
22
54
|
"""Get the config."""
|
|
23
55
|
return {
|
|
24
56
|
"project": {
|
|
25
|
-
"name":
|
|
57
|
+
"name": make_name_from_obj(cls.get_repository_name(), capitalize=False),
|
|
26
58
|
"readme": "README.md",
|
|
27
|
-
"
|
|
59
|
+
"dependencies": list(cls.get_dependencies()),
|
|
28
60
|
},
|
|
29
61
|
"build-system": {
|
|
30
62
|
"requires": ["poetry-core>=2.0.0,<3.0.0"],
|
|
@@ -32,15 +64,11 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
32
64
|
},
|
|
33
65
|
"tool": {
|
|
34
66
|
"poetry": {
|
|
35
|
-
"packages": [{"include":
|
|
36
|
-
"dependencies": dict.fromkeys(
|
|
37
|
-
cls.get_dependencies(),
|
|
38
|
-
"*",
|
|
39
|
-
),
|
|
67
|
+
"packages": [{"include": cls.get_repository_name()}],
|
|
40
68
|
"group": {
|
|
41
69
|
"dev": {
|
|
42
70
|
"dependencies": dict.fromkeys(
|
|
43
|
-
cls.get_dev_dependencies(),
|
|
71
|
+
cls.get_dev_dependencies() | DEV_DEPENDENCIES,
|
|
44
72
|
"*",
|
|
45
73
|
)
|
|
46
74
|
}
|
|
@@ -62,7 +90,9 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
62
90
|
"files": ".",
|
|
63
91
|
},
|
|
64
92
|
"pytest": {"ini_options": {"testpaths": [TESTS_PACKAGE_NAME]}},
|
|
65
|
-
"bandit": {
|
|
93
|
+
"bandit": {
|
|
94
|
+
"exclude_dirs": [ExperimentConfigFile.get_path().as_posix()],
|
|
95
|
+
},
|
|
66
96
|
},
|
|
67
97
|
}
|
|
68
98
|
|
|
@@ -73,6 +103,29 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
73
103
|
package_name = str(project_dict.get("name", ""))
|
|
74
104
|
return package_name.replace("-", "_")
|
|
75
105
|
|
|
106
|
+
@classmethod
|
|
107
|
+
def remove_wrong_dependencies(cls, config: dict[str, Any]) -> dict[str, Any]:
|
|
108
|
+
"""Remove the wrong dependencies from the config."""
|
|
109
|
+
# raise if the right sections do not exist
|
|
110
|
+
if config.get("project", {}).get("dependencies") is None:
|
|
111
|
+
msg = "No dependencies section in config"
|
|
112
|
+
raise ValueError(msg)
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
config.get("tool", {}).get("poetry", {}).get("group", {}).get("dev", {})
|
|
116
|
+
is None
|
|
117
|
+
):
|
|
118
|
+
msg = "No dev dependencies section in config"
|
|
119
|
+
raise ValueError(msg)
|
|
120
|
+
|
|
121
|
+
# remove the wrong dependencies sections if they exist
|
|
122
|
+
if config.get("tool", {}).get("poetry", {}).get("dependencies") is not None:
|
|
123
|
+
del config["tool"]["poetry"]["dependencies"]
|
|
124
|
+
if config.get("tool", {}).get("poetry", {}).get("dev-dependencies") is not None:
|
|
125
|
+
del config["tool"]["poetry"]["dev-dependencies"]
|
|
126
|
+
|
|
127
|
+
return config
|
|
128
|
+
|
|
76
129
|
@classmethod
|
|
77
130
|
def get_all_dependencies(cls) -> set[str]:
|
|
78
131
|
"""Get all dependencies."""
|
|
@@ -100,9 +153,17 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
100
153
|
@classmethod
|
|
101
154
|
def get_dependencies(cls) -> set[str]:
|
|
102
155
|
"""Get the dependencies."""
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
156
|
+
deps = set(cls.load().get("project", {}).get("dependencies", {}))
|
|
157
|
+
deps = {d.split("(")[0].strip() for d in deps}
|
|
158
|
+
if not deps:
|
|
159
|
+
deps = set(
|
|
160
|
+
cls.load()
|
|
161
|
+
.get("tool", {})
|
|
162
|
+
.get("poetry", {})
|
|
163
|
+
.get("dependencies", {})
|
|
164
|
+
.keys()
|
|
165
|
+
)
|
|
166
|
+
return deps
|
|
106
167
|
|
|
107
168
|
@classmethod
|
|
108
169
|
def get_expected_dev_dependencies(cls) -> set[str]:
|
|
@@ -132,25 +193,29 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
132
193
|
return cls.get_main_author()["name"]
|
|
133
194
|
|
|
134
195
|
@classmethod
|
|
135
|
-
|
|
196
|
+
@cache
|
|
197
|
+
def fetch_latest_python_version(cls) -> Version:
|
|
198
|
+
"""Fetch the latest python version from python.org."""
|
|
199
|
+
url = "https://endoflife.date/api/python.json"
|
|
200
|
+
resp = requests.get(url, timeout=10)
|
|
201
|
+
resp.raise_for_status()
|
|
202
|
+
data = resp.json()
|
|
203
|
+
# first element has metadata for latest stable
|
|
204
|
+
latest_version = data[0]["latest"]
|
|
205
|
+
return Version(latest_version)
|
|
206
|
+
|
|
207
|
+
@classmethod
|
|
208
|
+
def get_latest_possible_python_version(cls) -> Version:
|
|
136
209
|
"""Get the latest possible python version."""
|
|
137
210
|
constraint = cls.load()["project"]["requires-python"]
|
|
138
211
|
version_constraint = VersionConstraint(constraint)
|
|
139
|
-
|
|
140
|
-
if
|
|
141
|
-
|
|
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"
|
|
212
|
+
version = version_constraint.get_upper_inclusive()
|
|
213
|
+
if version is None:
|
|
214
|
+
version = cls.fetch_latest_python_version()
|
|
215
|
+
return version
|
|
151
216
|
|
|
152
217
|
@classmethod
|
|
153
|
-
def get_first_supported_python_version(cls) ->
|
|
218
|
+
def get_first_supported_python_version(cls) -> Version:
|
|
154
219
|
"""Get the first supported python version."""
|
|
155
220
|
constraint = cls.load()["project"]["requires-python"]
|
|
156
221
|
version_constraint = VersionConstraint(constraint)
|
|
@@ -158,7 +223,28 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
158
223
|
if lower is None:
|
|
159
224
|
msg = "Need a lower bound for python version"
|
|
160
225
|
raise ValueError(msg)
|
|
161
|
-
return
|
|
226
|
+
return lower
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def get_supported_python_versions(cls) -> list[Version]:
|
|
230
|
+
"""Get all supported python versions."""
|
|
231
|
+
constraint = cls.load()["project"]["requires-python"]
|
|
232
|
+
version_constraint = VersionConstraint(constraint)
|
|
233
|
+
return version_constraint.get_version_range(
|
|
234
|
+
level="minor", upper_default=cls.fetch_latest_python_version()
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
@classmethod
|
|
238
|
+
def update_poetry(cls) -> None:
|
|
239
|
+
"""Update poetry."""
|
|
240
|
+
args = [POETRY_ARG, "self", "update"]
|
|
241
|
+
run_subprocess(args)
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
def update_with_dev(cls) -> None:
|
|
245
|
+
"""Install all dependencies with dev."""
|
|
246
|
+
args = [POETRY_ARG, "update", "--with", "dev"]
|
|
247
|
+
run_subprocess(args)
|
|
162
248
|
|
|
163
249
|
|
|
164
250
|
class TypedConfigFile(ConfigFile):
|
|
@@ -220,7 +306,9 @@ class DotPythonVersionConfigFile(ConfigFile):
|
|
|
220
306
|
def get_configs(cls) -> dict[str, Any]:
|
|
221
307
|
"""Get the config."""
|
|
222
308
|
return {
|
|
223
|
-
cls.VERSION_KEY:
|
|
309
|
+
cls.VERSION_KEY: str(
|
|
310
|
+
PyprojectConfigFile.get_first_supported_python_version()
|
|
311
|
+
)
|
|
224
312
|
}
|
|
225
313
|
|
|
226
314
|
@classmethod
|
|
@@ -4,8 +4,9 @@ from abc import abstractmethod
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from winipedia_utils.
|
|
8
|
-
from winipedia_utils.
|
|
7
|
+
from winipedia_utils.dev.configs.base.config import ConfigFile
|
|
8
|
+
from winipedia_utils.dev.testing.convention import TESTS_PACKAGE_NAME
|
|
9
|
+
from winipedia_utils.utils.modules.module import make_obj_importpath
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class PythonConfigFile(ConfigFile):
|
|
@@ -73,7 +74,9 @@ class ConftestConfigFile(PythonTestsConfigFile):
|
|
|
73
74
|
@classmethod
|
|
74
75
|
def get_content_str(cls) -> str:
|
|
75
76
|
"""Get the config content."""
|
|
76
|
-
|
|
77
|
+
from winipedia_utils.dev.testing.tests import conftest # noqa: PLC0415
|
|
78
|
+
|
|
79
|
+
return f'''"""Pytest configuration for tests.
|
|
77
80
|
|
|
78
81
|
This module configures pytest plugins for the test suite, setting up the necessary
|
|
79
82
|
fixtures and hooks for the different
|
|
@@ -82,7 +85,7 @@ It also import custom plugins from tests/base/scopes.
|
|
|
82
85
|
This file should not be modified manually.
|
|
83
86
|
"""
|
|
84
87
|
|
|
85
|
-
pytest_plugins = ["
|
|
88
|
+
pytest_plugins = ["{make_obj_importpath(conftest)}"]
|
|
86
89
|
'''
|
|
87
90
|
|
|
88
91
|
|