dycw-actions 0.11.3__py3-none-any.whl → 0.14.0__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.
@@ -1,11 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
- from utilities.whenever import HOUR
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
- THROTTLE_DELTA = 12 * HOUR
8
+ THROTTLE_DURATION = 12 * HOUR
9
9
 
10
10
 
11
- __all__ = ["PATH_PRE_COMMIT", "THROTTLE_DELTA"]
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 THROTTLE_DELTA
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
- delta=THROTTLE_DELTA, path=path_throttle_cache(_touch_empty_py)
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 THROTTLE_DELTA
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
- delta=THROTTLE_DELTA, path=path_throttle_cache(_touch_py_typed)
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 != "pyproject.toml":
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
- def update_requirements_sub_cmd(*, paths: tuple[Path, ...]) -> None:
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(*paths)
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,9 @@ 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 utilities.functions import get_func_name, max_nullable
9
+ from utilities.functions import ensure_str, get_func_name, max_nullable
9
10
  from utilities.tabulate import func_param_desc
10
11
  from utilities.text import repr_str
11
12
 
@@ -20,11 +21,18 @@ from actions.pre_commit.update_requirements.classes import (
20
21
  parse_version1_or_2,
21
22
  parse_version2_or_3,
22
23
  )
23
- from actions.pre_commit.utilities import get_pyproject_dependencies, yield_toml_doc
24
+ from actions.pre_commit.update_requirements.settings import SETTINGS
25
+ from actions.pre_commit.utilities import (
26
+ get_aot,
27
+ get_pyproject_dependencies,
28
+ get_table,
29
+ yield_pyproject_toml,
30
+ yield_toml_doc,
31
+ )
24
32
  from actions.utilities import logged_run
25
33
 
26
34
  if TYPE_CHECKING:
27
- from collections.abc import MutableSet
35
+ from collections.abc import Iterator, MutableSet
28
36
  from pathlib import Path
29
37
 
30
38
  from utilities.packaging import Requirement
@@ -33,11 +41,25 @@ if TYPE_CHECKING:
33
41
  from actions.pre_commit.update_requirements.classes import Version2or3, VersionSet
34
42
 
35
43
 
36
- def update_requirements(*paths: PathLike) -> None:
37
- LOGGER.info(func_param_desc(update_requirements, __version__, f"{paths=}"))
44
+ def update_requirements(
45
+ *paths: PathLike,
46
+ indexes: list[str] | None = SETTINGS.indexes,
47
+ native_tls: bool = SETTINGS.native_tls,
48
+ ) -> None:
49
+ LOGGER.info(
50
+ func_param_desc(
51
+ update_requirements,
52
+ __version__,
53
+ f"{paths=}",
54
+ f"{indexes=}",
55
+ f"{native_tls=}",
56
+ )
57
+ )
38
58
  modifications: set[Path] = set()
39
59
  for path in paths:
40
- _format_path(path, modifications=modifications)
60
+ _format_path(
61
+ path, indexes=indexes, native_tls=native_tls, modifications=modifications
62
+ )
41
63
  if len(modifications) >= 1:
42
64
  LOGGER.info(
43
65
  "Exiting due to modifications: %s",
@@ -52,24 +74,40 @@ def _format_path(
52
74
  /,
53
75
  *,
54
76
  versions: VersionSet | None = None,
77
+ indexes: list[str] | None = SETTINGS.indexes,
78
+ native_tls: bool = SETTINGS.native_tls,
55
79
  modifications: MutableSet[Path] | None = None,
56
80
  ) -> None:
57
- versions_use = _get_versions() if versions is None else versions
81
+ versions_use = (
82
+ _get_versions(indexes=indexes, native_tls=native_tls)
83
+ if versions is None
84
+ else versions
85
+ )
58
86
  with yield_toml_doc(path, modifications=modifications) as doc:
59
87
  get_pyproject_dependencies(doc).apply(
60
88
  partial(_format_req, versions=versions_use)
61
89
  )
62
90
 
63
91
 
64
- def _get_versions() -> VersionSet:
65
- json1 = logged_run(
66
- "uv", "pip", "list", "--format", "json", "--strict", return_=True
67
- )
92
+ def _get_versions(
93
+ *,
94
+ indexes: list[str] | None = SETTINGS.indexes,
95
+ native_tls: bool = SETTINGS.native_tls,
96
+ ) -> VersionSet:
97
+ index_args: OrderedSet[str] = OrderedSet([])
98
+ _ = index_args.update(list(_yield_indexes()))
99
+ if indexes is not None:
100
+ _ = index_args.update(indexes)
101
+ head: list[str] = ["uv", "pip", "list", "--format", "json"]
102
+ tail: list[str] = ["--strict"]
103
+ if len(index_args) >= 1:
104
+ tail.extend(["--index", ",".join(index_args)])
105
+ if native_tls:
106
+ tail.append("--native-tls")
107
+ json1 = logged_run(*head, *tail, return_=True)
68
108
  models1 = TypeAdapter(list[PipListOutput]).validate_json(json1)
69
109
  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
- )
110
+ json2 = logged_run(*head, "--outdated", *tail, return_=True)
73
111
  models2 = TypeAdapter(list[PipListOutdatedOutput]).validate_json(json2)
74
112
  versions2 = {p.name: parse_version2_or_3(p.latest_version) for p in models2}
75
113
  out: StrDict = {}
@@ -78,6 +116,28 @@ def _get_versions() -> VersionSet:
78
116
  return out
79
117
 
80
118
 
119
+ def _yield_indexes() -> Iterator[str]:
120
+ try:
121
+ with yield_pyproject_toml() as doc:
122
+ try:
123
+ tool = get_table(doc, "tool")
124
+ except KeyError:
125
+ return
126
+ try:
127
+ uv = get_table(tool, "uv")
128
+ except KeyError:
129
+ return
130
+ try:
131
+ indexes = get_aot(uv, "index")
132
+ except KeyError:
133
+ return
134
+ else:
135
+ for index in indexes:
136
+ yield ensure_str(index["url"])
137
+ except FileNotFoundError:
138
+ return
139
+
140
+
81
141
  def _format_req(requirement: Requirement, /, *, versions: VersionSet) -> Requirement:
82
142
  try:
83
143
  lower = parse_version2_or_3(requirement[">="])
@@ -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"]
@@ -5,7 +5,7 @@ from collections.abc import Iterator, MutableSet
5
5
  from contextlib import contextmanager
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 FuncRequirement, HasAppend, HasSetDefault
30
+ from actions.types import ArrayLike, ContainerLike, FuncRequirement
30
31
 
31
32
 
32
- def ensure_aot_contains(array: AoT, /, *tables: Table) -> None:
33
- for table_ in tables:
34
- if table_ not in array:
35
- array.append(table_)
33
+ ##
36
34
 
37
35
 
38
- def ensure_contains(array: HasAppend, /, *objs: Any) -> None:
39
- if isinstance(array, AoT):
40
- msg = f"Use {ensure_aot_contains.__name__!r} instead of {ensure_contains.__name__!r}"
41
- raise TypeError(msg)
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 array:
44
- array.append(obj)
44
+ if obj not in container:
45
+ container.append(obj)
45
46
 
46
47
 
47
48
  def ensure_contains_partial_dict(
48
- container: HasAppend, partial: StrDict, /, *, extra: StrDict | None = None
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(container: HasAppend, text: str, /) -> str:
59
+ def ensure_contains_partial_str(list_: Array | list[str], text: str, /) -> str:
59
60
  try:
60
- return get_partial_str(container, text, skip_log=True)
61
+ return get_partial_str(list_, text, skip_log=True)
61
62
  except OneEmptyError:
62
- container.append(text)
63
+ list_.append(text)
63
64
  return text
64
65
 
65
66
 
66
- def ensure_not_contains(array: Array, /, *objs: Any) -> None:
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(array) if o == obj)
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 array[index]
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 get_aot(container: HasSetDefault, key: str, /) -> AoT:
80
- return ensure_class(container.setdefault(key, aot()), AoT)
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 get_array(container: HasSetDefault, key: str, /) -> Array:
84
- return ensure_class(container.setdefault(key, array()), Array)
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 get_dict(container: HasSetDefault, key: str, /) -> StrDict:
88
- return ensure_class(container.setdefault(key, {}), dict)
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 get_list(container: HasSetDefault, key: str, /) -> list[Any]:
92
- return ensure_class(container.setdefault(key, []), list)
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 get_table(container: HasSetDefault, key: str, /) -> Table:
96
- return ensure_class(container.setdefault(key, table()), Table)
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[Any], dict_: StrDict, /, *, skip_log: bool = False
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))
@@ -177,19 +249,21 @@ def is_partial_str(obj: Any, text: str, /) -> bool:
177
249
  def get_pyproject_dependencies(doc: TOMLDocument, /) -> PyProjectDependencies:
178
250
  out = PyProjectDependencies()
179
251
  if (project_key := "project") in doc:
180
- project = get_table(doc, project_key)
252
+ project = get_set_table(doc, project_key)
181
253
  if (dep_key := "dependencies") in project:
182
- out.dependencies = get_array(project, dep_key)
254
+ out.dependencies = get_set_array(project, dep_key)
183
255
  if (opt_dep_key := "optional-dependencies") in project:
184
- opt_dependencies = get_table(project, opt_dep_key)
256
+ opt_dependencies = get_set_table(project, opt_dep_key)
185
257
  out.opt_dependencies = {}
186
258
  for key in opt_dependencies:
187
- out.opt_dependencies[ensure_str(key)] = get_array(opt_dependencies, key)
259
+ out.opt_dependencies[ensure_str(key)] = get_set_array(
260
+ opt_dependencies, key
261
+ )
188
262
  if (dep_grps_key := "dependency-groups") in doc:
189
- dep_grps = get_table(doc, dep_grps_key)
263
+ dep_grps = get_set_table(doc, dep_grps_key)
190
264
  out.dep_groups = {}
191
265
  for key in dep_grps:
192
- out.dep_groups[ensure_str(key)] = get_array(dep_grps, key)
266
+ out.dep_groups[ensure_str(key)] = get_set_array(dep_grps, key)
193
267
  return out
194
268
 
195
269
 
@@ -295,6 +369,17 @@ def yield_json_dict(
295
369
  ##
296
370
 
297
371
 
372
+ @contextmanager
373
+ def yield_pyproject_toml(
374
+ *, modifications: MutableSet[Path] | None = None
375
+ ) -> Iterator[TOMLDocument]:
376
+ with yield_toml_doc(PYPROJECT_TOML, modifications=modifications) as doc:
377
+ yield doc
378
+
379
+
380
+ ##
381
+
382
+
298
383
  @contextmanager
299
384
  def yield_mutable_write_context[T](
300
385
  path: PathLike,
@@ -370,7 +455,6 @@ def yield_yaml_dict(
370
455
  __all__ = [
371
456
  "PyProjectDependencies",
372
457
  "WriteContext",
373
- "ensure_aot_contains",
374
458
  "ensure_contains",
375
459
  "ensure_contains_partial_dict",
376
460
  "ensure_contains_partial_str",
@@ -378,10 +462,17 @@ __all__ = [
378
462
  "get_aot",
379
463
  "get_array",
380
464
  "get_dict",
381
- "get_list",
465
+ "get_list_dicts",
466
+ "get_list_strs",
382
467
  "get_partial_dict",
383
468
  "get_partial_str",
384
469
  "get_pyproject_dependencies",
470
+ "get_set_aot",
471
+ "get_set_array",
472
+ "get_set_dict",
473
+ "get_set_list_dicts",
474
+ "get_set_list_strs",
475
+ "get_set_table",
385
476
  "get_table",
386
477
  "is_partial_dict",
387
478
  "is_partial_str",
@@ -389,6 +480,7 @@ __all__ = [
389
480
  "yield_immutable_write_context",
390
481
  "yield_json_dict",
391
482
  "yield_mutable_write_context",
483
+ "yield_pyproject_toml",
392
484
  "yield_python_file",
393
485
  "yield_text_file",
394
486
  "yield_toml_doc",
@@ -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("uv", "build", "--out-dir", str(temp), "--wheel", "--clear")
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
 
@@ -27,9 +27,9 @@ def random_sleep(
27
27
  )
28
28
  )
29
29
  start = get_now()
30
- delta = TimeDelta(seconds=choice(range(min, max, step)))
31
- LOGGER.info("Sleeping for %s...", delta)
32
- end = (start + delta).round(mode="ceil")
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
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import TYPE_CHECKING
5
+
6
+ import click
7
+ from click import argument
8
+ from typed_settings import click_options
9
+ from utilities.logging import basic_config
10
+ from utilities.os import is_pytest
11
+
12
+ from actions.logging import LOGGER
13
+ from actions.re_encrypt.lib import re_encrypt
14
+ from actions.re_encrypt.settings import Settings
15
+ from actions.utilities import LOADER
16
+
17
+ if TYPE_CHECKING:
18
+ from utilities.types import PathLike
19
+
20
+
21
+ @argument("path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
22
+ @click_options(Settings, [LOADER], show_envvars_in_help=True)
23
+ def re_encrypt_sub_cmd(settings: Settings, /, *, path: PathLike) -> None:
24
+ if is_pytest():
25
+ return
26
+ basic_config(obj=LOGGER)
27
+ re_encrypt(
28
+ path,
29
+ key_file=settings.key_file,
30
+ key=settings.key,
31
+ new_key_file=settings.new_key_file,
32
+ new_key=settings.new_key,
33
+ )
34
+
35
+
36
+ __all__ = ["re_encrypt_sub_cmd"]
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ RE_ENCRYPT_DOCSTRING = "Re-encrypt a JSON file"
4
+ RE_ENCRYPT_SUB_CMD = "re-encrypt"
5
+
6
+
7
+ __all__ = ["RE_ENCRYPT_DOCSTRING", "RE_ENCRYPT_SUB_CMD"]