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.
@@ -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"
@@ -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,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 utilities.functions import get_func_name, max_nullable
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.utilities import get_pyproject_dependencies, yield_toml_doc
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 utilities.packaging import Requirement
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(*paths: PathLike) -> None:
37
- LOGGER.info(func_param_desc(update_requirements, __version__, f"{paths=}"))
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(path, modifications=modifications)
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 = _get_versions() if versions is None else versions
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() -> VersionSet:
65
- json1 = logged_run(
66
- "uv", "pip", "list", "--format", "json", "--strict", return_=True
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"]
@@ -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 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))
@@ -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
- if (project_key := "project") in doc:
180
- project = get_table(doc, project_key)
181
- if (dep_key := "dependencies") in project:
182
- out.dependencies = get_array(project, dep_key)
183
- if (opt_dep_key := "optional-dependencies") in project:
184
- opt_dependencies = get_table(project, opt_dep_key)
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
- if (dep_grps_key := "dependency-groups") in doc:
189
- dep_grps = get_table(doc, dep_grps_key)
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
- "get_list",
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",
@@ -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