winipedia-utils 0.3.43__py3-none-any.whl → 0.4.18__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/git/github/repo/__init__.py +1 -0
- winipedia_utils/git/github/repo/protect.py +104 -0
- winipedia_utils/git/github/repo/repo.py +205 -0
- winipedia_utils/git/github/workflows/base/__init__.py +1 -0
- winipedia_utils/git/{workflows → github/workflows}/base/base.py +118 -54
- winipedia_utils/git/github/workflows/health_check.py +57 -0
- winipedia_utils/git/{workflows → github/workflows}/publish.py +11 -8
- winipedia_utils/git/github/workflows/release.py +45 -0
- winipedia_utils/git/gitignore/config.py +49 -29
- winipedia_utils/git/gitignore/gitignore.py +1 -1
- winipedia_utils/git/pre_commit/config.py +18 -13
- winipedia_utils/git/pre_commit/hooks.py +22 -4
- winipedia_utils/git/pre_commit/run_hooks.py +2 -1
- winipedia_utils/iterating/iterate.py +3 -4
- winipedia_utils/modules/module.py +2 -0
- winipedia_utils/modules/package.py +2 -1
- winipedia_utils/projects/poetry/config.py +74 -36
- winipedia_utils/projects/project.py +2 -2
- winipedia_utils/setup.py +2 -0
- winipedia_utils/testing/config.py +83 -29
- winipedia_utils/testing/tests/base/fixtures/fixture.py +36 -0
- winipedia_utils/testing/tests/base/fixtures/scopes/module.py +6 -5
- winipedia_utils/testing/tests/base/fixtures/scopes/session.py +7 -8
- winipedia_utils/testing/tests/base/utils/utils.py +43 -2
- winipedia_utils/text/config.py +84 -37
- {winipedia_utils-0.3.43.dist-info → winipedia_utils-0.4.18.dist-info}/METADATA +23 -8
- {winipedia_utils-0.3.43.dist-info → winipedia_utils-0.4.18.dist-info}/RECORD +31 -27
- winipedia_utils/git/workflows/health_check.py +0 -51
- winipedia_utils/git/workflows/release.py +0 -33
- /winipedia_utils/git/{workflows/base → github}/__init__.py +0 -0
- /winipedia_utils/git/{workflows → github/workflows}/__init__.py +0 -0
- {winipedia_utils-0.3.43.dist-info → winipedia_utils-0.4.18.dist-info}/WHEEL +0 -0
- {winipedia_utils-0.3.43.dist-info → winipedia_utils-0.4.18.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,8 +5,8 @@ This workflow is used to publish the package to PyPI with poetry.
|
|
|
5
5
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from winipedia_utils.git.workflows.base.base import Workflow
|
|
9
|
-
from winipedia_utils.git.workflows.release import ReleaseWorkflow
|
|
8
|
+
from winipedia_utils.git.github.workflows.base.base import Workflow
|
|
9
|
+
from winipedia_utils.git.github.workflows.release import ReleaseWorkflow
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class PublishWorkflow(Workflow):
|
|
@@ -16,7 +16,8 @@ class PublishWorkflow(Workflow):
|
|
|
16
16
|
It publishes the package to PyPI with poetry.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
@classmethod
|
|
20
|
+
def get_workflow_triggers(cls) -> dict[str, Any]:
|
|
20
21
|
"""Get the workflow triggers."""
|
|
21
22
|
return {
|
|
22
23
|
"workflow_run": {
|
|
@@ -25,22 +26,24 @@ class PublishWorkflow(Workflow):
|
|
|
25
26
|
},
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_permissions(cls) -> dict[str, Any]:
|
|
29
31
|
"""Get the workflow permissions."""
|
|
30
32
|
return {
|
|
31
33
|
"contents": "read",
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
@classmethod
|
|
37
|
+
def get_jobs(cls) -> dict[str, Any]:
|
|
35
38
|
"""Get the workflow jobs."""
|
|
36
|
-
return
|
|
39
|
+
return cls.get_standard_job(
|
|
37
40
|
steps=[
|
|
38
41
|
*(
|
|
39
|
-
|
|
42
|
+
cls.get_poetry_setup_steps(
|
|
40
43
|
configure_pipy_token=True,
|
|
41
44
|
)
|
|
42
45
|
),
|
|
43
|
-
|
|
46
|
+
cls.get_publish_to_pypi_step(),
|
|
44
47
|
],
|
|
45
48
|
if_condition="${{ github.event.workflow_run.conclusion == 'success' }}",
|
|
46
49
|
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Contains the release workflow.
|
|
2
|
+
|
|
3
|
+
This workflow is used to create a release on GitHub.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from winipedia_utils.git.github.workflows.health_check import HealthCheckWorkflow
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ReleaseWorkflow(HealthCheckWorkflow):
|
|
12
|
+
"""Release workflow.
|
|
13
|
+
|
|
14
|
+
This workflow is triggered by a push to the main branch.
|
|
15
|
+
It creates a tag for the release and builds a changelog.
|
|
16
|
+
With tag and changelog it creates a release on GitHub
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def get_workflow_triggers(cls) -> dict[str, Any]:
|
|
21
|
+
"""Get the workflow triggers."""
|
|
22
|
+
return {
|
|
23
|
+
"push": {"branches": ["main"]},
|
|
24
|
+
"workflow_dispatch": {},
|
|
25
|
+
"schedule": [
|
|
26
|
+
{
|
|
27
|
+
# run every Tuesday at 6 am
|
|
28
|
+
"cron": "0 6 * * 2",
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def get_permissions(cls) -> dict[str, Any]:
|
|
35
|
+
"""Get the workflow permissions."""
|
|
36
|
+
permissions = super().get_permissions()
|
|
37
|
+
permissions["contents"] = "write"
|
|
38
|
+
return permissions
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def get_jobs(cls) -> dict[str, Any]:
|
|
42
|
+
"""Get the workflow jobs."""
|
|
43
|
+
steps = super().get_jobs()
|
|
44
|
+
steps[cls.get_filename()]["steps"].extend(cls.get_release_steps())
|
|
45
|
+
return steps
|
|
@@ -3,52 +3,72 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
+
import requests
|
|
7
|
+
|
|
8
|
+
from winipedia_utils.testing.config import ExperimentConfigFile, LocalSecretsConfigFile
|
|
6
9
|
from winipedia_utils.text.config import ConfigFile
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class GitIgnoreConfigFile(ConfigFile):
|
|
10
13
|
"""Config file for .gitignore."""
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
@classmethod
|
|
16
|
+
def get_filename(cls) -> str:
|
|
17
|
+
"""Get the filename of the config file."""
|
|
18
|
+
return "" # so it builds the path .gitignore and not gitignore.gitignore
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
@classmethod
|
|
21
|
+
def get_parent_path(cls) -> Path:
|
|
17
22
|
"""Get the path to the config file."""
|
|
18
|
-
return
|
|
23
|
+
return Path()
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
@classmethod
|
|
26
|
+
def get_file_extension(cls) -> str:
|
|
27
|
+
"""Get the file extension of the config file."""
|
|
28
|
+
return "gitignore"
|
|
23
29
|
|
|
24
30
|
@classmethod
|
|
25
|
-
def
|
|
31
|
+
def load(cls) -> list[str]:
|
|
26
32
|
"""Load the config file."""
|
|
27
|
-
|
|
28
|
-
return {cls.IGNORE_KEY: paths}
|
|
33
|
+
return cls.get_path().read_text().splitlines()
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
@classmethod
|
|
36
|
+
def dump(cls, config: list[str] | dict[str, Any]) -> None:
|
|
31
37
|
"""Dump the config file."""
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
if not isinstance(config, list):
|
|
39
|
+
msg = f"Cannot dump {config} to .gitignore file."
|
|
40
|
+
raise TypeError(msg)
|
|
41
|
+
cls.get_path().write_text("\n".join(config))
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
@classmethod
|
|
44
|
+
def get_configs(cls) -> list[str]:
|
|
36
45
|
"""Get the config."""
|
|
37
|
-
|
|
38
|
-
ExperimentConfigFile,
|
|
39
|
-
)
|
|
40
|
-
|
|
46
|
+
# fetch the standard github gitignore via https://github.com/github/gitignore/blob/main/Python.gitignore
|
|
41
47
|
needed = [
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
".mypy_cache/",
|
|
45
|
-
".pytest_cache/",
|
|
46
|
-
".ruff_cache/",
|
|
48
|
+
*cls.get_github_python_gitignore(),
|
|
49
|
+
"# vscode stuff",
|
|
47
50
|
".vscode/",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
+
"",
|
|
52
|
+
"# winipedia_utils stuff",
|
|
53
|
+
"# for walk_os_skipping_gitignore_patterns func",
|
|
54
|
+
".git/",
|
|
55
|
+
"# for executing experimental code",
|
|
56
|
+
ExperimentConfigFile.get_path().as_posix(),
|
|
57
|
+
"# for secrets used locally",
|
|
58
|
+
LocalSecretsConfigFile.get_path().as_posix(),
|
|
51
59
|
]
|
|
52
|
-
existing =
|
|
60
|
+
existing = cls.load()
|
|
53
61
|
needed = [p for p in needed if p not in set(existing)]
|
|
54
|
-
return
|
|
62
|
+
return existing + needed
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def get_github_python_gitignore(cls) -> list[str]:
|
|
66
|
+
"""Get the standard github python gitignore."""
|
|
67
|
+
url = "https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore"
|
|
68
|
+
res = requests.get(url, timeout=10)
|
|
69
|
+
if not res.ok:
|
|
70
|
+
if not Path(".gitignore").exists():
|
|
71
|
+
msg = f"Failed to fetch {url}. Cannot create .gitignore."
|
|
72
|
+
raise RuntimeError(msg)
|
|
73
|
+
return []
|
|
74
|
+
return res.text.splitlines()
|
|
@@ -40,7 +40,7 @@ def path_is_in_gitignore(relative_path: str | Path) -> bool:
|
|
|
40
40
|
|
|
41
41
|
spec = pathspec.PathSpec.from_lines(
|
|
42
42
|
"gitwildmatch",
|
|
43
|
-
GitIgnoreConfigFile.
|
|
43
|
+
GitIgnoreConfigFile.load(),
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
return spec.match_file(as_posix)
|
|
@@ -7,27 +7,27 @@ import winipedia_utils
|
|
|
7
7
|
from winipedia_utils.logging.logger import get_logger
|
|
8
8
|
from winipedia_utils.modules.package import make_name_from_package
|
|
9
9
|
from winipedia_utils.os.os import run_subprocess
|
|
10
|
-
from winipedia_utils.projects.poetry.poetry import POETRY_RUN_ARGS
|
|
11
10
|
from winipedia_utils.text.config import YamlConfigFile
|
|
12
11
|
|
|
13
12
|
logger = get_logger(__name__)
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
class
|
|
15
|
+
class PreCommitConfigConfigFile(YamlConfigFile):
|
|
17
16
|
"""Config file for pre-commit."""
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
self.install()
|
|
18
|
+
@classmethod
|
|
19
|
+
def get_filename(cls) -> str:
|
|
20
|
+
"""Get the filename of the config file."""
|
|
21
|
+
filename = super().get_filename()
|
|
22
|
+
return f".{filename.replace('_', '-')}"
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
@classmethod
|
|
25
|
+
def get_parent_path(cls) -> Path:
|
|
27
26
|
"""Get the path to the config file."""
|
|
28
|
-
return
|
|
27
|
+
return Path()
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_configs(cls) -> dict[str, Any]:
|
|
31
31
|
"""Get the config."""
|
|
32
32
|
hook_name = make_name_from_package(winipedia_utils, capitalize=False)
|
|
33
33
|
return {
|
|
@@ -38,7 +38,7 @@ class PreCommitConfigFile(YamlConfigFile):
|
|
|
38
38
|
{
|
|
39
39
|
"id": hook_name,
|
|
40
40
|
"name": hook_name,
|
|
41
|
-
"entry":
|
|
41
|
+
"entry": cls.get_python_setup_script(),
|
|
42
42
|
"language": "system",
|
|
43
43
|
"always_run": True,
|
|
44
44
|
"pass_filenames": False,
|
|
@@ -48,8 +48,13 @@ class PreCommitConfigFile(YamlConfigFile):
|
|
|
48
48
|
]
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
def __init__(self) -> None:
|
|
52
|
+
"""Init the file."""
|
|
53
|
+
super().__init__()
|
|
54
|
+
self.install()
|
|
55
|
+
|
|
51
56
|
@classmethod
|
|
52
57
|
def install(cls) -> None:
|
|
53
58
|
"""Installs the pre commits in the config."""
|
|
54
59
|
logger.info("Running pre-commit install")
|
|
55
|
-
run_subprocess([
|
|
60
|
+
run_subprocess(["pre-commit", "install"], check=True)
|
|
@@ -42,20 +42,29 @@ def update_package_manager() -> list[str | Path]:
|
|
|
42
42
|
return [POETRY_ARG, "self", "update"]
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
def
|
|
45
|
+
def install_dependencies_with_dev() -> list[str | Path]:
|
|
46
46
|
"""Install all dependencies.
|
|
47
47
|
|
|
48
48
|
This function returns the input for subprocess.run() to install all dependencies.
|
|
49
49
|
"""
|
|
50
|
-
return [POETRY_ARG, "install"]
|
|
50
|
+
return [POETRY_ARG, "install", "--with", "dev"]
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
def
|
|
53
|
+
def update_dependencies_with_dev() -> list[str | Path]:
|
|
54
54
|
"""Update all dependencies.
|
|
55
55
|
|
|
56
56
|
This function returns the input for subprocess.run() to update all dependencies.
|
|
57
57
|
"""
|
|
58
|
-
return [POETRY_ARG, "update"]
|
|
58
|
+
return [POETRY_ARG, "update", "--with", "dev"]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def add_updates_to_git() -> list[str | Path]:
|
|
62
|
+
"""Add the updated dependencies to git.
|
|
63
|
+
|
|
64
|
+
This function returns the input for subprocess.run() to add the updated
|
|
65
|
+
dependencies to git, so that the hook does not fail bc the file was changed.
|
|
66
|
+
"""
|
|
67
|
+
return ["git", "add", "pyproject.toml"]
|
|
59
68
|
|
|
60
69
|
|
|
61
70
|
def lock_dependencies() -> list[str | Path]:
|
|
@@ -66,6 +75,15 @@ def lock_dependencies() -> list[str | Path]:
|
|
|
66
75
|
return [POETRY_ARG, "lock"]
|
|
67
76
|
|
|
68
77
|
|
|
78
|
+
def add_lock_file_to_git() -> list[str | Path]:
|
|
79
|
+
"""Add the lock file to git.
|
|
80
|
+
|
|
81
|
+
This function returns the input for subprocess.run() to add the lock file
|
|
82
|
+
to git, so that the hook does not fail bc the file was changed.
|
|
83
|
+
"""
|
|
84
|
+
return ["git", "add", "poetry.lock"]
|
|
85
|
+
|
|
86
|
+
|
|
69
87
|
def check_package_manager_configs() -> list[str | Path]:
|
|
70
88
|
"""Check that poetry.lock and pyproject.toml is up to date.
|
|
71
89
|
|
|
@@ -78,10 +78,9 @@ def nested_structure_is_subset(
|
|
|
78
78
|
if not nested_structure_is_subset(
|
|
79
79
|
value, actual_value, on_false_dict_action, on_false_list_action
|
|
80
80
|
):
|
|
81
|
-
|
|
81
|
+
all_good = False
|
|
82
82
|
if on_false_action is not None:
|
|
83
83
|
on_false_action(subset, superset, key_or_index)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
all_good = False
|
|
84
|
+
all_good = nested_structure_is_subset(subset, superset)
|
|
85
|
+
|
|
87
86
|
return all_good
|
|
@@ -215,6 +215,8 @@ def import_obj_from_importpath(
|
|
|
215
215
|
return import_module(importpath)
|
|
216
216
|
except ImportError:
|
|
217
217
|
# might be a class or function
|
|
218
|
+
if "." not in importpath:
|
|
219
|
+
raise
|
|
218
220
|
module_name, obj_name = importpath.rsplit(".", 1)
|
|
219
221
|
module = import_module(module_name)
|
|
220
222
|
obj: Callable[..., Any] | type | ModuleType = getattr(module, obj_name)
|
|
@@ -183,7 +183,8 @@ def find_packages(
|
|
|
183
183
|
)
|
|
184
184
|
|
|
185
185
|
if exclude is None:
|
|
186
|
-
|
|
186
|
+
# must init GitIgnoreConfigFile to create .gitignore if it does not exist
|
|
187
|
+
exclude = GitIgnoreConfigFile.load()
|
|
187
188
|
exclude = [
|
|
188
189
|
p.replace("/", ".").removesuffix(".") for p in exclude if p.endswith("/")
|
|
189
190
|
]
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
"""Config utilities for poetry and pyproject.toml."""
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any, cast
|
|
5
5
|
|
|
6
6
|
from winipedia_utils.modules.package import get_src_package, make_name_from_package
|
|
7
7
|
from winipedia_utils.testing.convention import TESTS_PACKAGE_NAME
|
|
8
8
|
from winipedia_utils.text.config import ConfigFile, TomlConfigFile
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class
|
|
11
|
+
class PyprojectConfigFile(TomlConfigFile):
|
|
12
12
|
"""Config file for pyproject.toml."""
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def get_path(self) -> Path:
|
|
14
|
+
@classmethod
|
|
15
|
+
def get_parent_path(cls) -> Path:
|
|
17
16
|
"""Get the path to the config file."""
|
|
18
|
-
return
|
|
17
|
+
return Path()
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
@classmethod
|
|
20
|
+
def get_configs(cls) -> dict[str, Any]:
|
|
21
21
|
"""Get the config."""
|
|
22
22
|
return {
|
|
23
23
|
"project": {
|
|
@@ -32,21 +32,14 @@ class PyProjectTomlConfig(TomlConfigFile):
|
|
|
32
32
|
"tool": {
|
|
33
33
|
"poetry": {
|
|
34
34
|
"packages": [{"include": get_src_package().__name__}],
|
|
35
|
+
"dependencies": dict.fromkeys(
|
|
36
|
+
cls.get_dependencies(),
|
|
37
|
+
"*",
|
|
38
|
+
),
|
|
35
39
|
"group": {
|
|
36
40
|
"dev": {
|
|
37
41
|
"dependencies": dict.fromkeys(
|
|
38
|
-
|
|
39
|
-
"ruff",
|
|
40
|
-
"pre-commit",
|
|
41
|
-
"mypy",
|
|
42
|
-
"pytest",
|
|
43
|
-
"bandit",
|
|
44
|
-
"types-setuptools",
|
|
45
|
-
"types-tqdm",
|
|
46
|
-
"types-defusedxml",
|
|
47
|
-
"types-pyyaml",
|
|
48
|
-
"pytest-mock",
|
|
49
|
-
],
|
|
42
|
+
cls.get_dev_dependencies(),
|
|
50
43
|
"*",
|
|
51
44
|
)
|
|
52
45
|
}
|
|
@@ -72,16 +65,23 @@ class PyProjectTomlConfig(TomlConfigFile):
|
|
|
72
65
|
},
|
|
73
66
|
}
|
|
74
67
|
|
|
75
|
-
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_package_name(cls) -> str:
|
|
76
70
|
"""Get the package name."""
|
|
77
|
-
project_dict =
|
|
71
|
+
project_dict = cls.load().get("project", {})
|
|
78
72
|
package_name = str(project_dict.get("name", ""))
|
|
79
73
|
return package_name.replace("-", "_")
|
|
80
74
|
|
|
81
|
-
|
|
75
|
+
@classmethod
|
|
76
|
+
def get_all_dependencies(cls) -> set[str]:
|
|
77
|
+
"""Get all dependencies."""
|
|
78
|
+
return cls.get_dependencies() | cls.get_dev_dependencies()
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def get_dev_dependencies(cls) -> set[str]:
|
|
82
82
|
"""Get the dev dependencies."""
|
|
83
83
|
dev_dependencies = set(
|
|
84
|
-
|
|
84
|
+
cls.load()
|
|
85
85
|
.get("tool", {})
|
|
86
86
|
.get("poetry", {})
|
|
87
87
|
.get("group", {})
|
|
@@ -91,38 +91,76 @@ class PyProjectTomlConfig(TomlConfigFile):
|
|
|
91
91
|
)
|
|
92
92
|
if not dev_dependencies:
|
|
93
93
|
dev_dependencies = set(
|
|
94
|
-
|
|
94
|
+
cls.load().get("dependency-groups", {}).get("dev", [])
|
|
95
95
|
)
|
|
96
96
|
dev_dependencies = {d.split("(")[0].strip() for d in dev_dependencies}
|
|
97
97
|
return dev_dependencies
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
@classmethod
|
|
100
|
+
def get_dependencies(cls) -> set[str]:
|
|
101
|
+
"""Get the dependencies."""
|
|
102
|
+
return set(
|
|
103
|
+
cls.load().get("tool", {}).get("poetry", {}).get("dependencies", {}).keys()
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def get_expected_dev_dependencies(cls) -> set[str]:
|
|
100
108
|
"""Get the expected dev dependencies."""
|
|
101
109
|
return set(
|
|
102
|
-
|
|
110
|
+
cls.get_configs()["tool"]["poetry"]["group"]["dev"]["dependencies"].keys()
|
|
103
111
|
)
|
|
104
112
|
|
|
113
|
+
@classmethod
|
|
114
|
+
def get_authors(cls) -> list[dict[str, str]]:
|
|
115
|
+
"""Get the authors."""
|
|
116
|
+
return cast(
|
|
117
|
+
"list[dict[str, str]]", cls.load().get("project", {}).get("authors", [])
|
|
118
|
+
)
|
|
105
119
|
|
|
106
|
-
|
|
120
|
+
@classmethod
|
|
121
|
+
def get_main_author(cls) -> dict[str, str]:
|
|
122
|
+
"""Get the main author.
|
|
123
|
+
|
|
124
|
+
Assumes the main author is the first author.
|
|
125
|
+
"""
|
|
126
|
+
return cls.get_authors()[0]
|
|
127
|
+
|
|
128
|
+
@classmethod
|
|
129
|
+
def get_main_author_name(cls) -> str:
|
|
130
|
+
"""Get the main author name."""
|
|
131
|
+
return cls.get_main_author()["name"]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class TypedConfigFile(ConfigFile):
|
|
107
135
|
"""Config file for py.typed."""
|
|
108
136
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return Path(package_name) / "py.typed"
|
|
137
|
+
@classmethod
|
|
138
|
+
def get_file_extension(cls) -> str:
|
|
139
|
+
"""Get the file extension of the config file."""
|
|
140
|
+
return "typed"
|
|
114
141
|
|
|
115
|
-
|
|
142
|
+
@classmethod
|
|
143
|
+
def load(cls) -> dict[str, Any] | list[Any]:
|
|
116
144
|
"""Load the config file."""
|
|
117
145
|
return {}
|
|
118
146
|
|
|
119
|
-
|
|
147
|
+
@classmethod
|
|
148
|
+
def dump(cls, config: dict[str, Any] | list[Any]) -> None:
|
|
120
149
|
"""Dump the config file."""
|
|
121
150
|
if config:
|
|
122
151
|
msg = "Cannot dump to py.typed file."
|
|
123
152
|
raise ValueError(msg)
|
|
124
|
-
self.path.touch()
|
|
125
153
|
|
|
126
|
-
|
|
154
|
+
@classmethod
|
|
155
|
+
def get_configs(cls) -> dict[str, Any] | list[Any]:
|
|
127
156
|
"""Get the config."""
|
|
128
157
|
return {}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class PyTypedConfigFile(ConfigFile):
|
|
161
|
+
"""Config file for py.typed."""
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def get_parent_path(cls) -> Path:
|
|
165
|
+
"""Get the path to the config file."""
|
|
166
|
+
return Path(PyprojectConfigFile.get_package_name())
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from winipedia_utils.modules.module import create_module
|
|
4
4
|
from winipedia_utils.projects.poetry.config import (
|
|
5
|
-
|
|
5
|
+
PyprojectConfigFile, # avoid circular import
|
|
6
6
|
)
|
|
7
7
|
from winipedia_utils.text.config import (
|
|
8
8
|
ConfigFile, # avoid circular import
|
|
@@ -13,5 +13,5 @@ def create_project_root() -> None:
|
|
|
13
13
|
"""Create the project root."""
|
|
14
14
|
ConfigFile.init_config_files()
|
|
15
15
|
|
|
16
|
-
src_package_name =
|
|
16
|
+
src_package_name = PyprojectConfigFile.get_package_name()
|
|
17
17
|
create_module(src_package_name, is_package=True)
|
winipedia_utils/setup.py
CHANGED
|
@@ -9,6 +9,7 @@ This script is intended to be called once at the beginning of a project.
|
|
|
9
9
|
from collections.abc import Callable
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
from winipedia_utils.git.gitignore.config import GitIgnoreConfigFile
|
|
12
13
|
from winipedia_utils.git.pre_commit.run_hooks import run_hooks
|
|
13
14
|
from winipedia_utils.logging.logger import get_logger
|
|
14
15
|
from winipedia_utils.projects.project import create_project_root
|
|
@@ -17,6 +18,7 @@ logger = get_logger(__name__)
|
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
SETUP_STEPS: list[Callable[..., Any]] = [
|
|
21
|
+
GitIgnoreConfigFile, # must be first
|
|
20
22
|
create_project_root,
|
|
21
23
|
run_hooks,
|
|
22
24
|
]
|