ominfra 0.0.0.dev157__py3-none-any.whl → 0.0.0.dev159__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,22 +3,24 @@
3
3
  ~deploy
4
4
  deploy.pid (flock)
5
5
  /app
6
- /<appspec> - shallow clone
6
+ /<appplaceholder> - shallow clone
7
7
  /conf
8
8
  /env
9
- <appspec>.env
9
+ <appplaceholder>.env
10
10
  /nginx
11
- <appspec>.conf
11
+ <appplaceholder>.conf
12
12
  /supervisor
13
- <appspec>.conf
13
+ <appplaceholder>.conf
14
14
  /venv
15
- /<appspec>
15
+ /<appplaceholder>
16
+
17
+ /tmp
16
18
 
17
19
  ?
18
20
  /logs
19
- /wrmsr--omlish--<spec>
21
+ /wrmsr--omlish--<placeholder>
20
22
 
21
- spec = <name>--<rev>--<when>
23
+ placeholder = <name>--<rev>--<when>
22
24
 
23
25
  ==
24
26
 
@@ -39,20 +41,23 @@ import dataclasses as dc
39
41
  import os.path
40
42
  import typing as ta
41
43
 
44
+ from omlish.lite.cached import cached_nullary
42
45
  from omlish.lite.check import check
43
46
 
47
+ from .types import DeployHome
48
+
44
49
 
45
50
  DeployPathKind = ta.Literal['dir', 'file'] # ta.TypeAlias
46
- DeployPathSpec = ta.Literal['app', 'tag'] # ta.TypeAlias
51
+ DeployPathPlaceholder = ta.Literal['app', 'tag'] # ta.TypeAlias
47
52
 
48
53
 
49
54
  ##
50
55
 
51
56
 
52
- DEPLOY_PATH_SPEC_PLACEHOLDER = '@'
53
- DEPLOY_PATH_SPEC_SEPARATORS = '-.'
57
+ DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER = '@'
58
+ DEPLOY_PATH_PLACEHOLDER_SEPARATORS = '-.'
54
59
 
55
- DEPLOY_PATH_SPECS: ta.FrozenSet[str] = frozenset([
60
+ DEPLOY_PATH_PLACEHOLDERS: ta.FrozenSet[str] = frozenset([
56
61
  'app',
57
62
  'tag', # <rev>-<dt>
58
63
  ])
@@ -70,7 +75,7 @@ class DeployPathPart(abc.ABC): # noqa
70
75
  raise NotImplementedError
71
76
 
72
77
  @abc.abstractmethod
73
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
78
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
74
79
  raise NotImplementedError
75
80
 
76
81
 
@@ -84,9 +89,9 @@ class DirDeployPathPart(DeployPathPart, abc.ABC):
84
89
 
85
90
  @classmethod
86
91
  def parse(cls, s: str) -> 'DirDeployPathPart':
87
- if DEPLOY_PATH_SPEC_PLACEHOLDER in s:
88
- check.equal(s[0], DEPLOY_PATH_SPEC_PLACEHOLDER)
89
- return SpecDirDeployPathPart(s[1:])
92
+ if DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER in s:
93
+ check.equal(s[0], DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER)
94
+ return PlaceholderDirDeployPathPart(s[1:])
90
95
  else:
91
96
  return ConstDirDeployPathPart(s)
92
97
 
@@ -98,13 +103,13 @@ class FileDeployPathPart(DeployPathPart, abc.ABC):
98
103
 
99
104
  @classmethod
100
105
  def parse(cls, s: str) -> 'FileDeployPathPart':
101
- if DEPLOY_PATH_SPEC_PLACEHOLDER in s:
102
- check.equal(s[0], DEPLOY_PATH_SPEC_PLACEHOLDER)
103
- if not any(c in s for c in DEPLOY_PATH_SPEC_SEPARATORS):
104
- return SpecFileDeployPathPart(s[1:], '')
106
+ if DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER in s:
107
+ check.equal(s[0], DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER)
108
+ if not any(c in s for c in DEPLOY_PATH_PLACEHOLDER_SEPARATORS):
109
+ return PlaceholderFileDeployPathPart(s[1:], '')
105
110
  else:
106
- p = min(f for c in DEPLOY_PATH_SPEC_SEPARATORS if (f := s.find(c)) > 0)
107
- return SpecFileDeployPathPart(s[1:p], s[p:])
111
+ p = min(f for c in DEPLOY_PATH_PLACEHOLDER_SEPARATORS if (f := s.find(c)) > 0)
112
+ return PlaceholderFileDeployPathPart(s[1:p], s[p:])
108
113
  else:
109
114
  return ConstFileDeployPathPart(s)
110
115
 
@@ -119,9 +124,9 @@ class ConstDeployPathPart(DeployPathPart, abc.ABC):
119
124
  def __post_init__(self) -> None:
120
125
  check.non_empty_str(self.name)
121
126
  check.not_in('/', self.name)
122
- check.not_in(DEPLOY_PATH_SPEC_PLACEHOLDER, self.name)
127
+ check.not_in(DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER, self.name)
123
128
 
124
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
129
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
125
130
  return self.name
126
131
 
127
132
 
@@ -137,40 +142,40 @@ class ConstFileDeployPathPart(ConstDeployPathPart, FileDeployPathPart):
137
142
 
138
143
 
139
144
  @dc.dataclass(frozen=True)
140
- class SpecDeployPathPart(DeployPathPart, abc.ABC):
141
- spec: str # DeployPathSpec
145
+ class PlaceholderDeployPathPart(DeployPathPart, abc.ABC):
146
+ placeholder: str # DeployPathPlaceholder
142
147
 
143
148
  def __post_init__(self) -> None:
144
- check.non_empty_str(self.spec)
145
- for c in [*DEPLOY_PATH_SPEC_SEPARATORS, DEPLOY_PATH_SPEC_PLACEHOLDER, '/']:
146
- check.not_in(c, self.spec)
147
- check.in_(self.spec, DEPLOY_PATH_SPECS)
148
-
149
- def _render_spec(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
150
- if specs is not None:
151
- return specs[self.spec] # type: ignore
149
+ check.non_empty_str(self.placeholder)
150
+ for c in [*DEPLOY_PATH_PLACEHOLDER_SEPARATORS, DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER, '/']:
151
+ check.not_in(c, self.placeholder)
152
+ check.in_(self.placeholder, DEPLOY_PATH_PLACEHOLDERS)
153
+
154
+ def _render_placeholder(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
155
+ if placeholders is not None:
156
+ return placeholders[self.placeholder] # type: ignore
152
157
  else:
153
- return DEPLOY_PATH_SPEC_PLACEHOLDER + self.spec
158
+ return DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER + self.placeholder
154
159
 
155
160
 
156
161
  @dc.dataclass(frozen=True)
157
- class SpecDirDeployPathPart(SpecDeployPathPart, DirDeployPathPart):
158
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
159
- return self._render_spec(specs)
162
+ class PlaceholderDirDeployPathPart(PlaceholderDeployPathPart, DirDeployPathPart):
163
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
164
+ return self._render_placeholder(placeholders)
160
165
 
161
166
 
162
167
  @dc.dataclass(frozen=True)
163
- class SpecFileDeployPathPart(SpecDeployPathPart, FileDeployPathPart):
168
+ class PlaceholderFileDeployPathPart(PlaceholderDeployPathPart, FileDeployPathPart):
164
169
  suffix: str
165
170
 
166
171
  def __post_init__(self) -> None:
167
172
  super().__post_init__()
168
173
  if self.suffix:
169
- for c in [DEPLOY_PATH_SPEC_PLACEHOLDER, '/']:
174
+ for c in [DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER, '/']:
170
175
  check.not_in(c, self.suffix)
171
176
 
172
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
173
- return self._render_spec(specs) + self.suffix
177
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
178
+ return self._render_placeholder(placeholders) + self.suffix
174
179
 
175
180
 
176
181
  ##
@@ -181,28 +186,30 @@ class DeployPath:
181
186
  parts: ta.Sequence[DeployPathPart]
182
187
 
183
188
  def __post_init__(self) -> None:
189
+ hash(self)
190
+
184
191
  check.not_empty(self.parts)
185
192
  for p in self.parts[:-1]:
186
193
  check.equal(p.kind, 'dir')
187
194
 
188
195
  pd = {}
189
196
  for i, p in enumerate(self.parts):
190
- if isinstance(p, SpecDeployPathPart):
191
- if p.spec in pd:
192
- raise DeployPathError('Duplicate specs in path', self)
193
- pd[p.spec] = i
197
+ if isinstance(p, PlaceholderDeployPathPart):
198
+ if p.placeholder in pd:
199
+ raise DeployPathError('Duplicate placeholders in path', self)
200
+ pd[p.placeholder] = i
194
201
 
195
202
  if 'tag' in pd:
196
203
  if 'app' not in pd or pd['app'] >= pd['tag']:
197
- raise DeployPathError('Tag spec in path without preceding app', self)
204
+ raise DeployPathError('Tag placeholder in path without preceding app', self)
198
205
 
199
206
  @property
200
207
  def kind(self) -> ta.Literal['file', 'dir']:
201
208
  return self.parts[-1].kind
202
209
 
203
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
210
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
204
211
  return os.path.join( # noqa
205
- *[p.render(specs) for p in self.parts],
212
+ *[p.render(placeholders) for p in self.parts],
206
213
  *([''] if self.kind == 'dir' else []),
207
214
  )
208
215
 
@@ -215,10 +222,10 @@ class DeployPath:
215
222
  else:
216
223
  tail_parse = FileDeployPathPart.parse
217
224
  ps = check.non_empty_str(s).split('/')
218
- return cls([
225
+ return cls((
219
226
  *([DirDeployPathPart.parse(p) for p in ps[:-1]] if len(ps) > 1 else []),
220
227
  tail_parse(ps[-1]),
221
- ])
228
+ ))
222
229
 
223
230
 
224
231
  ##
@@ -226,5 +233,36 @@ class DeployPath:
226
233
 
227
234
  class DeployPathOwner(abc.ABC):
228
235
  @abc.abstractmethod
229
- def get_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
236
+ def get_owned_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
230
237
  raise NotImplementedError
238
+
239
+
240
+ class SingleDirDeployPathOwner(DeployPathOwner, abc.ABC):
241
+ def __init__(
242
+ self,
243
+ *args: ta.Any,
244
+ owned_dir: str,
245
+ deploy_home: ta.Optional[DeployHome],
246
+ **kwargs: ta.Any,
247
+ ) -> None:
248
+ super().__init__(*args, **kwargs)
249
+
250
+ check.not_in('/', owned_dir)
251
+ self._owned_dir: str = check.non_empty_str(owned_dir)
252
+
253
+ self._deploy_home = deploy_home
254
+
255
+ self._owned_deploy_paths = frozenset([DeployPath.parse(self._owned_dir + '/')])
256
+
257
+ @cached_nullary
258
+ def _dir(self) -> str:
259
+ return os.path.join(check.non_empty_str(self._deploy_home), self._owned_dir)
260
+
261
+ @cached_nullary
262
+ def _make_dir(self) -> str:
263
+ if not os.path.isdir(d := self._dir()):
264
+ os.makedirs(d, exist_ok=True)
265
+ return d
266
+
267
+ def get_owned_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
268
+ return self._owned_deploy_paths
@@ -0,0 +1,42 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import hashlib
4
+ import typing as ta
5
+
6
+ from omlish.lite.cached import cached_nullary
7
+ from omlish.lite.check import check
8
+
9
+ from .types import DeployApp
10
+ from .types import DeployKey
11
+ from .types import DeployRev
12
+
13
+
14
+ ##
15
+
16
+
17
+ @dc.dataclass(frozen=True)
18
+ class DeployGitRepo:
19
+ host: ta.Optional[str] = None
20
+ username: ta.Optional[str] = None
21
+ path: ta.Optional[str] = None
22
+
23
+ def __post_init__(self) -> None:
24
+ check.not_in('..', check.non_empty_str(self.host))
25
+ check.not_in('.', check.non_empty_str(self.path))
26
+
27
+
28
+ ##
29
+
30
+
31
+ @dc.dataclass(frozen=True)
32
+ class DeploySpec:
33
+ app: DeployApp
34
+ repo: DeployGitRepo
35
+ rev: DeployRev
36
+
37
+ def __post_init__(self) -> None:
38
+ hash(self)
39
+
40
+ @cached_nullary
41
+ def key(self) -> DeployKey:
42
+ return DeployKey(hashlib.sha256(repr(self).encode('utf-8')).hexdigest()[:8])
@@ -0,0 +1,46 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.cached import cached_nullary
5
+ from omlish.lite.check import check
6
+
7
+ from .atomics import DeployAtomicPathSwap
8
+ from .atomics import DeployAtomicPathSwapKind
9
+ from .atomics import DeployAtomicPathSwapping
10
+ from .atomics import TempDirDeployAtomicPathSwapping
11
+ from .paths import SingleDirDeployPathOwner
12
+ from .types import DeployHome
13
+
14
+
15
+ class DeployTmpManager(
16
+ SingleDirDeployPathOwner,
17
+ DeployAtomicPathSwapping,
18
+ ):
19
+ def __init__(
20
+ self,
21
+ *,
22
+ deploy_home: ta.Optional[DeployHome] = None,
23
+ ) -> None:
24
+ super().__init__(
25
+ owned_dir='tmp',
26
+ deploy_home=deploy_home,
27
+ )
28
+
29
+ @cached_nullary
30
+ def _swapping(self) -> DeployAtomicPathSwapping:
31
+ return TempDirDeployAtomicPathSwapping(
32
+ temp_dir=self._make_dir(),
33
+ root_dir=check.non_empty_str(self._deploy_home),
34
+ )
35
+
36
+ def begin_atomic_path_swap(
37
+ self,
38
+ kind: DeployAtomicPathSwapKind,
39
+ dst_path: str,
40
+ **kwargs: ta.Any,
41
+ ) -> DeployAtomicPathSwap:
42
+ return self._swapping().begin_atomic_path_swap(
43
+ kind,
44
+ dst_path,
45
+ **kwargs,
46
+ )
@@ -6,6 +6,7 @@ DeployHome = ta.NewType('DeployHome', str)
6
6
  DeployApp = ta.NewType('DeployApp', str)
7
7
  DeployTag = ta.NewType('DeployTag', str)
8
8
  DeployRev = ta.NewType('DeployRev', str)
9
+ DeployKey = ta.NewType('DeployKey', str)
9
10
 
10
11
 
11
12
  class DeployAppTag(ta.NamedTuple):
@@ -7,8 +7,11 @@ TODO:
7
7
  import os.path
8
8
  import typing as ta
9
9
 
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
10
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
11
+ from omlish.lite.cached import cached_nullary
12
+ from omlish.lite.check import check
11
13
 
14
+ from .atomics import DeployAtomicPathSwapping
12
15
  from .paths import DeployPath
13
16
  from .paths import DeployPathOwner
14
17
  from .types import DeployAppTag
@@ -19,14 +22,19 @@ class DeployVenvManager(DeployPathOwner):
19
22
  def __init__(
20
23
  self,
21
24
  *,
22
- deploy_home: DeployHome,
25
+ deploy_home: ta.Optional[DeployHome] = None,
26
+ atomics: DeployAtomicPathSwapping,
23
27
  ) -> None:
24
28
  super().__init__()
25
29
 
26
30
  self._deploy_home = deploy_home
27
- self._dir = os.path.join(deploy_home, 'venvs')
31
+ self._atomics = atomics
28
32
 
29
- def get_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
33
+ @cached_nullary
34
+ def _dir(self) -> str:
35
+ return os.path.join(check.non_empty_str(self._deploy_home), 'venvs')
36
+
37
+ def get_owned_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
30
38
  return {
31
39
  DeployPath.parse('venvs/@app/@tag/'),
32
40
  }
@@ -40,6 +48,8 @@ class DeployVenvManager(DeployPathOwner):
40
48
  ) -> None:
41
49
  sys_exe = 'python3'
42
50
 
51
+ # !! NOTE: (most) venvs cannot be relocated, so an atomic swap can't be used. it's up to the path manager to
52
+ # garbage collect orphaned dirs.
43
53
  await asyncio_subprocesses.check_call(sys_exe, '-m', 'venv', venv_dir)
44
54
 
45
55
  #
@@ -61,6 +71,6 @@ class DeployVenvManager(DeployPathOwner):
61
71
 
62
72
  async def setup_app_venv(self, app_tag: DeployAppTag) -> None:
63
73
  await self.setup_venv(
64
- os.path.join(self._deploy_home, 'apps', app_tag.app, app_tag.tag),
65
- os.path.join(self._deploy_home, 'venvs', app_tag.app, app_tag.tag),
74
+ os.path.join(check.non_empty_str(self._deploy_home), 'apps', app_tag.app, app_tag.tag),
75
+ os.path.join(self._dir(), app_tag.app, app_tag.tag),
66
76
  )
@@ -7,10 +7,10 @@ import shlex
7
7
  import subprocess
8
8
  import typing as ta
9
9
 
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
10
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
11
11
  from omlish.lite.check import check
12
- from omlish.lite.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
- from omlish.lite.subprocesses import SubprocessChannelOption
12
+ from omlish.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
+ from omlish.subprocesses import SubprocessChannelOption
14
14
 
15
15
 
16
16
  ##
@@ -9,7 +9,7 @@ import json
9
9
  import os
10
10
  import typing as ta
11
11
 
12
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
12
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
13
13
  from omlish.lite.check import check
14
14
 
15
15
 
ominfra/pyremote.py CHANGED
@@ -162,7 +162,7 @@ def _pyremote_bootstrap_main(context_name: str) -> None:
162
162
  # Get pid
163
163
  pid = os.getpid()
164
164
 
165
- # Two copies of main src to be sent to parent
165
+ # Two copies of payload src to be sent to parent
166
166
  r0, w0 = os.pipe()
167
167
  r1, w1 = os.pipe()
168
168
 
@@ -201,17 +201,17 @@ def _pyremote_bootstrap_main(context_name: str) -> None:
201
201
  # Write pid
202
202
  os.write(1, struct.pack('<Q', pid))
203
203
 
204
- # Read main src from stdin
205
- main_z_len = struct.unpack('<I', os.read(0, 4))[0]
206
- if len(main_z := os.fdopen(0, 'rb').read(main_z_len)) != main_z_len:
204
+ # Read payload src from stdin
205
+ payload_z_len = struct.unpack('<I', os.read(0, 4))[0]
206
+ if len(payload_z := os.fdopen(0, 'rb').read(payload_z_len)) != payload_z_len:
207
207
  raise EOFError
208
- main_src = zlib.decompress(main_z)
208
+ payload_src = zlib.decompress(payload_z)
209
209
 
210
- # Write both copies of main src. Must write to w0 (parent stdin) before w1 (copy pipe) as pipe will likely fill
211
- # and block and need to be drained by pyremote_bootstrap_finalize running in parent.
210
+ # Write both copies of payload src. Must write to w0 (parent stdin) before w1 (copy pipe) as pipe will likely
211
+ # fill and block and need to be drained by pyremote_bootstrap_finalize running in parent.
212
212
  for w in [w0, w1]:
213
213
  fp = os.fdopen(w, 'wb', 0)
214
- fp.write(main_src)
214
+ fp.write(payload_src)
215
215
  fp.close()
216
216
 
217
217
  # Write second ack
@@ -275,7 +275,7 @@ class PyremotePayloadRuntime:
275
275
  input: ta.BinaryIO
276
276
  output: ta.BinaryIO
277
277
  context_name: str
278
- main_src: str
278
+ payload_src: str
279
279
  options: PyremoteBootstrapOptions
280
280
  env_info: PyremoteEnvInfo
281
281
 
@@ -283,9 +283,9 @@ class PyremotePayloadRuntime:
283
283
  def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
284
284
  # If src file var is not present we need to do initial finalization
285
285
  if _PYREMOTE_BOOTSTRAP_SRC_FILE_VAR not in os.environ:
286
- # Read second copy of main src
286
+ # Read second copy of payload src
287
287
  r1 = os.fdopen(_PYREMOTE_BOOTSTRAP_SRC_FD, 'rb', 0)
288
- main_src = r1.read().decode('utf-8')
288
+ payload_src = r1.read().decode('utf-8')
289
289
  r1.close()
290
290
 
291
291
  # Reap boostrap child. Must be done after reading second copy of source because source may be too big to fit in
@@ -303,7 +303,7 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
303
303
  # Write temp source file
304
304
  import tempfile
305
305
  tfd, tfn = tempfile.mkstemp('-pyremote.py')
306
- os.write(tfd, main_src.encode('utf-8'))
306
+ os.write(tfd, payload_src.encode('utf-8'))
307
307
  os.close(tfd)
308
308
 
309
309
  # Set vars
@@ -322,7 +322,7 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
322
322
 
323
323
  # Read temp source file
324
324
  with open(os.environ.pop(_PYREMOTE_BOOTSTRAP_SRC_FILE_VAR)) as sf:
325
- main_src = sf.read()
325
+ payload_src = sf.read()
326
326
 
327
327
  # Restore vars
328
328
  sys.executable = os.environ.pop(_PYREMOTE_BOOTSTRAP_ARGV0_VAR)
@@ -355,7 +355,7 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
355
355
  input=input,
356
356
  output=output,
357
357
  context_name=context_name,
358
- main_src=main_src,
358
+ payload_src=payload_src,
359
359
  options=options,
360
360
  env_info=env_info,
361
361
  )
@@ -367,31 +367,31 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
367
367
  class PyremoteBootstrapDriver:
368
368
  def __init__(
369
369
  self,
370
- main_src: ta.Union[str, ta.Sequence[str]],
370
+ payload_src: ta.Union[str, ta.Sequence[str]],
371
371
  options: PyremoteBootstrapOptions = PyremoteBootstrapOptions(),
372
372
  ) -> None:
373
373
  super().__init__()
374
374
 
375
- self._main_src = main_src
375
+ self._payload_src = payload_src
376
376
  self._options = options
377
377
 
378
- self._prepared_main_src = self._prepare_main_src(main_src, options)
379
- self._main_z = zlib.compress(self._prepared_main_src.encode('utf-8'))
378
+ self._prepared_payload_src = self._prepare_payload_src(payload_src, options)
379
+ self._payload_z = zlib.compress(self._prepared_payload_src.encode('utf-8'))
380
380
 
381
381
  self._options_json = json.dumps(dc.asdict(options), indent=None, separators=(',', ':')).encode('utf-8') # noqa
382
382
  #
383
383
 
384
384
  @classmethod
385
- def _prepare_main_src(
385
+ def _prepare_payload_src(
386
386
  cls,
387
- main_src: ta.Union[str, ta.Sequence[str]],
387
+ payload_src: ta.Union[str, ta.Sequence[str]],
388
388
  options: PyremoteBootstrapOptions,
389
389
  ) -> str:
390
390
  parts: ta.List[str]
391
- if isinstance(main_src, str):
392
- parts = [main_src]
391
+ if isinstance(payload_src, str):
392
+ parts = [payload_src]
393
393
  else:
394
- parts = list(main_src)
394
+ parts = list(payload_src)
395
395
 
396
396
  if (mn := options.main_name_override) is not None:
397
397
  parts.insert(0, f'__name__ = {mn!r}')
@@ -427,9 +427,9 @@ class PyremoteBootstrapDriver:
427
427
  d = yield from self._read(8)
428
428
  pid = struct.unpack('<Q', d)[0]
429
429
 
430
- # Write main src
431
- yield from self._write(struct.pack('<I', len(self._main_z)))
432
- yield from self._write(self._main_z)
430
+ # Write payload src
431
+ yield from self._write(struct.pack('<I', len(self._payload_z)))
432
+ yield from self._write(self._payload_z)
433
433
 
434
434
  # Read second ack (after writing src copies)
435
435
  yield from self._expect(_PYREMOTE_BOOTSTRAP_ACK1)