dycw-actions 0.11.3__py3-none-any.whl → 0.15.3__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/cli.py +7 -1
- actions/pre_commit/conformalize_repo/cli.py +1 -1
- actions/pre_commit/conformalize_repo/constants.py +1 -1
- actions/pre_commit/conformalize_repo/lib.py +129 -109
- actions/pre_commit/conformalize_repo/settings.py +3 -3
- actions/pre_commit/constants.py +3 -3
- actions/pre_commit/touch_empty_py/lib.py +2 -2
- actions/pre_commit/touch_py_typed/lib.py +4 -3
- actions/pre_commit/update_requirements/cli.py +10 -2
- actions/pre_commit/update_requirements/lib.py +104 -15
- actions/pre_commit/update_requirements/settings.py +23 -0
- actions/pre_commit/utilities.py +141 -42
- actions/publish_package/lib.py +17 -11
- actions/random_sleep/lib.py +3 -3
- actions/re_encrypt/__init__.py +1 -0
- actions/re_encrypt/cli.py +36 -0
- actions/re_encrypt/constants.py +7 -0
- actions/re_encrypt/lib.py +115 -0
- actions/re_encrypt/settings.py +26 -0
- actions/register_gitea_runner/settings.py +1 -2
- actions/run_hooks/lib.py +13 -11
- actions/setup_cronjob/settings.py +1 -1
- actions/types.py +5 -9
- actions/utilities.py +0 -16
- dycw_actions-0.15.3.dist-info/METADATA +45 -0
- {dycw_actions-0.11.3.dist-info → dycw_actions-0.15.3.dist-info}/RECORD +29 -23
- {dycw_actions-0.11.3.dist-info → dycw_actions-0.15.3.dist-info}/WHEEL +2 -2
- dycw_actions-0.15.3.dist-info/entry_points.txt +3 -0
- dycw_actions-0.11.3.dist-info/METADATA +0 -24
- dycw_actions-0.11.3.dist-info/entry_points.txt +0 -3
|
@@ -115,9 +115,6 @@ class Settings:
|
|
|
115
115
|
default=False,
|
|
116
116
|
help="Set up 'pyproject.toml' [project.optional-dependencies.scripts]",
|
|
117
117
|
)
|
|
118
|
-
pyproject__tool__uv__indexes: list[tuple[str, str]] = option(
|
|
119
|
-
factory=list, help="Set up 'pyproject.toml' [[uv.tool.index]]"
|
|
120
|
-
)
|
|
121
118
|
pyright: bool = option(default=False, help="Set up 'pyrightconfig.json'")
|
|
122
119
|
pytest: bool = option(default=False, help="Set up 'pytest.toml'")
|
|
123
120
|
pytest__asyncio: bool = option(default=False, help="Set up 'pytest.toml' asyncio_*")
|
|
@@ -135,6 +132,9 @@ class Settings:
|
|
|
135
132
|
repo_name: str | None = option(default=None, help="Repo name")
|
|
136
133
|
ruff: bool = option(default=False, help="Set up 'ruff.toml'")
|
|
137
134
|
run_version_bump: bool = option(default=RUN_VERSION_BUMP, help="Run version bump")
|
|
135
|
+
uv__indexes: list[tuple[str, str]] = option(
|
|
136
|
+
factory=list, help="Set up 'uv' with index indexes"
|
|
137
|
+
)
|
|
138
138
|
uv__native_tls: bool = option(default=False, help="Setup 'uv' with native TLS")
|
|
139
139
|
script: str | None = option(
|
|
140
140
|
default=None, help="Set up a script instead of a package"
|
actions/pre_commit/constants.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from utilities.
|
|
3
|
+
from utilities.constants import HOUR
|
|
4
4
|
|
|
5
5
|
from actions.constants import PATH_ACTIONS
|
|
6
6
|
|
|
7
7
|
PATH_PRE_COMMIT = PATH_ACTIONS / "pre_commit"
|
|
8
|
-
|
|
8
|
+
THROTTLE_DURATION = 12 * HOUR
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
__all__ = ["PATH_PRE_COMMIT", "
|
|
11
|
+
__all__ = ["PATH_PRE_COMMIT", "THROTTLE_DURATION"]
|
|
@@ -11,7 +11,7 @@ from utilities.throttle import throttle
|
|
|
11
11
|
|
|
12
12
|
from actions import __version__
|
|
13
13
|
from actions.logging import LOGGER
|
|
14
|
-
from actions.pre_commit.constants import
|
|
14
|
+
from actions.pre_commit.constants import THROTTLE_DURATION
|
|
15
15
|
from actions.pre_commit.utilities import path_throttle_cache, yield_python_file
|
|
16
16
|
|
|
17
17
|
if TYPE_CHECKING:
|
|
@@ -36,7 +36,7 @@ def _touch_empty_py(*paths: PathLike) -> None:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
touch_empty_py = throttle(
|
|
39
|
-
|
|
39
|
+
duration=THROTTLE_DURATION, path=path_throttle_cache(_touch_empty_py)
|
|
40
40
|
)(_touch_empty_py)
|
|
41
41
|
|
|
42
42
|
|
|
@@ -11,8 +11,9 @@ from utilities.text import repr_str
|
|
|
11
11
|
from utilities.throttle import throttle
|
|
12
12
|
|
|
13
13
|
from actions import __version__
|
|
14
|
+
from actions.constants import PYPROJECT_TOML
|
|
14
15
|
from actions.logging import LOGGER
|
|
15
|
-
from actions.pre_commit.constants import
|
|
16
|
+
from actions.pre_commit.constants import THROTTLE_DURATION
|
|
16
17
|
from actions.pre_commit.utilities import path_throttle_cache
|
|
17
18
|
|
|
18
19
|
if TYPE_CHECKING:
|
|
@@ -36,7 +37,7 @@ def _touch_py_typed(*paths: PathLike) -> None:
|
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
touch_py_typed = throttle(
|
|
39
|
-
|
|
40
|
+
duration=THROTTLE_DURATION, path=path_throttle_cache(_touch_py_typed)
|
|
40
41
|
)(_touch_py_typed)
|
|
41
42
|
|
|
42
43
|
|
|
@@ -47,7 +48,7 @@ def _format_path(
|
|
|
47
48
|
if not path.is_file():
|
|
48
49
|
msg = f"Expected a file; {str(path)!r} is not"
|
|
49
50
|
raise FileNotFoundError(msg)
|
|
50
|
-
if path.name !=
|
|
51
|
+
if path.name != PYPROJECT_TOML.name:
|
|
51
52
|
msg = f"Expected 'pyproject.toml'; got {str(path)!r}"
|
|
52
53
|
raise TypeError(msg)
|
|
53
54
|
src = path.parent / "src"
|
|
@@ -2,23 +2,31 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
+
from typed_settings import click_options
|
|
5
6
|
from utilities.logging import basic_config
|
|
6
7
|
from utilities.os import is_pytest
|
|
7
8
|
|
|
8
9
|
from actions.logging import LOGGER
|
|
9
10
|
from actions.pre_commit.click import path_argument
|
|
10
11
|
from actions.pre_commit.update_requirements.lib import update_requirements
|
|
12
|
+
from actions.pre_commit.update_requirements.settings import Settings
|
|
13
|
+
from actions.utilities import LOADER
|
|
11
14
|
|
|
12
15
|
if TYPE_CHECKING:
|
|
13
16
|
from pathlib import Path
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
@path_argument
|
|
17
|
-
|
|
20
|
+
@click_options(Settings, [LOADER], show_envvars_in_help=True)
|
|
21
|
+
def update_requirements_sub_cmd(
|
|
22
|
+
settings: Settings, /, *, paths: tuple[Path, ...]
|
|
23
|
+
) -> None:
|
|
18
24
|
if is_pytest():
|
|
19
25
|
return
|
|
20
26
|
basic_config(obj=LOGGER)
|
|
21
|
-
update_requirements(
|
|
27
|
+
update_requirements(
|
|
28
|
+
*paths, indexes=settings.indexes, native_tls=settings.native_tls
|
|
29
|
+
)
|
|
22
30
|
|
|
23
31
|
|
|
24
32
|
__all__ = ["update_requirements_sub_cmd"]
|
|
@@ -4,8 +4,11 @@ import sys
|
|
|
4
4
|
from functools import partial
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from ordered_set import OrderedSet
|
|
7
8
|
from pydantic import TypeAdapter
|
|
8
|
-
from
|
|
9
|
+
from tomlkit import string
|
|
10
|
+
from utilities.functions import ensure_str, get_func_name, max_nullable
|
|
11
|
+
from utilities.packaging import Requirement
|
|
9
12
|
from utilities.tabulate import func_param_desc
|
|
10
13
|
from utilities.text import repr_str
|
|
11
14
|
|
|
@@ -20,24 +23,47 @@ from actions.pre_commit.update_requirements.classes import (
|
|
|
20
23
|
parse_version1_or_2,
|
|
21
24
|
parse_version2_or_3,
|
|
22
25
|
)
|
|
23
|
-
from actions.pre_commit.
|
|
26
|
+
from actions.pre_commit.update_requirements.settings import SETTINGS
|
|
27
|
+
from actions.pre_commit.utilities import (
|
|
28
|
+
get_aot,
|
|
29
|
+
get_pyproject_dependencies,
|
|
30
|
+
get_set_array,
|
|
31
|
+
get_set_table,
|
|
32
|
+
get_table,
|
|
33
|
+
yield_pyproject_toml,
|
|
34
|
+
yield_toml_doc,
|
|
35
|
+
)
|
|
24
36
|
from actions.utilities import logged_run
|
|
25
37
|
|
|
26
38
|
if TYPE_CHECKING:
|
|
27
|
-
from collections.abc import MutableSet
|
|
39
|
+
from collections.abc import Iterator, MutableSet
|
|
28
40
|
from pathlib import Path
|
|
29
41
|
|
|
30
|
-
from
|
|
42
|
+
from tomlkit import TOMLDocument
|
|
31
43
|
from utilities.types import PathLike, StrDict
|
|
32
44
|
|
|
33
45
|
from actions.pre_commit.update_requirements.classes import Version2or3, VersionSet
|
|
34
46
|
|
|
35
47
|
|
|
36
|
-
def update_requirements(
|
|
37
|
-
|
|
48
|
+
def update_requirements(
|
|
49
|
+
*paths: PathLike,
|
|
50
|
+
indexes: list[str] | None = SETTINGS.indexes,
|
|
51
|
+
native_tls: bool = SETTINGS.native_tls,
|
|
52
|
+
) -> None:
|
|
53
|
+
LOGGER.info(
|
|
54
|
+
func_param_desc(
|
|
55
|
+
update_requirements,
|
|
56
|
+
__version__,
|
|
57
|
+
f"{paths=}",
|
|
58
|
+
f"{indexes=}",
|
|
59
|
+
f"{native_tls=}",
|
|
60
|
+
)
|
|
61
|
+
)
|
|
38
62
|
modifications: set[Path] = set()
|
|
39
63
|
for path in paths:
|
|
40
|
-
_format_path(
|
|
64
|
+
_format_path(
|
|
65
|
+
path, indexes=indexes, native_tls=native_tls, modifications=modifications
|
|
66
|
+
)
|
|
41
67
|
if len(modifications) >= 1:
|
|
42
68
|
LOGGER.info(
|
|
43
69
|
"Exiting due to modifications: %s",
|
|
@@ -52,24 +78,41 @@ def _format_path(
|
|
|
52
78
|
/,
|
|
53
79
|
*,
|
|
54
80
|
versions: VersionSet | None = None,
|
|
81
|
+
indexes: list[str] | None = SETTINGS.indexes,
|
|
82
|
+
native_tls: bool = SETTINGS.native_tls,
|
|
55
83
|
modifications: MutableSet[Path] | None = None,
|
|
56
84
|
) -> None:
|
|
57
|
-
versions_use =
|
|
85
|
+
versions_use = (
|
|
86
|
+
_get_versions(indexes=indexes, native_tls=native_tls)
|
|
87
|
+
if versions is None
|
|
88
|
+
else versions
|
|
89
|
+
)
|
|
58
90
|
with yield_toml_doc(path, modifications=modifications) as doc:
|
|
59
91
|
get_pyproject_dependencies(doc).apply(
|
|
60
92
|
partial(_format_req, versions=versions_use)
|
|
61
93
|
)
|
|
94
|
+
_pin_cli_dependencies(doc, versions_use)
|
|
62
95
|
|
|
63
96
|
|
|
64
|
-
def _get_versions(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
97
|
+
def _get_versions(
|
|
98
|
+
*,
|
|
99
|
+
indexes: list[str] | None = SETTINGS.indexes,
|
|
100
|
+
native_tls: bool = SETTINGS.native_tls,
|
|
101
|
+
) -> VersionSet:
|
|
102
|
+
index_args: OrderedSet[str] = OrderedSet([])
|
|
103
|
+
_ = index_args.update(list(_yield_indexes()))
|
|
104
|
+
if indexes is not None:
|
|
105
|
+
_ = index_args.update(indexes)
|
|
106
|
+
head: list[str] = ["uv", "pip", "list", "--format", "json"]
|
|
107
|
+
tail: list[str] = ["--strict"]
|
|
108
|
+
if len(index_args) >= 1:
|
|
109
|
+
tail.extend(["--index", ",".join(index_args)])
|
|
110
|
+
if native_tls:
|
|
111
|
+
tail.append("--native-tls")
|
|
112
|
+
json1 = logged_run(*head, *tail, return_=True)
|
|
68
113
|
models1 = TypeAdapter(list[PipListOutput]).validate_json(json1)
|
|
69
114
|
versions1 = {p.name: parse_version2_or_3(p.version) for p in models1}
|
|
70
|
-
json2 = logged_run(
|
|
71
|
-
"uv", "pip", "list", "--format", "json", "--outdated", "--strict", return_=True
|
|
72
|
-
)
|
|
115
|
+
json2 = logged_run(*head, "--outdated", *tail, return_=True)
|
|
73
116
|
models2 = TypeAdapter(list[PipListOutdatedOutput]).validate_json(json2)
|
|
74
117
|
versions2 = {p.name: parse_version2_or_3(p.latest_version) for p in models2}
|
|
75
118
|
out: StrDict = {}
|
|
@@ -78,6 +121,28 @@ def _get_versions() -> VersionSet:
|
|
|
78
121
|
return out
|
|
79
122
|
|
|
80
123
|
|
|
124
|
+
def _yield_indexes() -> Iterator[str]:
|
|
125
|
+
try:
|
|
126
|
+
with yield_pyproject_toml() as doc:
|
|
127
|
+
try:
|
|
128
|
+
tool = get_table(doc, "tool")
|
|
129
|
+
except KeyError:
|
|
130
|
+
return
|
|
131
|
+
try:
|
|
132
|
+
uv = get_table(tool, "uv")
|
|
133
|
+
except KeyError:
|
|
134
|
+
return
|
|
135
|
+
try:
|
|
136
|
+
indexes = get_aot(uv, "index")
|
|
137
|
+
except KeyError:
|
|
138
|
+
return
|
|
139
|
+
else:
|
|
140
|
+
for index in indexes:
|
|
141
|
+
yield ensure_str(index["url"])
|
|
142
|
+
except FileNotFoundError:
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
|
|
81
146
|
def _format_req(requirement: Requirement, /, *, versions: VersionSet) -> Requirement:
|
|
82
147
|
try:
|
|
83
148
|
lower = parse_version2_or_3(requirement[">="])
|
|
@@ -130,4 +195,28 @@ def _format_req(requirement: Requirement, /, *, versions: VersionSet) -> Require
|
|
|
130
195
|
return requirement
|
|
131
196
|
|
|
132
197
|
|
|
198
|
+
def _pin_cli_dependencies(doc: TOMLDocument, versions: VersionSet, /) -> None:
|
|
199
|
+
try:
|
|
200
|
+
project = get_table(doc, "project")
|
|
201
|
+
except KeyError:
|
|
202
|
+
return
|
|
203
|
+
try:
|
|
204
|
+
_ = get_table(project, "scripts")
|
|
205
|
+
except KeyError:
|
|
206
|
+
return
|
|
207
|
+
dependencies = get_set_array(project, "dependencies")
|
|
208
|
+
opt_dependencies = get_set_table(project, "optional-dependencies")
|
|
209
|
+
cli = get_set_array(opt_dependencies, "cli")
|
|
210
|
+
cli.clear()
|
|
211
|
+
for dep in dependencies:
|
|
212
|
+
req = Requirement(dep)
|
|
213
|
+
try:
|
|
214
|
+
version = versions[req.name]
|
|
215
|
+
except KeyError:
|
|
216
|
+
pass
|
|
217
|
+
else:
|
|
218
|
+
req = req.replace(">=", None).replace("<", None).replace("==", str(version))
|
|
219
|
+
cli.append(string(str(req)))
|
|
220
|
+
|
|
221
|
+
|
|
133
222
|
__all__ = ["update_requirements"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typed_settings import load_settings, option, settings
|
|
4
|
+
|
|
5
|
+
from actions.utilities import LOADER
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@settings
|
|
9
|
+
class Settings:
|
|
10
|
+
indexes: list[str] | None = option(
|
|
11
|
+
factory=list,
|
|
12
|
+
help="List of URLs as additional indexes when searching for packages",
|
|
13
|
+
)
|
|
14
|
+
native_tls: bool = option(
|
|
15
|
+
default=False,
|
|
16
|
+
help="Whether to load TLS certificates from the platform's native certificate store",
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
SETTINGS = load_settings(Settings, [LOADER])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = ["SETTINGS", "Settings"]
|
actions/pre_commit/utilities.py
CHANGED
|
@@ -2,10 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from collections.abc import Iterator, MutableSet
|
|
5
|
-
from contextlib import contextmanager
|
|
5
|
+
from contextlib import contextmanager, suppress
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import TYPE_CHECKING, Any, assert_never
|
|
8
|
+
from typing import TYPE_CHECKING, Any, assert_never, overload
|
|
9
9
|
|
|
10
10
|
import tomlkit
|
|
11
11
|
from libcst import Module, parse_module
|
|
@@ -16,8 +16,9 @@ from utilities.functions import ensure_class, ensure_str, get_func_name
|
|
|
16
16
|
from utilities.iterables import OneEmptyError, OneNonUniqueError, one
|
|
17
17
|
from utilities.packaging import Requirement
|
|
18
18
|
from utilities.types import PathLike, StrDict
|
|
19
|
+
from utilities.typing import is_str_dict
|
|
19
20
|
|
|
20
|
-
from actions.constants import PATH_CACHE, YAML_INSTANCE
|
|
21
|
+
from actions.constants import PATH_CACHE, PYPROJECT_TOML, YAML_INSTANCE
|
|
21
22
|
from actions.logging import LOGGER
|
|
22
23
|
from actions.utilities import are_equal_modulo_new_line, write_text, yaml_dump
|
|
23
24
|
|
|
@@ -26,26 +27,26 @@ if TYPE_CHECKING:
|
|
|
26
27
|
|
|
27
28
|
from utilities.types import PathLike, StrDict
|
|
28
29
|
|
|
29
|
-
from actions.types import
|
|
30
|
+
from actions.types import ArrayLike, ContainerLike, FuncRequirement
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
for table_ in tables:
|
|
34
|
-
if table_ not in array:
|
|
35
|
-
array.append(table_)
|
|
33
|
+
##
|
|
36
34
|
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
@overload
|
|
37
|
+
def ensure_contains(container: AoT, /, *objs: Table) -> None: ...
|
|
38
|
+
@overload
|
|
39
|
+
def ensure_contains(container: list[str], /, *objs: str) -> None: ...
|
|
40
|
+
@overload
|
|
41
|
+
def ensure_contains(container: list[StrDict], /, *objs: StrDict) -> None: ...
|
|
42
|
+
def ensure_contains(container: ArrayLike, /, *objs: Any) -> None:
|
|
42
43
|
for obj in objs:
|
|
43
|
-
if obj not in
|
|
44
|
-
|
|
44
|
+
if obj not in container:
|
|
45
|
+
container.append(obj)
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def ensure_contains_partial_dict(
|
|
48
|
-
container:
|
|
49
|
+
container: list[StrDict], partial: StrDict, /, *, extra: StrDict | None = None
|
|
49
50
|
) -> StrDict:
|
|
50
51
|
try:
|
|
51
52
|
return get_partial_dict(container, partial, skip_log=True)
|
|
@@ -55,52 +56,123 @@ def ensure_contains_partial_dict(
|
|
|
55
56
|
return dict_
|
|
56
57
|
|
|
57
58
|
|
|
58
|
-
def ensure_contains_partial_str(
|
|
59
|
+
def ensure_contains_partial_str(list_: Array | list[str], text: str, /) -> str:
|
|
59
60
|
try:
|
|
60
|
-
return get_partial_str(
|
|
61
|
+
return get_partial_str(list_, text, skip_log=True)
|
|
61
62
|
except OneEmptyError:
|
|
62
|
-
|
|
63
|
+
list_.append(text)
|
|
63
64
|
return text
|
|
64
65
|
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
@overload
|
|
68
|
+
def ensure_not_contains(container: AoT, /, *objs: Table) -> None: ...
|
|
69
|
+
@overload
|
|
70
|
+
def ensure_not_contains(container: list[str], /, *objs: str) -> None: ...
|
|
71
|
+
@overload
|
|
72
|
+
def ensure_not_contains(container: list[StrDict], /, *objs: StrDict) -> None: ...
|
|
73
|
+
def ensure_not_contains(container: ArrayLike, /, *objs: Any) -> None:
|
|
67
74
|
for obj in objs:
|
|
68
75
|
try:
|
|
69
|
-
index = next(i for i, o in enumerate(
|
|
76
|
+
index = next(i for i, o in enumerate(container) if o == obj)
|
|
70
77
|
except StopIteration:
|
|
71
78
|
pass
|
|
72
79
|
else:
|
|
73
|
-
del
|
|
80
|
+
del container[index]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def get_aot(container: ContainerLike, key: str, /) -> AoT:
|
|
87
|
+
return ensure_class(container[key], AoT)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_array(container: ContainerLike, key: str, /) -> Array:
|
|
91
|
+
return ensure_class(container[key], Array)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_dict(dict_: StrDict, key: str, /) -> StrDict:
|
|
95
|
+
if is_str_dict(value := dict_[key]):
|
|
96
|
+
return value
|
|
97
|
+
raise TypeError(value)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_list_dicts(dict_: StrDict, key: str, /) -> list[StrDict]:
|
|
101
|
+
list_ = ensure_class(dict_[key], list)
|
|
102
|
+
for i in list_:
|
|
103
|
+
if not is_str_dict(i):
|
|
104
|
+
raise TypeError(i)
|
|
105
|
+
return list_
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_list_strs(dict_: StrDict, key: str, /) -> list[str]:
|
|
109
|
+
list_ = ensure_class(dict_[key], list)
|
|
110
|
+
for i in list_:
|
|
111
|
+
if not isinstance(i, str):
|
|
112
|
+
raise TypeError(i)
|
|
113
|
+
return list_
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def get_table(container: ContainerLike, key: str, /) -> Table:
|
|
117
|
+
return ensure_class(container[key], Table)
|
|
74
118
|
|
|
75
119
|
|
|
76
120
|
##
|
|
77
121
|
|
|
78
122
|
|
|
79
|
-
def
|
|
80
|
-
|
|
123
|
+
def get_set_aot(container: ContainerLike, key: str, /) -> AoT:
|
|
124
|
+
try:
|
|
125
|
+
return get_aot(container, key)
|
|
126
|
+
except KeyError:
|
|
127
|
+
value = container[key] = aot()
|
|
128
|
+
return value
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_set_array(container: ContainerLike, key: str, /) -> Array:
|
|
132
|
+
try:
|
|
133
|
+
return get_array(container, key)
|
|
134
|
+
except KeyError:
|
|
135
|
+
value = container[key] = array()
|
|
136
|
+
return value
|
|
81
137
|
|
|
82
138
|
|
|
83
|
-
def
|
|
84
|
-
|
|
139
|
+
def get_set_dict(dict_: StrDict, key: str, /) -> StrDict:
|
|
140
|
+
try:
|
|
141
|
+
return get_dict(dict_, key)
|
|
142
|
+
except KeyError:
|
|
143
|
+
value = dict_[key] = {}
|
|
144
|
+
return value
|
|
85
145
|
|
|
86
146
|
|
|
87
|
-
def
|
|
88
|
-
|
|
147
|
+
def get_set_list_dicts(dict_: StrDict, key: str, /) -> list[StrDict]:
|
|
148
|
+
try:
|
|
149
|
+
return get_list_dicts(dict_, key)
|
|
150
|
+
except KeyError:
|
|
151
|
+
value = dict_[key] = []
|
|
152
|
+
return value
|
|
89
153
|
|
|
90
154
|
|
|
91
|
-
def
|
|
92
|
-
|
|
155
|
+
def get_set_list_strs(dict_: StrDict, key: str, /) -> list[str]:
|
|
156
|
+
try:
|
|
157
|
+
return get_list_strs(dict_, key)
|
|
158
|
+
except KeyError:
|
|
159
|
+
value = dict_[key] = []
|
|
160
|
+
return value
|
|
93
161
|
|
|
94
162
|
|
|
95
|
-
def
|
|
96
|
-
|
|
163
|
+
def get_set_table(container: ContainerLike, key: str, /) -> Table:
|
|
164
|
+
try:
|
|
165
|
+
return get_table(container, key)
|
|
166
|
+
except KeyError:
|
|
167
|
+
value = container[key] = table()
|
|
168
|
+
return value
|
|
97
169
|
|
|
98
170
|
|
|
99
171
|
##
|
|
100
172
|
|
|
101
173
|
|
|
102
174
|
def get_partial_dict(
|
|
103
|
-
iterable: Iterable[
|
|
175
|
+
iterable: Iterable[StrDict], dict_: StrDict, /, *, skip_log: bool = False
|
|
104
176
|
) -> StrDict:
|
|
105
177
|
try:
|
|
106
178
|
return one(i for i in iterable if is_partial_dict(dict_, i))
|
|
@@ -176,17 +248,26 @@ def is_partial_str(obj: Any, text: str, /) -> bool:
|
|
|
176
248
|
|
|
177
249
|
def get_pyproject_dependencies(doc: TOMLDocument, /) -> PyProjectDependencies:
|
|
178
250
|
out = PyProjectDependencies()
|
|
179
|
-
|
|
180
|
-
project = get_table(doc,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
251
|
+
try:
|
|
252
|
+
project = get_table(doc, "project")
|
|
253
|
+
except KeyError:
|
|
254
|
+
pass
|
|
255
|
+
else:
|
|
256
|
+
with suppress(KeyError):
|
|
257
|
+
out.dependencies = get_array(project, "dependencies")
|
|
258
|
+
try:
|
|
259
|
+
opt_dependencies = get_table(project, "optional-dependencies")
|
|
260
|
+
except KeyError:
|
|
261
|
+
pass
|
|
262
|
+
else:
|
|
185
263
|
out.opt_dependencies = {}
|
|
186
264
|
for key in opt_dependencies:
|
|
187
265
|
out.opt_dependencies[ensure_str(key)] = get_array(opt_dependencies, key)
|
|
188
|
-
|
|
189
|
-
dep_grps = get_table(doc,
|
|
266
|
+
try:
|
|
267
|
+
dep_grps = get_table(doc, "dependency-groups")
|
|
268
|
+
except KeyError:
|
|
269
|
+
pass
|
|
270
|
+
else:
|
|
190
271
|
out.dep_groups = {}
|
|
191
272
|
for key in dep_grps:
|
|
192
273
|
out.dep_groups[ensure_str(key)] = get_array(dep_grps, key)
|
|
@@ -295,6 +376,17 @@ def yield_json_dict(
|
|
|
295
376
|
##
|
|
296
377
|
|
|
297
378
|
|
|
379
|
+
@contextmanager
|
|
380
|
+
def yield_pyproject_toml(
|
|
381
|
+
*, modifications: MutableSet[Path] | None = None
|
|
382
|
+
) -> Iterator[TOMLDocument]:
|
|
383
|
+
with yield_toml_doc(PYPROJECT_TOML, modifications=modifications) as doc:
|
|
384
|
+
yield doc
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
##
|
|
388
|
+
|
|
389
|
+
|
|
298
390
|
@contextmanager
|
|
299
391
|
def yield_mutable_write_context[T](
|
|
300
392
|
path: PathLike,
|
|
@@ -370,7 +462,6 @@ def yield_yaml_dict(
|
|
|
370
462
|
__all__ = [
|
|
371
463
|
"PyProjectDependencies",
|
|
372
464
|
"WriteContext",
|
|
373
|
-
"ensure_aot_contains",
|
|
374
465
|
"ensure_contains",
|
|
375
466
|
"ensure_contains_partial_dict",
|
|
376
467
|
"ensure_contains_partial_str",
|
|
@@ -378,10 +469,17 @@ __all__ = [
|
|
|
378
469
|
"get_aot",
|
|
379
470
|
"get_array",
|
|
380
471
|
"get_dict",
|
|
381
|
-
"
|
|
472
|
+
"get_list_dicts",
|
|
473
|
+
"get_list_strs",
|
|
382
474
|
"get_partial_dict",
|
|
383
475
|
"get_partial_str",
|
|
384
476
|
"get_pyproject_dependencies",
|
|
477
|
+
"get_set_aot",
|
|
478
|
+
"get_set_array",
|
|
479
|
+
"get_set_dict",
|
|
480
|
+
"get_set_list_dicts",
|
|
481
|
+
"get_set_list_strs",
|
|
482
|
+
"get_set_table",
|
|
385
483
|
"get_table",
|
|
386
484
|
"is_partial_dict",
|
|
387
485
|
"is_partial_str",
|
|
@@ -389,6 +487,7 @@ __all__ = [
|
|
|
389
487
|
"yield_immutable_write_context",
|
|
390
488
|
"yield_json_dict",
|
|
391
489
|
"yield_mutable_write_context",
|
|
490
|
+
"yield_pyproject_toml",
|
|
392
491
|
"yield_python_file",
|
|
393
492
|
"yield_text_file",
|
|
394
493
|
"yield_toml_doc",
|
actions/publish_package/lib.py
CHANGED
|
@@ -14,6 +14,8 @@ from actions.utilities import logged_run
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from typed_settings import Secret
|
|
16
16
|
|
|
17
|
+
from actions.types import SecretLike
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
def publish_package(
|
|
19
21
|
*,
|
|
@@ -34,18 +36,22 @@ def publish_package(
|
|
|
34
36
|
f"{native_tls=}",
|
|
35
37
|
)
|
|
36
38
|
)
|
|
39
|
+
build_head: list[str] = ["uv", "build", "--out-dir"]
|
|
40
|
+
build_tail: list[str] = ["--wheel", "--clear"]
|
|
41
|
+
publish: list[SecretLike] = ["uv", "publish"]
|
|
42
|
+
if username is not None:
|
|
43
|
+
publish.extend(["--username", username])
|
|
44
|
+
if password is not None:
|
|
45
|
+
publish.extend(["--password", password])
|
|
46
|
+
if publish_url is not None:
|
|
47
|
+
publish.extend(["--publish-url", publish_url])
|
|
48
|
+
if trusted_publishing:
|
|
49
|
+
publish.extend(["--trusted-publishing", "always"])
|
|
50
|
+
if native_tls:
|
|
51
|
+
publish.append("--native-tls")
|
|
37
52
|
with TemporaryDirectory() as temp:
|
|
38
|
-
logged_run(
|
|
39
|
-
logged_run(
|
|
40
|
-
"uv",
|
|
41
|
-
"publish",
|
|
42
|
-
*([] if username is None else ["--username", username]),
|
|
43
|
-
*([] if password is None else ["--password", password]),
|
|
44
|
-
*([] if publish_url is None else ["--publish-url", publish_url]),
|
|
45
|
-
*(["--trusted-publishing", "always"] if trusted_publishing else []),
|
|
46
|
-
*(["--native-tls"] if native_tls else []),
|
|
47
|
-
f"{temp}/*",
|
|
48
|
-
)
|
|
53
|
+
logged_run(*build_head, str(temp), *build_tail)
|
|
54
|
+
logged_run(*publish, f"{temp}/*")
|
|
49
55
|
LOGGER.info("Finished running %r", get_func_name(publish_package))
|
|
50
56
|
|
|
51
57
|
|
actions/random_sleep/lib.py
CHANGED
|
@@ -27,9 +27,9 @@ def random_sleep(
|
|
|
27
27
|
)
|
|
28
28
|
)
|
|
29
29
|
start = get_now()
|
|
30
|
-
|
|
31
|
-
LOGGER.info("Sleeping for %s...",
|
|
32
|
-
end = (start +
|
|
30
|
+
duration = TimeDelta(seconds=choice(range(min, max, step)))
|
|
31
|
+
LOGGER.info("Sleeping for %s...", duration)
|
|
32
|
+
end = (start + duration).round(mode="ceil")
|
|
33
33
|
while (now := get_now()) < end:
|
|
34
34
|
_intermediate(start, now, end, log_freq=log_freq)
|
|
35
35
|
LOGGER.info("Finished running %r", get_func_name(random_sleep))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|