omdev 0.0.0.dev212__py3-none-any.whl → 0.0.0.dev213__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.
omdev/cc/cdeps.py CHANGED
@@ -5,6 +5,7 @@ import typing as ta
5
5
  from omlish import cached
6
6
  from omlish import lang
7
7
  from omlish import marshal as msh
8
+ from omlish.configs import all as configs
8
9
 
9
10
 
10
11
  @dc.dataclass(frozen=True)
@@ -20,19 +21,51 @@ class Cdep:
20
21
 
21
22
  #
22
23
 
24
+ sources: ta.Sequence[str] | None = None
23
25
  include: ta.Sequence[str] | None = None
24
26
 
25
27
  #
26
28
 
27
29
  @dc.dataclass(frozen=True)
28
30
  class Cmake:
29
- fetch_content_url: str | None = None
31
+ @dc.dataclass(frozen=True)
32
+ class FetchContent:
33
+ url: str | None = None
34
+
35
+ @dc.dataclass(frozen=True)
36
+ class Git:
37
+ repository: str | None = None
38
+ tag: str | None = None
39
+
40
+ git: Git | None = None
41
+
42
+ fetch_content: FetchContent | None = None
30
43
 
31
44
  cmake: Cmake | None = None
32
45
 
33
46
 
47
+ def process_marshaled_cdep(obj: ta.Any) -> ta.Any:
48
+ obj = configs.processing.matched_rewrite(
49
+ lambda s: s if isinstance(s, str) else ''.join(s),
50
+ obj,
51
+ ('sources', None),
52
+ ('include', None),
53
+ )
54
+
55
+ return obj
56
+
57
+
34
58
  @cached.function
35
59
  def load_cdeps() -> ta.Mapping[str, Cdep]:
36
60
  src = lang.get_relative_resources(globals=globals())['cdeps.toml'].read_text()
37
61
  dct = tomllib.loads(src)
62
+
63
+ dct = {
64
+ **dct,
65
+ 'deps': {
66
+ k: process_marshaled_cdep(v)
67
+ for k, v in dct.get('deps', {}).items()
68
+ },
69
+ }
70
+
38
71
  return msh.unmarshal(dct.get('deps', {}), ta.Mapping[str, Cdep]) # type: ignore
omdev/cc/cdeps.toml CHANGED
@@ -1,3 +1,18 @@
1
+ [deps.httplib]
2
+ include = ['.']
3
+
4
+ [deps.httplib.git]
5
+ url = 'https://github.com/yhirose/cpp-httplib'
6
+ rev = 'a7bc00e3307fecdb4d67545e93be7b88cfb1e186'
7
+ subtrees = ['httplib.h']
8
+
9
+ [deps.httplib.cmake.fetch_content.git]
10
+ repository = 'https://github.com/yhirose/cpp-httplib.git'
11
+ tag = 'a7bc00e3307fecdb4d67545e93be7b88cfb1e186'
12
+
13
+
14
+ #
15
+
1
16
  [deps.json]
2
17
  include = ['single_include']
3
18
 
@@ -6,8 +21,9 @@ url = 'https://github.com/nlohmann/json'
6
21
  rev = '9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03'
7
22
  subtrees = ['single_include']
8
23
 
9
- [deps.json.cmake]
10
- fetch_content_url = 'https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz'
24
+ [deps.json.cmake.fetch_content]
25
+ url = 'https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz'
26
+
11
27
 
12
28
  #
13
29
 
@@ -19,6 +35,7 @@ url = 'https://github.com/pybind/pybind11'
19
35
  rev = '945e251a6ce7273058b36214d94415e9c9530b8e'
20
36
  subtrees = ['include']
21
37
 
38
+
22
39
  #
23
40
 
24
41
  [deps.ut]
omdev/cc/cli.py CHANGED
@@ -18,6 +18,8 @@ Freestanding options:
18
18
  TODO:
19
19
  - cext interop
20
20
  - gen cmake
21
+ - fix CFLAGS/CCFLAGS/CPPFLAGS/CXXFLAGS
22
+ - jit-gen cmake mode? multi-src builds
21
23
  """
22
24
  import os
23
25
  import shlex
@@ -35,6 +37,7 @@ from .. import magic
35
37
  from ..cache import data as dcache
36
38
  from .cdeps import Cdep
37
39
  from .cdeps import load_cdeps
40
+ from .cdeps import process_marshaled_cdep
38
41
 
39
42
 
40
43
  class Cli(ap.Cli):
@@ -64,16 +67,22 @@ class Cli(ap.Cli):
64
67
  if src_magic.key == '@omlish-cdeps':
65
68
  for dep in check.isinstance(src_magic.prepared, ta.Sequence):
66
69
  if isinstance(dep, ta.Mapping):
67
- dep = msh.unmarshal(dep, Cdep) # type: ignore
70
+ dep = process_marshaled_cdep(dep)
71
+ dep = msh.unmarshal(dep, Cdep)
68
72
  else:
69
73
  dep = load_cdeps()[check.isinstance(dep, str)]
70
74
 
75
+ if dep.sources:
76
+ # TODO
77
+ raise NotImplementedError
78
+
71
79
  dep_spec = dcache.GitSpec(
72
80
  url=dep.git.url,
73
81
  rev=dep.git.rev,
74
82
  subtrees=dep.git.subtrees,
75
83
  )
76
84
  dep_dir = dcache.default().get(dep_spec)
85
+
77
86
  for dep_inc in dep.include or []:
78
87
  inc_dir = os.path.join(dep_dir, dep_inc)
79
88
  check.state(os.path.isdir(inc_dir))
@@ -96,6 +105,9 @@ class Cli(ap.Cli):
96
105
  if cflags := os.environ.get('CFLAGS'):
97
106
  sh_parts.append(cflags) # Explicitly shell-unquoted
98
107
 
108
+ if ldflags := os.environ.get('LDFLAGS'):
109
+ sh_parts.append(ldflags) # Explicitly shell-unquoted
110
+
99
111
  sh_parts.extend([
100
112
  '-std=c++20',
101
113
  shlex.quote(os.path.abspath(src_file)),
omdev/ci/ci.py CHANGED
@@ -7,9 +7,10 @@ import tarfile
7
7
  import tempfile
8
8
  import typing as ta
9
9
 
10
+ from omlish.lite.cached import async_cached_nullary
10
11
  from omlish.lite.cached import cached_nullary
11
12
  from omlish.lite.check import check
12
- from omlish.lite.contextmanagers import ExitStacked
13
+ from omlish.lite.contextmanagers import AsyncExitStacked
13
14
  from omlish.lite.contextmanagers import defer
14
15
 
15
16
  from .cache import FileCache
@@ -22,13 +23,14 @@ from .docker import is_docker_image_present
22
23
  from .docker import load_docker_tar_cmd
23
24
  from .docker import pull_docker_image
24
25
  from .docker import save_docker_tar_cmd
26
+ from .docker import tag_docker_image
25
27
  from .requirements import build_requirements_hash
26
28
  from .requirements import download_requirements
27
29
  from .shell import ShellCmd
28
30
  from .utils import log_timing_context
29
31
 
30
32
 
31
- class Ci(ExitStacked):
33
+ class Ci(AsyncExitStacked):
32
34
  FILE_NAME_HASH_LEN = 16
33
35
 
34
36
  @dc.dataclass(frozen=True)
@@ -45,6 +47,9 @@ class Ci(ExitStacked):
45
47
  requirements_txts: ta.Optional[ta.Sequence[str]] = None
46
48
 
47
49
  always_pull: bool = False
50
+ always_build: bool = False
51
+
52
+ no_dependencies: bool = False
48
53
 
49
54
  def __post_init__(self) -> None:
50
55
  check.not_isinstance(self.requirements_txts, str)
@@ -64,7 +69,7 @@ class Ci(ExitStacked):
64
69
 
65
70
  #
66
71
 
67
- def _load_cache_docker_image(self, key: str) -> ta.Optional[str]:
72
+ async def _load_cache_docker_image(self, key: str) -> ta.Optional[str]:
68
73
  if self._shell_cache is None:
69
74
  return None
70
75
 
@@ -74,9 +79,9 @@ class Ci(ExitStacked):
74
79
 
75
80
  get_cache_cmd = dc.replace(get_cache_cmd, s=f'{get_cache_cmd.s} | zstd -cd --long') # noqa
76
81
 
77
- return load_docker_tar_cmd(get_cache_cmd)
82
+ return await load_docker_tar_cmd(get_cache_cmd)
78
83
 
79
- def _save_cache_docker_image(self, key: str, image: str) -> None:
84
+ async def _save_cache_docker_image(self, key: str, image: str) -> None:
80
85
  if self._shell_cache is None:
81
86
  return
82
87
 
@@ -85,12 +90,12 @@ class Ci(ExitStacked):
85
90
 
86
91
  put_cache_cmd = dc.replace(put_cache_cmd, s=f'zstd | {put_cache_cmd.s}')
87
92
 
88
- save_docker_tar_cmd(image, put_cache_cmd)
93
+ await save_docker_tar_cmd(image, put_cache_cmd)
89
94
 
90
95
  #
91
96
 
92
- def _load_docker_image(self, image: str) -> None:
93
- if not self._cfg.always_pull and is_docker_image_present(image):
97
+ async def _load_docker_image(self, image: str) -> None:
98
+ if not self._cfg.always_pull and (await is_docker_image_present(image)):
94
99
  return
95
100
 
96
101
  dep_suffix = image
@@ -98,63 +103,79 @@ class Ci(ExitStacked):
98
103
  dep_suffix = dep_suffix.replace(c, '-')
99
104
 
100
105
  cache_key = f'docker-{dep_suffix}'
101
- if self._load_cache_docker_image(cache_key) is not None:
106
+ if (await self._load_cache_docker_image(cache_key)) is not None:
102
107
  return
103
108
 
104
- pull_docker_image(image)
109
+ await pull_docker_image(image)
105
110
 
106
- self._save_cache_docker_image(cache_key, image)
111
+ await self._save_cache_docker_image(cache_key, image)
107
112
 
108
- def load_docker_image(self, image: str) -> None:
113
+ async def load_docker_image(self, image: str) -> None:
109
114
  with log_timing_context(f'Load docker image: {image}'):
110
- self._load_docker_image(image)
115
+ await self._load_docker_image(image)
111
116
 
112
- @cached_nullary
113
- def load_compose_service_dependencies(self) -> None:
117
+ @async_cached_nullary
118
+ async def load_compose_service_dependencies(self) -> None:
114
119
  deps = get_compose_service_dependencies(
115
120
  self._cfg.compose_file,
116
121
  self._cfg.service,
117
122
  )
118
123
 
119
124
  for dep_image in deps.values():
120
- self.load_docker_image(dep_image)
125
+ await self.load_docker_image(dep_image)
121
126
 
122
127
  #
123
128
 
124
- def _resolve_ci_image(self) -> str:
125
- docker_file_hash = build_docker_file_hash(self._cfg.docker_file)[:self.FILE_NAME_HASH_LEN]
129
+ @cached_nullary
130
+ def docker_file_hash(self) -> str:
131
+ return build_docker_file_hash(self._cfg.docker_file)[:self.FILE_NAME_HASH_LEN]
132
+
133
+ async def _resolve_ci_image(self) -> str:
134
+ cache_key = f'ci-{self.docker_file_hash()}'
135
+ image_tag = f'{self._cfg.service}:{cache_key}'
136
+
137
+ if not self._cfg.always_build and (await is_docker_image_present(image_tag)):
138
+ return image_tag
126
139
 
127
- cache_key = f'ci-{docker_file_hash}'
128
- if (cache_image_id := self._load_cache_docker_image(cache_key)) is not None:
129
- return cache_image_id
140
+ if (cache_image_id := await self._load_cache_docker_image(cache_key)) is not None:
141
+ await tag_docker_image(
142
+ cache_image_id,
143
+ image_tag,
144
+ )
145
+ return image_tag
130
146
 
131
- image_id = build_docker_image(
147
+ image_id = await build_docker_image(
132
148
  self._cfg.docker_file,
149
+ tag=image_tag,
133
150
  cwd=self._cfg.project_dir,
134
151
  )
135
152
 
136
- self._save_cache_docker_image(cache_key, image_id)
153
+ await self._save_cache_docker_image(cache_key, image_id)
137
154
 
138
- return image_id
155
+ return image_tag
139
156
 
140
- @cached_nullary
141
- def resolve_ci_image(self) -> str:
157
+ @async_cached_nullary
158
+ async def resolve_ci_image(self) -> str:
142
159
  with log_timing_context('Resolve ci image') as ltc:
143
- image_id = self._resolve_ci_image()
160
+ image_id = await self._resolve_ci_image()
144
161
  ltc.set_description(f'Resolve ci image: {image_id}')
145
162
  return image_id
146
163
 
147
164
  #
148
165
 
149
- def _resolve_requirements_dir(self) -> str:
150
- requirements_txts = [
166
+ @cached_nullary
167
+ def requirements_txts(self) -> ta.Sequence[str]:
168
+ return [
151
169
  os.path.join(self._cfg.project_dir, rf)
152
170
  for rf in check.not_none(self._cfg.requirements_txts)
153
171
  ]
154
172
 
155
- requirements_hash = build_requirements_hash(requirements_txts)[:self.FILE_NAME_HASH_LEN]
173
+ @cached_nullary
174
+ def requirements_hash(self) -> str:
175
+ return build_requirements_hash(self.requirements_txts())[:self.FILE_NAME_HASH_LEN]
156
176
 
157
- tar_file_key = f'requirements-{requirements_hash}'
177
+ async def _resolve_requirements_dir(self) -> str:
178
+ tar_file_key = f'requirements-{self.docker_file_hash()}-{self.requirements_hash()}'
158
179
  tar_file_name = f'{tar_file_key}.tar'
159
180
 
160
181
  temp_dir = tempfile.mkdtemp()
@@ -170,9 +191,9 @@ class Ci(ExitStacked):
170
191
  os.makedirs(temp_requirements_dir)
171
192
 
172
193
  download_requirements(
173
- self.resolve_ci_image(),
194
+ await self.resolve_ci_image(),
174
195
  temp_requirements_dir,
175
- requirements_txts,
196
+ self.requirements_txts(),
176
197
  )
177
198
 
178
199
  if self._file_cache is not None:
@@ -189,16 +210,16 @@ class Ci(ExitStacked):
189
210
 
190
211
  return temp_requirements_dir
191
212
 
192
- @cached_nullary
193
- def resolve_requirements_dir(self) -> str:
213
+ @async_cached_nullary
214
+ async def resolve_requirements_dir(self) -> str:
194
215
  with log_timing_context('Resolve requirements dir') as ltc:
195
- requirements_dir = self._resolve_requirements_dir()
216
+ requirements_dir = await self._resolve_requirements_dir()
196
217
  ltc.set_description(f'Resolve requirements dir: {requirements_dir}')
197
218
  return requirements_dir
198
219
 
199
220
  #
200
221
 
201
- def _run_compose_(self) -> None:
222
+ async def _run_compose_(self) -> None:
202
223
  setup_cmds = [
203
224
  'pip install --root-user-action ignore --find-links /requirements --no-index uv',
204
225
  (
@@ -216,34 +237,36 @@ class Ci(ExitStacked):
216
237
 
217
238
  #
218
239
 
219
- with DockerComposeRun(DockerComposeRun.Config(
240
+ async with DockerComposeRun(DockerComposeRun.Config(
220
241
  compose_file=self._cfg.compose_file,
221
242
  service=self._cfg.service,
222
243
 
223
- image=self.resolve_ci_image(),
244
+ image=await self.resolve_ci_image(),
224
245
 
225
246
  cmd=ci_cmd,
226
247
 
227
248
  run_options=[
228
249
  '-v', f'{os.path.abspath(self._cfg.project_dir)}:/project',
229
- '-v', f'{os.path.abspath(self.resolve_requirements_dir())}:/requirements',
250
+ '-v', f'{os.path.abspath(await self.resolve_requirements_dir())}:/requirements',
230
251
  ],
231
252
 
232
253
  cwd=self._cfg.project_dir,
254
+
255
+ no_dependencies=self._cfg.no_dependencies,
233
256
  )) as ci_compose_run:
234
- ci_compose_run.run()
257
+ await ci_compose_run.run()
235
258
 
236
- def _run_compose(self) -> None:
259
+ async def _run_compose(self) -> None:
237
260
  with log_timing_context('Run compose'):
238
- self._run_compose_()
261
+ await self._run_compose_()
239
262
 
240
263
  #
241
264
 
242
- def run(self) -> None:
243
- self.load_compose_service_dependencies()
265
+ async def run(self) -> None:
266
+ await self.load_compose_service_dependencies()
244
267
 
245
- self.resolve_ci_image()
268
+ await self.resolve_ci_image()
246
269
 
247
- self.resolve_requirements_dir()
270
+ await self.resolve_requirements_dir()
248
271
 
249
- self._run_compose()
272
+ await self._run_compose()
omdev/ci/cli.py CHANGED
@@ -76,18 +76,21 @@ class CiCli(ArgparseCli):
76
76
  argparse_arg('--docker-file'),
77
77
  argparse_arg('--compose-file'),
78
78
  argparse_arg('-r', '--requirements-txt', action='append'),
79
+
79
80
  argparse_arg('--github-cache', action='store_true'),
80
81
  argparse_arg('--cache-dir'),
82
+
81
83
  argparse_arg('--always-pull', action='store_true'),
84
+ argparse_arg('--always-build', action='store_true'),
85
+
86
+ argparse_arg('--no-dependencies', action='store_true'),
82
87
  )
83
88
  async def run(self) -> None:
84
89
  project_dir = self.args.project_dir
85
90
  docker_file = self.args.docker_file
86
91
  compose_file = self.args.compose_file
87
- service = self.args.service
88
92
  requirements_txts = self.args.requirements_txt
89
93
  cache_dir = self.args.cache_dir
90
- always_pull = self.args.always_pull
91
94
 
92
95
  #
93
96
 
@@ -157,14 +160,14 @@ class CiCli(ArgparseCli):
157
160
 
158
161
  #
159
162
 
160
- with Ci(
163
+ async with Ci(
161
164
  Ci.Config(
162
165
  project_dir=project_dir,
163
166
 
164
167
  docker_file=docker_file,
165
168
 
166
169
  compose_file=compose_file,
167
- service=service,
170
+ service=self.args.service,
168
171
 
169
172
  requirements_txts=requirements_txts,
170
173
 
@@ -173,12 +176,15 @@ class CiCli(ArgparseCli):
173
176
  'python3 -m pytest -svv test.py',
174
177
  ])),
175
178
 
176
- always_pull=always_pull,
179
+ always_pull=self.args.always_pull,
180
+ always_build=self.args.always_build,
181
+
182
+ no_dependencies=self.args.no_dependencies,
177
183
  ),
178
184
  file_cache=file_cache,
179
185
  shell_cache=shell_cache,
180
186
  ) as ci:
181
- ci.run()
187
+ await ci.run()
182
188
 
183
189
 
184
190
  async def _async_main() -> ta.Optional[int]:
omdev/ci/compose.py CHANGED
@@ -11,12 +11,13 @@ import os.path
11
11
  import shlex
12
12
  import typing as ta
13
13
 
14
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
14
15
  from omlish.lite.cached import cached_nullary
15
16
  from omlish.lite.check import check
16
- from omlish.lite.contextmanagers import ExitStacked
17
+ from omlish.lite.contextmanagers import AsyncExitStacked
18
+ from omlish.lite.contextmanagers import adefer
17
19
  from omlish.lite.contextmanagers import defer
18
20
  from omlish.lite.json import json_dumps_pretty
19
- from omlish.subprocesses import subprocesses
20
21
 
21
22
  from .shell import ShellCmd
22
23
  from .utils import make_temp_file
@@ -46,7 +47,7 @@ def get_compose_service_dependencies(
46
47
  ##
47
48
 
48
49
 
49
- class DockerComposeRun(ExitStacked):
50
+ class DockerComposeRun(AsyncExitStacked):
50
51
  @dc.dataclass(frozen=True)
51
52
  class Config:
52
53
  compose_file: str
@@ -64,6 +65,7 @@ class DockerComposeRun(ExitStacked):
64
65
 
65
66
  #
66
67
 
68
+ no_dependencies: bool = False
67
69
  no_dependency_cleanup: bool = False
68
70
 
69
71
  #
@@ -82,40 +84,6 @@ class DockerComposeRun(ExitStacked):
82
84
 
83
85
  #
84
86
 
85
- @property
86
- def image_tag(self) -> str:
87
- pfx = 'sha256:'
88
- if (image := self._cfg.image).startswith(pfx):
89
- image = image[len(pfx):]
90
-
91
- return f'{self._cfg.service}:{image}'
92
-
93
- @cached_nullary
94
- def tag_image(self) -> str:
95
- image_tag = self.image_tag
96
-
97
- subprocesses.check_call(
98
- 'docker',
99
- 'tag',
100
- self._cfg.image,
101
- image_tag,
102
- **self._subprocess_kwargs,
103
- )
104
-
105
- def delete_tag() -> None:
106
- subprocesses.check_call(
107
- 'docker',
108
- 'rmi',
109
- image_tag,
110
- **self._subprocess_kwargs,
111
- )
112
-
113
- self._enter_context(defer(delete_tag)) # noqa
114
-
115
- return image_tag
116
-
117
- #
118
-
119
87
  def _rewrite_compose_dct(self, in_dct: ta.Dict[str, ta.Any]) -> ta.Dict[str, ta.Any]:
120
88
  out = dict(in_dct)
121
89
 
@@ -129,7 +97,7 @@ class DockerComposeRun(ExitStacked):
129
97
  in_service: dict = in_services[self._cfg.service]
130
98
  out_services[self._cfg.service] = out_service = dict(in_service)
131
99
 
132
- out_service['image'] = self.image_tag
100
+ out_service['image'] = self._cfg.image
133
101
 
134
102
  for k in ['build', 'platform']:
135
103
  if k in out_service:
@@ -142,16 +110,21 @@ class DockerComposeRun(ExitStacked):
142
110
 
143
111
  #
144
112
 
145
- depends_on = in_service.get('depends_on', [])
113
+ if not self._cfg.no_dependencies:
114
+ depends_on = in_service.get('depends_on', [])
146
115
 
147
- for dep_service, in_dep_service_dct in list(in_services.items()):
148
- if dep_service not in depends_on:
149
- continue
116
+ for dep_service, in_dep_service_dct in list(in_services.items()):
117
+ if dep_service not in depends_on:
118
+ continue
150
119
 
151
- out_dep_service: dict = dict(in_dep_service_dct)
152
- out_services[dep_service] = out_dep_service
120
+ out_dep_service: dict = dict(in_dep_service_dct)
121
+ out_services[dep_service] = out_dep_service
153
122
 
154
- out_dep_service['ports'] = []
123
+ out_dep_service['ports'] = []
124
+
125
+ else:
126
+ out_service['depends_on'] = []
127
+ out_service['links'] = []
155
128
 
156
129
  #
157
130
 
@@ -177,22 +150,20 @@ class DockerComposeRun(ExitStacked):
177
150
 
178
151
  #
179
152
 
180
- def _cleanup_dependencies(self) -> None:
181
- subprocesses.check_call(
153
+ async def _cleanup_dependencies(self) -> None:
154
+ await asyncio_subprocesses.check_call(
182
155
  'docker',
183
156
  'compose',
184
157
  '-f', self.rewrite_compose_file(),
185
158
  'down',
186
159
  )
187
160
 
188
- def run(self) -> None:
189
- self.tag_image()
190
-
161
+ async def run(self) -> None:
191
162
  compose_file = self.rewrite_compose_file()
192
163
 
193
- with contextlib.ExitStack() as es:
194
- if not self._cfg.no_dependency_cleanup:
195
- es.enter_context(defer(self._cleanup_dependencies)) # noqa
164
+ async with contextlib.AsyncExitStack() as es:
165
+ if not (self._cfg.no_dependencies or self._cfg.no_dependency_cleanup):
166
+ await es.enter_async_context(adefer(self._cleanup_dependencies)) # noqa
196
167
 
197
168
  sh_cmd = ' '.join([
198
169
  'docker',
@@ -211,7 +182,7 @@ class DockerComposeRun(ExitStacked):
211
182
 
212
183
  run_cmd = dc.replace(self._cfg.cmd, s=sh_cmd)
213
184
 
214
- run_cmd.run(
215
- subprocesses.check_call,
185
+ await run_cmd.run(
186
+ asyncio_subprocesses.check_call,
216
187
  **self._subprocess_kwargs,
217
188
  )