protoprimer 0.0.2.dev0__tar.gz → 0.0.2.dev2__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: protoprimer
3
- Version: 0.0.2.dev0
3
+ Version: 0.0.2.dev2
4
4
  Summary: universal multi-stage `python` environment initializer & bootstrapper (primer) via a stand-alone automatic (proto) script
5
5
  Author: uvsmtid
6
6
  Author-email: uvsmtid@gmail.com
@@ -35,7 +35,7 @@ import venv
35
35
 
36
36
  # Implements this (using the single script directly without a separate `_version.py` file):
37
37
  # https://stackoverflow.com/a/7071358/441652
38
- __version__ = "0.0.2.dev0"
38
+ __version__ = "0.0.2.dev2"
39
39
 
40
40
  from typing import (
41
41
  Any,
@@ -95,59 +95,55 @@ def init_arg_parser():
95
95
  )
96
96
 
97
97
  arg_parser.add_argument(
98
- # TODO: put in ArgConst:
99
- "--context_phase",
98
+ ArgConst.arg_context_phase,
100
99
  type=str,
101
- choices=[context_phase.name for context_phase in ContextPhase],
102
- default=ContextPhase.proto_primer.name,
103
- help=f"Select `{ContextPhase.__name__}`.",
100
+ choices=[context_phase.name for context_phase in PrimerPhase],
101
+ default=PrimerPhase.phase_proto.name,
102
+ help=f"Select `{PrimerPhase.__name__}`.",
104
103
  )
105
104
  arg_parser.add_argument(
106
- "-s",
107
- # TODO: put in ArgConst:
108
- "--silent",
105
+ ArgConst.arg_s,
106
+ ArgConst.arg_silent,
109
107
  action="store_true",
110
- dest="log_level_silent",
108
+ dest=ArgConst.dest_silent,
111
109
  # In the case of exceptions, stack traces are still printed:
112
- help="Do not log, use non-zero exit code on error.",
110
+ help="Do not log (set only non-zero exit code on error).",
113
111
  )
114
112
  arg_parser.add_argument(
115
- "-q",
116
- # TODO: put in ArgConst:
117
- "--quiet",
113
+ ArgConst.arg_q,
114
+ ArgConst.arg_quiet,
118
115
  action="store_true",
119
- dest="log_level_quiet",
116
+ dest=ArgConst.dest_quiet,
120
117
  help="Log errors messages only.",
121
118
  )
122
119
  arg_parser.add_argument(
123
- "-v",
124
- # TODO: put in ArgConst:
125
- "--verbose",
120
+ ArgConst.arg_v,
121
+ ArgConst.arg_verbose,
126
122
  action="count",
127
- dest="log_level_verbose",
123
+ dest=ArgConst.dest_verbose,
128
124
  default=0,
129
- help="Log debug messages.",
125
+ help="Increase log verbosity level.",
130
126
  )
131
127
  arg_parser.add_argument(
132
- # TODO: put in ArgConst:
133
- "--run_mode",
128
+ ArgConst.arg_run_mode,
134
129
  type=str,
135
130
  choices=[run_mode.name for run_mode in RunMode],
136
131
  default=RunMode.bootstrap_env.name,
137
- help="Select run mode.",
132
+ help=f"Select {RunMode.__name__}.",
138
133
  )
139
134
  arg_parser.add_argument(
140
- # TODO: put in ArgConst:
141
- "--state_name",
135
+ ArgConst.arg_state_name,
142
136
  type=str,
137
+ # TODO: Provide choices?
138
+ # TODO: Provide default?
143
139
  default=None,
144
140
  # TODO: Compute universal sink:
145
- help="Select state name to start with (default = universal sink).",
141
+ help=f"Select target {EnvState.__name__}.",
146
142
  )
147
143
  # TODO: use it with special `--init_repo` flag (otherwise, do not allow):
148
144
  arg_parser.add_argument(
149
145
  ArgConst.arg_client_dir_path,
150
- nargs="?",
146
+ type=str,
151
147
  default=None,
152
148
  help="Path to client root dir (relative to current directory or absolute).",
153
149
  )
@@ -156,12 +152,12 @@ def init_arg_parser():
156
152
  type=str,
157
153
  choices=[py_exec.name for py_exec in PythonExecutable],
158
154
  default=PythonExecutable.py_exec_unknown.name,
159
- help="Used internally: category of `python` executable detected by recursive invocation.",
155
+ help=f"Used internally: override {PythonExecutable.__name__}.",
160
156
  )
161
157
  # TODO: use it with special `--init_repo` flag (otherwise, do not allow):
162
158
  arg_parser.add_argument(
163
159
  ArgConst.arg_conf_env_path,
164
- nargs="?",
160
+ type=str,
165
161
  default=None,
166
162
  # TODO: Rephrase (it should be more generic):
167
163
  help="Path to one of the dirs (normally under `@/dst/`) to be used as target for `@/conf/` symlink.",
@@ -285,22 +281,43 @@ def install_editable_package(
285
281
  )
286
282
 
287
283
 
288
- class ContextPhase(enum.Enum):
284
+ # TODO: Rename to ConfBundle:
285
+ class PrimerConf(enum.Enum):
286
+ """
287
+ See: FS_89_41_35_82.conf_bundle.md
288
+ """
289
+
290
+ conf_proto = enum.auto()
291
+
292
+ conf_client = enum.auto()
293
+
294
+ conf_env = enum.auto()
295
+
296
+
297
+ class PrimerPhase(enum.Enum):
298
+ """
299
+ See: FS_14_52_73_23.primer_phase.md
300
+ """
289
301
 
290
- proto_primer = enum.auto()
302
+ phase_proto = enum.auto()
291
303
 
292
- venv_primer = enum.auto()
304
+ phase_venv = enum.auto()
293
305
 
294
306
 
295
307
  class RunMode(enum.Enum):
296
308
  """
297
309
  Various modes the script can be run in.
310
+
311
+ See: FS_11_27_29_83.run_mode.md
298
312
  """
299
313
 
300
314
  print_dag = enum.auto()
301
315
 
302
316
  bootstrap_env = enum.auto()
303
317
 
318
+ # TODO: implement:
319
+ check_env = enum.auto()
320
+
304
321
 
305
322
  class AbstractBootstrapperVisitor:
306
323
  """
@@ -368,8 +385,11 @@ class SinkPrinterVisitor(AbstractBootstrapperVisitor):
368
385
  class PythonExecutable(enum.IntEnum):
369
386
  """
370
387
  Python executables started during the bootstrap process - each replaces the executable program (via `os.execv`).
388
+
389
+ See: FS_72_45_12_06.python_executable.md
371
390
  """
372
391
 
392
+ # TODO: rename to `unpredictable`
373
393
  # `python` executable has not been categorized yet:
374
394
  py_exec_unknown = -1
375
395
 
@@ -613,7 +633,7 @@ class Bootstrapper_state_proto_kernel_config_file_path(
613
633
  )
614
634
  return os.path.join(
615
635
  state_proto_kernel_dir_path,
616
- ConfConstInput.default_file_basename_conf_primer,
636
+ ConfConstInput.default_file_basename_conf_proto,
617
637
  )
618
638
 
619
639
 
@@ -1234,22 +1254,6 @@ class Bootstrapper_state_py_exec_selected(
1234
1254
  f"to re-create it automatically. "
1235
1255
  )
1236
1256
 
1237
- def switch_to_required_python():
1238
- assert state_py_exec_specified == PythonExecutable.py_exec_unknown
1239
- self.env_ctx.py_exec = PythonExecutable.py_exec_arbitrary
1240
- logger.info(
1241
- f"switching from current `python` interpreter [{path_to_curr_python}] to required one [{state_env_path_to_python}]"
1242
- )
1243
- os.execv(
1244
- state_env_path_to_python,
1245
- [
1246
- state_env_path_to_python,
1247
- *sys.argv,
1248
- ArgConst.arg_py_exec,
1249
- PythonExecutable.py_exec_required.name,
1250
- ],
1251
- )
1252
-
1253
1257
  venv_path_to_python = os.path.join(
1254
1258
  state_env_path_to_venv,
1255
1259
  ConfConstGeneral.file_rel_path_venv_python,
@@ -1257,8 +1261,15 @@ class Bootstrapper_state_py_exec_selected(
1257
1261
  path_to_curr_python = get_path_to_curr_python()
1258
1262
  if is_sub_path(path_to_curr_python, state_env_path_to_venv):
1259
1263
  if path_to_curr_python != venv_path_to_python:
1264
+ assert state_py_exec_specified == PythonExecutable.py_exec_unknown
1265
+ self.env_ctx.py_exec = PythonExecutable.py_exec_arbitrary
1260
1266
  # Ensure `python` is from the correct `venv` path
1261
- switch_to_required_python()
1267
+ self.env_ctx.switch_python(
1268
+ curr_py_exec=state_py_exec_specified,
1269
+ curr_python_path=path_to_curr_python,
1270
+ next_py_exec=PythonExecutable.py_exec_required,
1271
+ next_python_path=state_env_path_to_python,
1272
+ )
1262
1273
  else:
1263
1274
  # If already under `venv` with the expected path, nothing to do.
1264
1275
  assert (
@@ -1272,7 +1283,14 @@ class Bootstrapper_state_py_exec_selected(
1272
1283
  self.env_ctx.py_exec = state_py_exec_specified
1273
1284
  else:
1274
1285
  if path_to_curr_python != state_env_path_to_python:
1275
- switch_to_required_python()
1286
+ assert state_py_exec_specified == PythonExecutable.py_exec_unknown
1287
+ self.env_ctx.py_exec = PythonExecutable.py_exec_arbitrary
1288
+ self.env_ctx.switch_python(
1289
+ curr_py_exec=state_py_exec_specified,
1290
+ curr_python_path=path_to_curr_python,
1291
+ next_py_exec=PythonExecutable.py_exec_required,
1292
+ next_python_path=state_env_path_to_python,
1293
+ )
1276
1294
  else:
1277
1295
  assert (
1278
1296
  state_py_exec_specified == PythonExecutable.py_exec_unknown
@@ -1287,17 +1305,11 @@ class Bootstrapper_state_py_exec_selected(
1287
1305
  )
1288
1306
  else:
1289
1307
  logger.info(f"reusing existing `venv` [{state_env_path_to_venv}]")
1290
- logger.info(
1291
- f"switching from current `python` interpreter [{state_env_path_to_python}] to `venv` interpreter [{venv_path_to_python}]"
1292
- )
1293
- os.execv(
1294
- venv_path_to_python,
1295
- [
1296
- venv_path_to_python,
1297
- *sys.argv,
1298
- ArgConst.arg_py_exec,
1299
- PythonExecutable.py_exec_venv.name,
1300
- ],
1308
+ self.env_ctx.switch_python(
1309
+ curr_py_exec=state_py_exec_specified,
1310
+ curr_python_path=state_env_path_to_python,
1311
+ next_py_exec=PythonExecutable.py_exec_venv,
1312
+ next_python_path=venv_path_to_python,
1301
1313
  )
1302
1314
 
1303
1315
  return self.env_ctx.py_exec
@@ -1411,17 +1423,15 @@ class Bootstrapper_state_py_exec_updated_protoprimer_package_reached(
1411
1423
  < PythonExecutable.py_exec_updated_protoprimer_package.value
1412
1424
  ):
1413
1425
  self.env_ctx.py_exec = PythonExecutable.py_exec_updated_protoprimer_package
1414
- logger.info(
1426
+ # TODO: maybe add this reason to `switch_python` as an arg?
1427
+ logger.debug(
1415
1428
  f"restarting current `python` interpreter [{venv_path_to_python}] to make [{EnvState.state_protoprimer_package_installed.name}] effective"
1416
1429
  )
1417
- os.execv(
1418
- venv_path_to_python,
1419
- [
1420
- venv_path_to_python,
1421
- *sys.argv,
1422
- ArgConst.arg_py_exec,
1423
- PythonExecutable.py_exec_updated_protoprimer_package.name,
1424
- ],
1430
+ self.env_ctx.switch_python(
1431
+ curr_py_exec=state_py_exec_specified,
1432
+ curr_python_path=venv_path_to_python,
1433
+ next_py_exec=PythonExecutable.py_exec_updated_protoprimer_package,
1434
+ next_python_path=venv_path_to_python,
1425
1435
  )
1426
1436
  else:
1427
1437
  # Successfully reached end goal:
@@ -1545,17 +1555,15 @@ class Bootstrapper_state_py_exec_updated_proto_kernel_code(
1545
1555
  < PythonExecutable.py_exec_updated_proto_kernel_code.value
1546
1556
  ):
1547
1557
  self.env_ctx.py_exec = PythonExecutable.py_exec_updated_proto_kernel_code
1548
- logger.info(
1558
+ # TODO: maybe add this reason to `switch_python` as an arg?
1559
+ logger.debug(
1549
1560
  f"restarting current `python` interpreter [{venv_path_to_python}] to make [{EnvState.state_proto_kernel_updated.name}] effective"
1550
1561
  )
1551
- os.execv(
1552
- venv_path_to_python,
1553
- [
1554
- venv_path_to_python,
1555
- *sys.argv,
1556
- ArgConst.arg_py_exec,
1557
- PythonExecutable.py_exec_updated_proto_kernel_code.name,
1558
- ],
1562
+ self.env_ctx.switch_python(
1563
+ curr_py_exec=state_py_exec_specified,
1564
+ curr_python_path=venv_path_to_python,
1565
+ next_py_exec=PythonExecutable.py_exec_updated_proto_kernel_code,
1566
+ next_python_path=venv_path_to_python,
1559
1567
  )
1560
1568
  else:
1561
1569
  # Successfully reached end goal:
@@ -1632,6 +1640,8 @@ class EnvState(enum.Enum):
1632
1640
  Configuration states to be bootstrapped during the bootstrap process.
1633
1641
 
1634
1642
  NOTE: Only `str` names of the enum items are supposed to be used (any value is ignored).
1643
+
1644
+ See: FS_68_54_41_96.state_dependency.md
1635
1645
  """
1636
1646
 
1637
1647
  def __init__(
@@ -1737,16 +1747,45 @@ class TargetState:
1737
1747
 
1738
1748
  class ArgConst:
1739
1749
 
1740
- # TODO: decide on convention for pure `arg_name` and `--arg_name`:
1741
1750
  name_conf_env_path = "conf_env_path"
1742
1751
  name_recursion_flag = "recursion_flag"
1743
1752
  name_client_dir_path = "client_dir_path"
1744
1753
  name_py_exec = "py_exec"
1754
+ name_context_phase = "context_phase"
1755
+ name_run_mode = "run_mode"
1756
+ name_state_name = "state_name"
1757
+
1758
+ name_s = "s"
1759
+ name_silent = "silent"
1760
+
1761
+ name_q = "q"
1762
+ name_quiet = "quiet"
1763
+
1764
+ name_v = "v"
1765
+ name_verbose = "verbose"
1766
+
1767
+ prefix_log_level = "log_level"
1745
1768
 
1746
1769
  arg_conf_env_path = f"--{name_conf_env_path}"
1747
1770
  arg_recursion_flag = f"--{name_recursion_flag}"
1748
1771
  arg_client_dir_path = f"--{name_client_dir_path}"
1749
1772
  arg_py_exec = f"--{name_py_exec}"
1773
+ arg_context_phase = f"--{name_context_phase}"
1774
+ arg_run_mode = f"--{name_run_mode}"
1775
+ arg_state_name = f"--{name_state_name}"
1776
+
1777
+ arg_s = f"-{name_s}"
1778
+ arg_silent = f"--{name_silent}"
1779
+ value_silent = f"--{name_silent}"
1780
+ dest_silent = f"log_level_{name_silent}"
1781
+
1782
+ arg_q = f"-{name_q}"
1783
+ arg_quiet = f"--{name_quiet}"
1784
+ dest_quiet = f"log_level_{name_quiet}"
1785
+
1786
+ arg_v = f"-{name_v}"
1787
+ arg_verbose = f"--{name_verbose}"
1788
+ dest_verbose = f"log_level_{name_verbose}"
1750
1789
 
1751
1790
 
1752
1791
  class ConfConstGeneral:
@@ -1791,9 +1830,7 @@ class ConfConstInput:
1791
1830
  file_abs_path_script = ConfConstGeneral.input_based
1792
1831
  dir_abs_path_current = ConfConstGeneral.input_based
1793
1832
 
1794
- default_file_basename_conf_primer = (
1795
- f"conf_primer.{ConfConstGeneral.default_primer_kernel_module}.json"
1796
- )
1833
+ default_file_basename_conf_proto = f"{PrimerConf.conf_proto.name}.{ConfConstGeneral.default_primer_kernel_module}.json"
1797
1834
 
1798
1835
 
1799
1836
  class ConfConstPrimer:
@@ -2075,6 +2112,26 @@ class EnvContext:
2075
2112
  # `generate_files`
2076
2113
  # TODO: TODO_11_66_62_70: python_bootstrap:
2077
2114
 
2115
+ def switch_python(
2116
+ self,
2117
+ curr_py_exec: PythonExecutable,
2118
+ curr_python_path: str,
2119
+ next_py_exec: PythonExecutable,
2120
+ next_python_path: str,
2121
+ ):
2122
+ logger.info(
2123
+ f"switching from current `python` interpreter [{curr_python_path}][{curr_py_exec.name}] to [{next_python_path}][{next_py_exec.name}]"
2124
+ )
2125
+ os.execv(
2126
+ next_python_path,
2127
+ [
2128
+ next_python_path,
2129
+ *sys.argv,
2130
+ ArgConst.arg_py_exec,
2131
+ next_py_exec.name,
2132
+ ],
2133
+ )
2134
+
2078
2135
 
2079
2136
  class CustomFormatter(logging.Formatter):
2080
2137
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: protoprimer
3
- Version: 0.0.2.dev0
3
+ Version: 0.0.2.dev2
4
4
  Summary: universal multi-stage `python` environment initializer & bootstrapper (primer) via a stand-alone automatic (proto) script
5
5
  Author: uvsmtid
6
6
  Author-email: uvsmtid@gmail.com