dycw-actions 0.3.2__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.
- actions/__init__.py +1 -1
- actions/action_dicts/constants.py +8 -0
- actions/action_dicts/lib.py +186 -0
- actions/clean_dir/cli.py +21 -0
- actions/clean_dir/constants.py +7 -0
- actions/clean_dir/lib.py +59 -0
- actions/clean_dir/settings.py +18 -0
- actions/cli.py +95 -6
- actions/constants.py +10 -0
- actions/pre_commit/click.py +15 -0
- actions/pre_commit/conformalize_repo/__init__.py +1 -0
- actions/pre_commit/conformalize_repo/cli.py +64 -0
- actions/pre_commit/conformalize_repo/configs/gitignore +244 -0
- actions/pre_commit/conformalize_repo/constants.py +78 -0
- actions/pre_commit/conformalize_repo/lib.py +1293 -0
- actions/pre_commit/conformalize_repo/settings.py +119 -0
- actions/pre_commit/constants.py +8 -0
- actions/pre_commit/format_requirements/__init__.py +1 -0
- actions/pre_commit/format_requirements/cli.py +24 -0
- actions/pre_commit/format_requirements/constants.py +7 -0
- actions/pre_commit/format_requirements/lib.py +52 -0
- actions/pre_commit/replace_sequence_strs/__init__.py +1 -0
- actions/pre_commit/replace_sequence_strs/cli.py +24 -0
- actions/pre_commit/replace_sequence_strs/constants.py +7 -0
- actions/pre_commit/replace_sequence_strs/lib.py +73 -0
- actions/pre_commit/touch_empty_py/__init__.py +1 -0
- actions/pre_commit/touch_empty_py/cli.py +24 -0
- actions/pre_commit/touch_empty_py/constants.py +7 -0
- actions/pre_commit/touch_empty_py/lib.py +54 -0
- actions/pre_commit/touch_py_typed/__init__.py +1 -0
- actions/pre_commit/touch_py_typed/cli.py +24 -0
- actions/pre_commit/touch_py_typed/constants.py +7 -0
- actions/pre_commit/touch_py_typed/lib.py +64 -0
- actions/pre_commit/update_requirements/__init__.py +1 -0
- actions/pre_commit/update_requirements/classes.py +117 -0
- actions/pre_commit/update_requirements/cli.py +24 -0
- actions/pre_commit/update_requirements/constants.py +7 -0
- actions/pre_commit/update_requirements/lib.py +128 -0
- actions/pre_commit/utilities.py +386 -0
- actions/publish_package/__init__.py +1 -0
- actions/publish_package/cli.py +27 -0
- actions/publish_package/constants.py +7 -0
- actions/{publish → publish_package}/lib.py +18 -17
- actions/{publish → publish_package}/settings.py +7 -7
- actions/py.typed +0 -0
- actions/random_sleep/__init__.py +1 -0
- actions/random_sleep/cli.py +26 -0
- actions/random_sleep/constants.py +7 -0
- actions/{sleep → random_sleep}/lib.py +14 -13
- actions/{sleep → random_sleep}/settings.py +3 -3
- actions/run_hooks/__init__.py +1 -0
- actions/run_hooks/cli.py +21 -0
- actions/run_hooks/constants.py +7 -0
- actions/run_hooks/lib.py +97 -0
- actions/run_hooks/settings.py +24 -0
- actions/setup_cronjob/__init__.py +1 -0
- actions/setup_cronjob/cli.py +31 -0
- actions/setup_cronjob/configs/cron.tmpl +3 -0
- actions/setup_cronjob/configs/logrotate.tmpl +10 -0
- actions/setup_cronjob/constants.py +12 -0
- actions/setup_cronjob/lib.py +120 -0
- actions/setup_cronjob/settings.py +27 -0
- actions/tag_commit/__init__.py +1 -0
- actions/tag_commit/cli.py +27 -0
- actions/tag_commit/constants.py +7 -0
- actions/tag_commit/lib.py +63 -0
- actions/{tag → tag_commit}/settings.py +3 -3
- actions/types.py +14 -1
- actions/utilities.py +131 -17
- dycw_actions-0.7.1.dist-info/METADATA +22 -0
- dycw_actions-0.7.1.dist-info/RECORD +77 -0
- {dycw_actions-0.3.2.dist-info → dycw_actions-0.7.1.dist-info}/WHEEL +1 -1
- actions/publish/cli.py +0 -43
- actions/settings.py +0 -18
- actions/sleep/cli.py +0 -39
- actions/tag/cli.py +0 -43
- actions/tag/lib.py +0 -62
- dycw_actions-0.3.2.dist-info/METADATA +0 -14
- dycw_actions-0.3.2.dist-info/RECORD +0 -22
- /actions/{publish → action_dicts}/__init__.py +0 -0
- /actions/{sleep → clean_dir}/__init__.py +0 -0
- /actions/{tag → pre_commit}/__init__.py +0 -0
- {dycw_actions-0.3.2.dist-info → dycw_actions-0.7.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typed_settings import load_settings, option, settings
|
|
4
|
+
|
|
5
|
+
from actions.pre_commit.conformalize_repo.constants import RUN_VERSION_BUMP
|
|
6
|
+
from actions.utilities import LOADER
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@settings
|
|
10
|
+
class Settings:
|
|
11
|
+
coverage: bool = option(default=False, help="Set up '.coveragerc.toml'")
|
|
12
|
+
description: str | None = option(default=None, help="Repo description")
|
|
13
|
+
envrc: bool = option(default=False, help="Set up '.envrc'")
|
|
14
|
+
envrc__uv: bool = option(default=False, help="Set up '.envrc' with uv")
|
|
15
|
+
envrc__uv__native_tls: bool = option(
|
|
16
|
+
default=False, help="Set up '.envrc' with uv native TLS"
|
|
17
|
+
)
|
|
18
|
+
github__pull_request__pre_commit: bool = option(
|
|
19
|
+
default=False, help="Set up 'pull-request.yaml' pre-commit"
|
|
20
|
+
)
|
|
21
|
+
github__pull_request__pre_commit__gitea: bool = option(
|
|
22
|
+
default=False, help="Set up 'pull-request.yaml' for Gitea"
|
|
23
|
+
)
|
|
24
|
+
github__pull_request__pyright: bool = option(
|
|
25
|
+
default=False, help="Set up 'pull-request.yaml' pyright"
|
|
26
|
+
)
|
|
27
|
+
github__pull_request__pytest__macos: bool = option(
|
|
28
|
+
default=False, help="Set up 'pull-request.yaml' pytest with MacOS"
|
|
29
|
+
)
|
|
30
|
+
github__pull_request__pytest__ubuntu: bool = option(
|
|
31
|
+
default=False, help="Set up 'pull-request.yaml' pytest with Ubuntu"
|
|
32
|
+
)
|
|
33
|
+
github__pull_request__pytest__windows: bool = option(
|
|
34
|
+
default=False, help="Set up 'pull-request.yaml' pytest with Windows"
|
|
35
|
+
)
|
|
36
|
+
github__pull_request__ruff: bool = option(
|
|
37
|
+
default=False, help="Set up 'pull-request.yaml' ruff"
|
|
38
|
+
)
|
|
39
|
+
github__push__publish: bool = option(
|
|
40
|
+
default=False, help="Set up 'push.yaml' publishing"
|
|
41
|
+
)
|
|
42
|
+
github__push__tag: bool = option(default=False, help="Set up 'push.yaml' tagging")
|
|
43
|
+
github__push__tag__major: bool = option(
|
|
44
|
+
default=False, help="Set up 'push.yaml' with the 'major' tag"
|
|
45
|
+
)
|
|
46
|
+
github__push__tag__major_minor: bool = option(
|
|
47
|
+
default=False, help="Set up 'push.yaml' with the 'major.minor' tag"
|
|
48
|
+
)
|
|
49
|
+
github__push__tag__latest: bool = option(
|
|
50
|
+
default=False, help="Set up 'push.yaml' tagging"
|
|
51
|
+
)
|
|
52
|
+
gitignore: bool = option(default=False, help="Set up '.gitignore'")
|
|
53
|
+
package_name: str | None = option(default=None, help="Package name")
|
|
54
|
+
pre_commit__dockerfmt: bool = option(
|
|
55
|
+
default=False, help="Set up '.pre-commit-config.yaml' dockerfmt"
|
|
56
|
+
)
|
|
57
|
+
pre_commit__prettier: bool = option(
|
|
58
|
+
default=False, help="Set up '.pre-commit-config.yaml' prettier"
|
|
59
|
+
)
|
|
60
|
+
pre_commit__python: bool = option(
|
|
61
|
+
default=False, help="Set up '.pre-commit-config.yaml' python"
|
|
62
|
+
)
|
|
63
|
+
pre_commit__ruff: bool = option(
|
|
64
|
+
default=False, help="Set up '.pre-commit-config.yaml' ruff"
|
|
65
|
+
)
|
|
66
|
+
pre_commit__shell: bool = option(
|
|
67
|
+
default=False, help="Set up '.pre-commit-config.yaml' shell"
|
|
68
|
+
)
|
|
69
|
+
pre_commit__taplo: bool = option(
|
|
70
|
+
default=False, help="Set up '.pre-commit-config.yaml' taplo"
|
|
71
|
+
)
|
|
72
|
+
pre_commit__uv: bool = option(
|
|
73
|
+
default=False, help="Set up '.pre-commit-config.yaml' uv"
|
|
74
|
+
)
|
|
75
|
+
pre_commit__uv__script: str | None = option(
|
|
76
|
+
default=None, help="Set up '.pre-commit-config.yaml' uv lock script"
|
|
77
|
+
)
|
|
78
|
+
pyproject: bool = option(default=False, help="Set up 'pyproject.toml'")
|
|
79
|
+
pyproject__project__optional_dependencies__scripts: bool = option(
|
|
80
|
+
default=False,
|
|
81
|
+
help="Set up 'pyproject.toml' [project.optional-dependencies.scripts]",
|
|
82
|
+
)
|
|
83
|
+
pyproject__tool__uv__indexes: list[tuple[str, str]] = option(
|
|
84
|
+
factory=list, help="Set up 'pyproject.toml' [[uv.tool.index]]"
|
|
85
|
+
)
|
|
86
|
+
pyright: bool = option(default=False, help="Set up 'pyrightconfig.json'")
|
|
87
|
+
pytest: bool = option(default=False, help="Set up 'pytest.toml'")
|
|
88
|
+
pytest__asyncio: bool = option(default=False, help="Set up 'pytest.toml' asyncio_*")
|
|
89
|
+
pytest__ignore_warnings: bool = option(
|
|
90
|
+
default=False, help="Set up 'pytest.toml' filterwarnings"
|
|
91
|
+
)
|
|
92
|
+
pytest__timeout: int | None = option(
|
|
93
|
+
default=None, help="Set up 'pytest.toml' timeout"
|
|
94
|
+
)
|
|
95
|
+
python_package_name: str | None = option(
|
|
96
|
+
default=None, help="Python package name override"
|
|
97
|
+
)
|
|
98
|
+
python_version: str = option(default="3.14", help="Python version")
|
|
99
|
+
readme: bool = option(default=False, help="Set up 'README.md'")
|
|
100
|
+
repo_name: str | None = option(default=None, help="Repo name")
|
|
101
|
+
ruff: bool = option(default=False, help="Set up 'ruff.toml'")
|
|
102
|
+
run_version_bump: bool = option(default=RUN_VERSION_BUMP, help="Run version bump")
|
|
103
|
+
script: str | None = option(
|
|
104
|
+
default=None, help="Set up a script instead of a package"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def python_package_name_use(self) -> str | None:
|
|
109
|
+
if self.python_package_name is not None:
|
|
110
|
+
return self.python_package_name
|
|
111
|
+
if self.package_name is not None:
|
|
112
|
+
return self.package_name.replace("-", "_")
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
SETTINGS = load_settings(Settings, [LOADER])
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
__all__ = ["SETTINGS", "Settings"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from utilities.logging import basic_config
|
|
6
|
+
from utilities.os import is_pytest
|
|
7
|
+
|
|
8
|
+
from actions.logging import LOGGER
|
|
9
|
+
from actions.pre_commit.click import path_argument
|
|
10
|
+
from actions.pre_commit.format_requirements.lib import format_requirements
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@path_argument
|
|
17
|
+
def format_requirements_sub_cmd(*, paths: tuple[Path, ...]) -> None:
|
|
18
|
+
if is_pytest():
|
|
19
|
+
return
|
|
20
|
+
basic_config(obj=LOGGER)
|
|
21
|
+
format_requirements(*paths)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ["format_requirements_sub_cmd"]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from utilities.text import repr_str, strip_and_dedent
|
|
7
|
+
|
|
8
|
+
from actions import __version__
|
|
9
|
+
from actions.logging import LOGGER
|
|
10
|
+
from actions.pre_commit.utilities import get_pyproject_dependencies, yield_toml_doc
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import MutableSet
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from utilities.packaging import Requirement
|
|
17
|
+
from utilities.types import PathLike
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def format_requirements(*paths: PathLike) -> None:
|
|
21
|
+
LOGGER.info(
|
|
22
|
+
strip_and_dedent("""
|
|
23
|
+
Running '%s' (version %s) with settings:
|
|
24
|
+
- paths = %s
|
|
25
|
+
"""),
|
|
26
|
+
format_requirements.__name__,
|
|
27
|
+
__version__,
|
|
28
|
+
paths,
|
|
29
|
+
)
|
|
30
|
+
modifications: set[Path] = set()
|
|
31
|
+
for path in paths:
|
|
32
|
+
_format_path(path, modifications=modifications)
|
|
33
|
+
if len(modifications) >= 1:
|
|
34
|
+
LOGGER.info(
|
|
35
|
+
"Exiting due to modifications: %s",
|
|
36
|
+
", ".join(map(repr_str, sorted(modifications))),
|
|
37
|
+
)
|
|
38
|
+
sys.exit(1)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _format_path(
|
|
42
|
+
path: PathLike, /, *, modifications: MutableSet[Path] | None = None
|
|
43
|
+
) -> None:
|
|
44
|
+
with yield_toml_doc(path, modifications=modifications) as doc:
|
|
45
|
+
get_pyproject_dependencies(doc).apply(_format_req)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _format_req(requirement: Requirement, /) -> Requirement:
|
|
49
|
+
return requirement
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
__all__ = ["format_requirements"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from utilities.logging import basic_config
|
|
6
|
+
from utilities.os import is_pytest
|
|
7
|
+
|
|
8
|
+
from actions.logging import LOGGER
|
|
9
|
+
from actions.pre_commit.click import path_argument
|
|
10
|
+
from actions.pre_commit.replace_sequence_strs.lib import replace_sequence_strs
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@path_argument
|
|
17
|
+
def replace_sequence_strs_sub_cmd(*, paths: tuple[Path, ...]) -> None:
|
|
18
|
+
if is_pytest():
|
|
19
|
+
return
|
|
20
|
+
basic_config(obj=LOGGER)
|
|
21
|
+
replace_sequence_strs(*paths)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ["replace_sequence_strs_sub_cmd"]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import TYPE_CHECKING, override
|
|
5
|
+
|
|
6
|
+
from libcst import CSTTransformer, Name, Subscript
|
|
7
|
+
from libcst.matchers import Index as MIndex
|
|
8
|
+
from libcst.matchers import Name as MName
|
|
9
|
+
from libcst.matchers import Subscript as MSubscript
|
|
10
|
+
from libcst.matchers import SubscriptElement as MSubscriptElement
|
|
11
|
+
from libcst.matchers import matches
|
|
12
|
+
from libcst.metadata import MetadataWrapper
|
|
13
|
+
from utilities.text import repr_str, strip_and_dedent
|
|
14
|
+
|
|
15
|
+
from actions import __version__
|
|
16
|
+
from actions.logging import LOGGER
|
|
17
|
+
from actions.pre_commit.utilities import yield_python_file
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from collections.abc import MutableSet
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
from utilities.types import PathLike
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def replace_sequence_strs(*paths: PathLike) -> None:
|
|
27
|
+
LOGGER.info(
|
|
28
|
+
strip_and_dedent("""
|
|
29
|
+
Running '%s' (version %s) with settings:
|
|
30
|
+
- paths = %s
|
|
31
|
+
"""),
|
|
32
|
+
replace_sequence_strs.__name__,
|
|
33
|
+
__version__,
|
|
34
|
+
paths,
|
|
35
|
+
)
|
|
36
|
+
modifications: set[Path] = set()
|
|
37
|
+
for path in paths:
|
|
38
|
+
_format_path(path, modifications=modifications)
|
|
39
|
+
if len(modifications) >= 1:
|
|
40
|
+
LOGGER.info(
|
|
41
|
+
"Exiting due to modifications: %s",
|
|
42
|
+
", ".join(map(repr_str, sorted(modifications))),
|
|
43
|
+
)
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _format_path(
|
|
48
|
+
path: PathLike, /, *, modifications: MutableSet[Path] | None = None
|
|
49
|
+
) -> None:
|
|
50
|
+
with yield_python_file(path, modifications=modifications) as context:
|
|
51
|
+
context.output = MetadataWrapper(context.input).module.visit(
|
|
52
|
+
SequenceToListTransformer()
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SequenceToListTransformer(CSTTransformer):
|
|
57
|
+
@override
|
|
58
|
+
def leave_Subscript(
|
|
59
|
+
self, original_node: Subscript, updated_node: Subscript
|
|
60
|
+
) -> Subscript:
|
|
61
|
+
_ = original_node
|
|
62
|
+
if matches(
|
|
63
|
+
updated_node,
|
|
64
|
+
MSubscript(
|
|
65
|
+
value=MName("Sequence"),
|
|
66
|
+
slice=[MSubscriptElement(slice=MIndex(value=MName("str")))],
|
|
67
|
+
),
|
|
68
|
+
):
|
|
69
|
+
return updated_node.with_changes(value=Name("list"))
|
|
70
|
+
return updated_node
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
__all__ = ["replace_sequence_strs"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from utilities.logging import basic_config
|
|
6
|
+
from utilities.os import is_pytest
|
|
7
|
+
|
|
8
|
+
from actions.logging import LOGGER
|
|
9
|
+
from actions.pre_commit.click import path_argument
|
|
10
|
+
from actions.pre_commit.touch_empty_py.lib import touch_empty_py
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@path_argument
|
|
17
|
+
def touch_empty_py_sub_cmd(*, paths: tuple[Path, ...]) -> None:
|
|
18
|
+
if is_pytest():
|
|
19
|
+
return
|
|
20
|
+
basic_config(obj=LOGGER)
|
|
21
|
+
touch_empty_py(*paths)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ["touch_empty_py_sub_cmd"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from libcst import parse_statement
|
|
7
|
+
from utilities.text import repr_str, strip_and_dedent
|
|
8
|
+
|
|
9
|
+
from actions import __version__
|
|
10
|
+
from actions.logging import LOGGER
|
|
11
|
+
from actions.pre_commit.utilities import yield_python_file
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections.abc import MutableSet
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from utilities.types import PathLike
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def touch_empty_py(*paths: PathLike) -> None:
|
|
21
|
+
LOGGER.info(
|
|
22
|
+
strip_and_dedent("""
|
|
23
|
+
Running '%s' (version %s) with settings:
|
|
24
|
+
- paths = %s
|
|
25
|
+
"""),
|
|
26
|
+
touch_empty_py.__name__,
|
|
27
|
+
__version__,
|
|
28
|
+
paths,
|
|
29
|
+
)
|
|
30
|
+
modifications: set[Path] = set()
|
|
31
|
+
for path in paths:
|
|
32
|
+
_format_path(path, modifications=modifications)
|
|
33
|
+
if len(modifications) >= 1:
|
|
34
|
+
LOGGER.info(
|
|
35
|
+
"Exiting due to modifications: %s",
|
|
36
|
+
", ".join(map(repr_str, sorted(modifications))),
|
|
37
|
+
)
|
|
38
|
+
sys.exit(1)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _format_path(
|
|
42
|
+
path: PathLike, /, *, modifications: MutableSet[Path] | None = None
|
|
43
|
+
) -> None:
|
|
44
|
+
with yield_python_file(path, modifications=modifications) as context:
|
|
45
|
+
if len(context.input.body) >= 1:
|
|
46
|
+
return
|
|
47
|
+
body = [
|
|
48
|
+
*context.input.body,
|
|
49
|
+
parse_statement("from __future__ import annotations"),
|
|
50
|
+
]
|
|
51
|
+
context.output = context.input.with_changes(body=body)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = ["touch_empty_py"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from utilities.logging import basic_config
|
|
6
|
+
from utilities.os import is_pytest
|
|
7
|
+
|
|
8
|
+
from actions.logging import LOGGER
|
|
9
|
+
from actions.pre_commit.click import path_argument
|
|
10
|
+
from actions.pre_commit.touch_py_typed.lib import touch_py_typed
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@path_argument
|
|
17
|
+
def touch_py_typed_sub_cmd(*, paths: tuple[Path, ...]) -> None:
|
|
18
|
+
if is_pytest():
|
|
19
|
+
return
|
|
20
|
+
basic_config(obj=LOGGER)
|
|
21
|
+
touch_py_typed(*paths)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ["touch_py_typed_sub_cmd"]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from utilities.iterables import one
|
|
8
|
+
from utilities.text import repr_str, strip_and_dedent
|
|
9
|
+
|
|
10
|
+
from actions import __version__
|
|
11
|
+
from actions.logging import LOGGER
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections.abc import MutableSet
|
|
15
|
+
|
|
16
|
+
from utilities.types import PathLike
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def touch_py_typed(*paths: PathLike) -> None:
|
|
20
|
+
LOGGER.info(
|
|
21
|
+
strip_and_dedent("""
|
|
22
|
+
Running '%s' (version %s) with settings:
|
|
23
|
+
- paths = %s
|
|
24
|
+
"""),
|
|
25
|
+
touch_py_typed.__name__,
|
|
26
|
+
__version__,
|
|
27
|
+
paths,
|
|
28
|
+
)
|
|
29
|
+
modifications: set[Path] = set()
|
|
30
|
+
for path in paths:
|
|
31
|
+
_format_path(path, modifications=modifications)
|
|
32
|
+
if len(modifications) >= 1:
|
|
33
|
+
LOGGER.info(
|
|
34
|
+
"Exiting due to modifications: %s",
|
|
35
|
+
", ".join(map(repr_str, sorted(modifications))),
|
|
36
|
+
)
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _format_path(
|
|
41
|
+
path: PathLike, /, *, modifications: MutableSet[Path] | None = None
|
|
42
|
+
) -> None:
|
|
43
|
+
path = Path(path)
|
|
44
|
+
if not path.is_file():
|
|
45
|
+
msg = f"Expected a file; {str(path)!r} is not"
|
|
46
|
+
raise FileNotFoundError(msg)
|
|
47
|
+
if path.name != "pyproject.toml":
|
|
48
|
+
msg = f"Expected 'pyproject.toml'; got {str(path)!r}"
|
|
49
|
+
raise TypeError(msg)
|
|
50
|
+
src = path.parent / "src"
|
|
51
|
+
if not src.exists():
|
|
52
|
+
return
|
|
53
|
+
if not src.is_dir():
|
|
54
|
+
msg = f"Expected a directory; {str(src)!r} is not"
|
|
55
|
+
raise NotADirectoryError(msg)
|
|
56
|
+
non_tests = one(p for p in src.iterdir() if p.name != "tests")
|
|
57
|
+
py_typed = non_tests / "py.typed"
|
|
58
|
+
if not py_typed.exists():
|
|
59
|
+
py_typed.touch()
|
|
60
|
+
if modifications is not None:
|
|
61
|
+
modifications.add(py_typed)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
__all__ = ["touch_py_typed"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from dataclasses import dataclass, field, replace
|
|
5
|
+
from functools import total_ordering
|
|
6
|
+
from typing import Any, Self, override
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
from utilities.version import (
|
|
10
|
+
ParseVersionError,
|
|
11
|
+
_VersionEmptySuffixError,
|
|
12
|
+
_VersionNegativeMajorVersionError,
|
|
13
|
+
_VersionNegativeMinorVersionError,
|
|
14
|
+
_VersionZeroError,
|
|
15
|
+
)
|
|
16
|
+
from utilities.version import Version as Version3
|
|
17
|
+
from utilities.version import parse_version as parse_version3
|
|
18
|
+
|
|
19
|
+
type TwoSidedVersions = tuple[Version2or3 | None, Version1or2 | None]
|
|
20
|
+
type Version1or2 = int | Version2
|
|
21
|
+
type Version2or3 = Version2 | Version3
|
|
22
|
+
type VersionSet = dict[str, Version2or3]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PipListOutdatedOutput(BaseModel):
|
|
26
|
+
name: str
|
|
27
|
+
version: str
|
|
28
|
+
latest_version: str
|
|
29
|
+
latest_filetype: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(repr=False, frozen=True, slots=True)
|
|
36
|
+
@total_ordering
|
|
37
|
+
class Version2:
|
|
38
|
+
"""A version identifier."""
|
|
39
|
+
|
|
40
|
+
major: int = 0
|
|
41
|
+
minor: int = 0
|
|
42
|
+
suffix: str | None = field(default=None, kw_only=True)
|
|
43
|
+
|
|
44
|
+
def __post_init__(self) -> None:
|
|
45
|
+
if (self.major == 0) and (self.minor == 0):
|
|
46
|
+
raise _VersionZeroError(major=self.major, minor=self.minor, patch=0)
|
|
47
|
+
if self.major < 0:
|
|
48
|
+
raise _VersionNegativeMajorVersionError(major=self.major)
|
|
49
|
+
if self.minor < 0:
|
|
50
|
+
raise _VersionNegativeMinorVersionError(minor=self.minor)
|
|
51
|
+
if (self.suffix is not None) and (len(self.suffix) == 0):
|
|
52
|
+
raise _VersionEmptySuffixError(suffix=self.suffix)
|
|
53
|
+
|
|
54
|
+
def __le__(self, other: Any, /) -> bool:
|
|
55
|
+
if not isinstance(other, type(self)):
|
|
56
|
+
return NotImplemented
|
|
57
|
+
self_as_tuple = (self.major, self.minor)
|
|
58
|
+
other_as_tuple = (other.major, other.minor)
|
|
59
|
+
return self_as_tuple <= other_as_tuple
|
|
60
|
+
|
|
61
|
+
@override
|
|
62
|
+
def __repr__(self) -> str:
|
|
63
|
+
version = f"{self.major}.{self.minor}"
|
|
64
|
+
if self.suffix is not None:
|
|
65
|
+
version = f"{version}-{self.suffix}"
|
|
66
|
+
return version
|
|
67
|
+
|
|
68
|
+
def bump_major(self) -> Self:
|
|
69
|
+
return type(self)(self.major + 1, 0)
|
|
70
|
+
|
|
71
|
+
def bump_minor(self) -> Self:
|
|
72
|
+
return type(self)(self.major, self.minor + 1)
|
|
73
|
+
|
|
74
|
+
def with_suffix(self, *, suffix: str | None = None) -> Self:
|
|
75
|
+
return replace(self, suffix=suffix)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def parse_version1_or_2(version: str, /) -> Version1or2:
|
|
79
|
+
try:
|
|
80
|
+
return parse_version2(version)
|
|
81
|
+
except ParseVersionError:
|
|
82
|
+
return int(version)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def parse_version2_or_3(version: str, /) -> Version2or3:
|
|
86
|
+
try:
|
|
87
|
+
return parse_version3(version)
|
|
88
|
+
except ParseVersionError:
|
|
89
|
+
return parse_version2(version)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def parse_version2(version: str, /) -> Version2:
|
|
93
|
+
try:
|
|
94
|
+
((major, minor, suffix),) = _PARSE_VERSION2_PATTERN.findall(version)
|
|
95
|
+
except ValueError:
|
|
96
|
+
raise ParseVersionError(version=version) from None
|
|
97
|
+
return Version2(int(major), int(minor), suffix=None if suffix == "" else suffix)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
_PARSE_VERSION2_PATTERN = re.compile(r"^(\d+)\.(\d+)(?:-(\w+))?")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
_ = PipListOutdatedOutput.model_rebuild()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
__all__ = [
|
|
107
|
+
"PipListOutdatedOutput",
|
|
108
|
+
"TwoSidedVersions",
|
|
109
|
+
"Version1or2",
|
|
110
|
+
"Version2",
|
|
111
|
+
"Version2or3",
|
|
112
|
+
"Version3",
|
|
113
|
+
"VersionSet",
|
|
114
|
+
"parse_version1_or_2",
|
|
115
|
+
"parse_version2",
|
|
116
|
+
"parse_version2_or_3",
|
|
117
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from utilities.logging import basic_config
|
|
6
|
+
from utilities.os import is_pytest
|
|
7
|
+
|
|
8
|
+
from actions.logging import LOGGER
|
|
9
|
+
from actions.pre_commit.click import path_argument
|
|
10
|
+
from actions.pre_commit.update_requirements.lib import update_requirements
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@path_argument
|
|
17
|
+
def update_requirements_sub_cmd(*, paths: tuple[Path, ...]) -> None:
|
|
18
|
+
if is_pytest():
|
|
19
|
+
return
|
|
20
|
+
basic_config(obj=LOGGER)
|
|
21
|
+
update_requirements(*paths)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ["update_requirements_sub_cmd"]
|