runem 0.0.28__py3-none-any.whl → 0.0.30__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.
runem/runem.py CHANGED
@@ -34,18 +34,19 @@ from timeit import default_timer as timer
34
34
  from halo import Halo
35
35
 
36
36
  from runem.command_line import parse_args
37
- from runem.config import load_config
37
+ from runem.config import load_project_config, load_user_configs
38
38
  from runem.config_metadata import ConfigMetadata
39
- from runem.config_parse import parse_config
39
+ from runem.config_parse import load_config_metadata
40
40
  from runem.files import find_files
41
41
  from runem.job import Job
42
42
  from runem.job_execute import job_execute
43
43
  from runem.job_filter import filter_jobs
44
- from runem.log import log
44
+ from runem.log import error, log, warn
45
45
  from runem.report import report_on_run
46
46
  from runem.types import (
47
47
  Config,
48
48
  FilePathListLookup,
49
+ HookName,
49
50
  JobReturn,
50
51
  JobRunMetadata,
51
52
  JobRunMetadatasByPhase,
@@ -68,8 +69,11 @@ def _determine_run_parameters(argv: typing.List[str]) -> ConfigMetadata:
68
69
  """
69
70
  config: Config
70
71
  cfg_filepath: pathlib.Path
71
- config, cfg_filepath = load_config()
72
- config_metadata: ConfigMetadata = parse_config(config, cfg_filepath)
72
+ config, cfg_filepath = load_project_config()
73
+ user_configs: typing.List[typing.Tuple[Config, pathlib.Path]] = load_user_configs()
74
+ config_metadata: ConfigMetadata = load_config_metadata(
75
+ config, cfg_filepath, user_configs, verbose=("--verbose" in argv)
76
+ )
73
77
 
74
78
  # Now we parse the cli arguments extending them with information from the
75
79
  # .runem.yml config.
@@ -263,18 +267,21 @@ def _process_jobs_by_phase(
263
267
  )
264
268
  if failure_exception is not None:
265
269
  if config_metadata.args.verbose:
266
- log(f"ERROR: running phase {phase}: aborting run")
270
+ error(f"running phase {phase}: aborting run")
267
271
  return failure_exception
268
272
 
269
273
  # ALl phases completed aok.
270
274
  return None
271
275
 
272
276
 
277
+ MainReturnType = typing.Tuple[
278
+ ConfigMetadata, JobRunMetadatasByPhase, typing.Optional[BaseException]
279
+ ]
280
+
281
+
273
282
  def _main(
274
283
  argv: typing.List[str],
275
- ) -> typing.Tuple[
276
- OrderedPhases, JobRunMetadatasByPhase, typing.Optional[BaseException]
277
- ]:
284
+ ) -> MainReturnType:
278
285
  start = timer()
279
286
 
280
287
  config_metadata: ConfigMetadata = _determine_run_parameters(argv)
@@ -283,7 +290,10 @@ def _main(
283
290
  os.chdir(config_metadata.cfg_filepath.parent)
284
291
 
285
292
  file_lists: FilePathListLookup = find_files(config_metadata)
286
- assert file_lists
293
+ if not file_lists:
294
+ warn("no files found")
295
+ return (config_metadata, {}, None)
296
+
287
297
  if config_metadata.args.verbose:
288
298
  log(f"found {len(file_lists)} batches, ", end="")
289
299
  for tag in sorted(file_lists.keys()):
@@ -297,9 +307,11 @@ def _main(
297
307
  end = timer()
298
308
 
299
309
  job_run_metadatas: JobRunMetadatasByPhase = defaultdict(list)
300
- job_run_metadatas["_app"].append(
301
- (("pre-build", (timedelta(seconds=end - start))), None)
302
- )
310
+ pre_build_time: JobTiming = {
311
+ "job": ("pre-build", (timedelta(seconds=end - start))),
312
+ "commands": [],
313
+ }
314
+ job_run_metadatas["_app"].append((pre_build_time, None))
303
315
 
304
316
  start = timer()
305
317
 
@@ -313,11 +325,14 @@ def _main(
313
325
 
314
326
  end = timer()
315
327
 
316
- phase_run_timing: JobTiming = ("run-phases", timedelta(seconds=end - start))
328
+ phase_run_timing: JobTiming = {
329
+ "job": ("run-phases", timedelta(seconds=end - start)),
330
+ "commands": [],
331
+ }
317
332
  phase_run_report: JobReturn = None
318
333
  phase_run_metadata: JobRunMetadata = (phase_run_timing, phase_run_report)
319
334
  job_run_metadatas["_app"].append(phase_run_metadata)
320
- return config_metadata.phases, job_run_metadatas, failure_exception
335
+ return config_metadata, job_run_metadatas, failure_exception
321
336
 
322
337
 
323
338
  def timed_main(argv: typing.List[str]) -> None:
@@ -327,23 +342,35 @@ def timed_main(argv: typing.List[str]) -> None:
327
342
  are representative.
328
343
  """
329
344
  start = timer()
330
- phase_run_oder: OrderedPhases
345
+ config_metadata: ConfigMetadata
331
346
  job_run_metadatas: JobRunMetadatasByPhase
332
347
  failure_exception: typing.Optional[BaseException]
333
- phase_run_oder, job_run_metadatas, failure_exception = _main(argv)
348
+ config_metadata, job_run_metadatas, failure_exception = _main(argv)
349
+ phase_run_oder: OrderedPhases = config_metadata.phases
334
350
  end = timer()
335
351
  time_taken: timedelta = timedelta(seconds=end - start)
336
- time_saved = report_on_run(phase_run_oder, job_run_metadatas, time_taken)
352
+ wall_clock_time_saved: timedelta
353
+ system_time_spent: timedelta
354
+ system_time_spent, wall_clock_time_saved = report_on_run(
355
+ phase_run_oder, job_run_metadatas, time_taken
356
+ )
337
357
  message: str = "DONE: runem took"
338
358
  if failure_exception:
339
359
  message = "FAILED: your jobs failed after"
340
360
  log(
341
361
  (
342
362
  f"{message}: {time_taken.total_seconds()}s, "
343
- f"saving you {time_saved.total_seconds()}s"
363
+ f"saving you {wall_clock_time_saved.total_seconds()}s, "
364
+ f"without runem you would have waited {system_time_spent.total_seconds()}s"
344
365
  )
345
366
  )
346
367
 
368
+ config_metadata.hook_manager.invoke_hooks(
369
+ hook_name=HookName.ON_EXIT,
370
+ config_metadata=config_metadata,
371
+ wall_clock_time_saved=wall_clock_time_saved,
372
+ )
373
+
347
374
  if failure_exception is not None:
348
375
  # we got a failure somewhere, now that we've reported the timings we
349
376
  # re-raise.
runem/types.py CHANGED
@@ -2,6 +2,7 @@ import argparse
2
2
  import pathlib
3
3
  import typing
4
4
  from datetime import timedelta
5
+ from enum import Enum
5
6
 
6
7
  from runem.informative_dict import InformativeDict, ReadOnlyInformativeDict
7
8
 
@@ -26,13 +27,36 @@ ReportUrlInfo = typing.Tuple[ReportName, ReportUrl]
26
27
  ReportUrls = typing.List[ReportUrlInfo]
27
28
 
28
29
 
30
+ class HookName(Enum):
31
+ # at exit
32
+ ON_EXIT = "on-exit"
33
+ # before all tasks are run, after config is read
34
+ # BEFORE_ALL = "before-all"
35
+ # after all tasks are done, before reporting
36
+ # AFTER_ALL = "after-all"
37
+
38
+
29
39
  class JobReturnData(typing.TypedDict, total=False):
30
40
  """A dict that defines job result to be reported to the user."""
31
41
 
32
42
  reportUrls: ReportUrls # urls containing reports for the user
33
43
 
34
44
 
35
- JobTiming = typing.Tuple[str, timedelta]
45
+ TimingEntry = typing.Tuple[str, timedelta]
46
+ TimingEntries = typing.List[TimingEntry]
47
+
48
+
49
+ class JobTiming(typing.TypedDict, total=True):
50
+ """A hierarchy of timing info. Job->JobCommands.
51
+
52
+ The overall time for a job is in 'job', the child calls to run_command are in
53
+ 'commands'
54
+ """
55
+
56
+ job: TimingEntry # the overall time for a job
57
+ commands: TimingEntries # timing for each call to `run_command`
58
+
59
+
36
60
  JobReturn = typing.Optional[JobReturnData]
37
61
  JobRunMetadata = typing.Tuple[JobTiming, JobReturn]
38
62
  JobRunTimesByPhase = typing.Dict[PhaseName, typing.List[JobTiming]]
@@ -111,7 +135,14 @@ class JobWhen(typing.TypedDict, total=False):
111
135
  phase: PhaseName # the phase when the job should be run
112
136
 
113
137
 
114
- class JobConfig(typing.TypedDict, total=False):
138
+ class JobWrapper(typing.TypedDict, total=False):
139
+ """A base-type for jobs, hooks, and things that can be invoked."""
140
+
141
+ addr: JobAddressConfig # which callable to call
142
+ command: str # a one-liner command to be run
143
+
144
+
145
+ class JobConfig(JobWrapper, total=False):
115
146
  """A dict that defines a job to be run.
116
147
 
117
148
  It consists of the label, address, context and filter information
@@ -120,8 +151,6 @@ class JobConfig(typing.TypedDict, total=False):
120
151
  """
121
152
 
122
153
  label: JobName # the name of the job
123
- addr: JobAddressConfig # which callable to call
124
- command: str # a one-liner command to be run
125
154
  ctx: typing.Optional[JobContextConfig] # how to call the callable
126
155
  when: JobWhen # when to call the job
127
156
 
@@ -179,6 +208,30 @@ class GlobalSerialisedConfig(typing.TypedDict):
179
208
  config: GlobalConfig
180
209
 
181
210
 
211
+ class HookConfig(JobWrapper, total=False):
212
+ """Specification for hooks.
213
+
214
+ Like JobConfig with use addr or command to specify what to execute.
215
+ """
216
+
217
+ hook_name: HookName # the hook for when this is called
218
+
219
+
220
+ Hooks = typing.DefaultDict[HookName, typing.List[HookConfig]]
221
+
222
+ # A dictionary to hold hooks, with hook names as keys
223
+ HooksStore = typing.Dict[HookName, typing.List[HookConfig]]
224
+
225
+
226
+ class HookSerialisedConfig(typing.TypedDict):
227
+ """Intended to make reading a config file easier.
228
+
229
+ Also, unlike JobSerialisedConfig, this type may not actually help readability.
230
+ """
231
+
232
+ hook: HookConfig
233
+
234
+
182
235
  class JobSerialisedConfig(typing.TypedDict):
183
236
  """Makes serialised configs easier to read.
184
237
 
@@ -190,6 +243,10 @@ class JobSerialisedConfig(typing.TypedDict):
190
243
  job: JobConfig
191
244
 
192
245
 
193
- ConfigNodes = typing.Union[GlobalSerialisedConfig, JobSerialisedConfig]
246
+ ConfigNodes = typing.Union[
247
+ GlobalSerialisedConfig, JobSerialisedConfig, HookSerialisedConfig
248
+ ]
194
249
  # The config format as it is serialised to/from disk
195
250
  Config = typing.List[ConfigNodes]
251
+
252
+ UserConfigMetadata = typing.List[typing.Tuple[Config, pathlib.Path]]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: runem
3
- Version: 0.0.28
3
+ Version: 0.0.30
4
4
  Summary: Awesome runem created by lursight
5
5
  Home-page: https://github.com/lursight/runem/
6
6
  Author: lursight
@@ -10,25 +10,26 @@ Requires-Dist: halo
10
10
  Requires-Dist: packaging
11
11
  Requires-Dist: PyYAML
12
12
  Provides-Extra: test
13
- Requires-Dist: black ==23.11.0 ; extra == 'test'
14
- Requires-Dist: coverage ==7.3.2 ; extra == 'test'
13
+ Requires-Dist: black ==24.3.0 ; extra == 'test'
14
+ Requires-Dist: coverage ==7.4.4 ; extra == 'test'
15
15
  Requires-Dist: docformatter ==1.7.5 ; extra == 'test'
16
16
  Requires-Dist: flake8-bugbear ==24.2.6 ; extra == 'test'
17
17
  Requires-Dist: flake8 ==7.0.0 ; extra == 'test'
18
18
  Requires-Dist: gitchangelog ==3.0.4 ; extra == 'test'
19
- Requires-Dist: isort ==5.12.0 ; extra == 'test'
19
+ Requires-Dist: isort ==5.13.2 ; extra == 'test'
20
20
  Requires-Dist: mkdocs ==1.5.3 ; extra == 'test'
21
- Requires-Dist: mypy ==1.8.0 ; extra == 'test'
21
+ Requires-Dist: mypy ==1.9.0 ; extra == 'test'
22
22
  Requires-Dist: pydocstyle ==6.3.0 ; extra == 'test'
23
- Requires-Dist: pylint ==3.0.2 ; extra == 'test'
23
+ Requires-Dist: pylint ==3.1.0 ; extra == 'test'
24
24
  Requires-Dist: pylama ==8.4.1 ; extra == 'test'
25
25
  Requires-Dist: pytest-cov ==4.1.0 ; extra == 'test'
26
26
  Requires-Dist: pytest-profiling ==1.7.0 ; extra == 'test'
27
- Requires-Dist: pytest-xdist ==3.3.1 ; extra == 'test'
28
- Requires-Dist: pytest ==7.4.3 ; extra == 'test'
27
+ Requires-Dist: pytest-xdist ==3.5.0 ; extra == 'test'
28
+ Requires-Dist: pytest ==8.1.1 ; extra == 'test'
29
+ Requires-Dist: setuptools ; extra == 'test'
29
30
  Requires-Dist: termplotlib ==0.3.9 ; extra == 'test'
30
- Requires-Dist: types-PyYAML ==6.0.12.12 ; extra == 'test'
31
- Requires-Dist: requests-mock ==1.10.0 ; extra == 'test'
31
+ Requires-Dist: types-PyYAML ==6.0.12.20240311 ; extra == 'test'
32
+ Requires-Dist: requests-mock ==1.11.0 ; extra == 'test'
32
33
  Requires-Dist: types-setuptools ; extra == 'test'
33
34
 
34
35
  # Run 'em
@@ -39,7 +40,7 @@ Requires-Dist: types-setuptools ; extra == 'test'
39
40
 
40
41
  ## 1. Overview
41
42
 
42
- The core objective of Run'em's is to minimize the wall-clock time required for executing whatever command-line tools a developer uses (or *should* use). Overall it is designed to enhance iteration speed and boost developer productivity.
43
+ The core objective of Run'em's is to minimize the wall-clock time required for running checks, supporting [shift-left](https://en.wikipedia.org/wiki/Shift-left_testing). Overall it is designed to enhance iteration speed and boost developer productivity.
43
44
 
44
45
  `runem` is also designed to be easy to learn and simple to use, but `runem` also has many powerful tools for advanced users.
45
46
 
@@ -172,7 +173,7 @@ Here's a simple setup for a python project.
172
173
  type: bool
173
174
  desc: formats docs and comments in whatever job can do so
174
175
  - option:
175
- name: check_only
176
+ name: check-only
176
177
  alias: check
177
178
  default: false
178
179
  type: bool
@@ -246,11 +247,11 @@ def _job_py_code_reformat(
246
247
  docformatter_extra_args = [
247
248
  "--in-place",
248
249
  ]
249
- if "check_only" in options and options["check_only"]:
250
+ if options["check-only"]:
250
251
  extra_args.append("--check")
251
252
  docformatter_extra_args = [] # --inplace is not compatible with --check
252
253
 
253
- if "black" in options and options["black"]:
254
+ if options["black"]:
254
255
  black_cmd = [
255
256
  "python3",
256
257
  "-m",
@@ -261,7 +262,7 @@ def _job_py_code_reformat(
261
262
  kwargs["label"] = f"{label} black"
262
263
  run_command(cmd=black_cmd, **kwargs)
263
264
 
264
- if "docformatter" in options and options["docformatter"]:
265
+ if options["docformatter"]:
265
266
  docformatter_cmd = [
266
267
  "python3",
267
268
  "-m",
@@ -278,7 +279,7 @@ def _job_py_code_reformat(
278
279
  0, # no work/change required
279
280
  3, # no errors, but code was reformatted
280
281
  )
281
- if "check_only" in options and options["check_only"]:
282
+ if options["check-only"]:
282
283
  # in check it is ONLY ok if no work/change was required
283
284
  allowed_exits = (0,)
284
285
  kwargs["label"] = f"{label} docformatter"
@@ -400,12 +401,12 @@ runem: reports:
400
401
  runem: runem: 8.820488s
401
402
  runem: ├runem.pre-build: 0.019031s
402
403
  runem: ├runem.run-phases: 8.801317s
403
- runem: ├pre-run (total): 0.00498s
404
+ runem: ├pre-run (user-time): 0.00498s
404
405
  runem: │├pre-run.install python requirements: 2.6e-05s
405
406
  runem: │├pre-run.ls -alh runem: 0.004954s
406
- runem: ├edit (total): 0.557559s
407
+ runem: ├edit (user-time): 0.557559s
407
408
  runem: │├edit.reformat py: 0.557559s
408
- runem: ├analysis (total): 21.526145s
409
+ runem: ├analysis (user-time): 21.526145s
409
410
  runem: │├analysis.pylint py: 7.457029s
410
411
  runem: │├analysis.flake8 py: 0.693754s
411
412
  runem: │├analysis.mypy py: 1.071956s
@@ -430,12 +431,12 @@ runem: reports:
430
431
  runem [14.174612] ███████████████▋
431
432
  ├runem.pre-build [ 0.025858]
432
433
  ├runem.run-phases [14.148587] ███████████████▋
433
- ├pre-run (total) [ 0.005825]
434
+ ├pre-run (user-time) [ 0.005825]
434
435
  │├pre-run.install python requirements [ 0.000028]
435
436
  │├pre-run.ls -alh runem [ 0.005797]
436
- ├edit (total) [ 0.579153] ▋
437
+ ├edit (user-time) [ 0.579153] ▋
437
438
  │├edit.reformat py [ 0.579153] ▋
438
- ├analysis (total) [36.231034] ████████████████████████████████████████
439
+ ├analysis (user-time) [36.231034] ████████████████████████████████████████
439
440
  │├analysis.pylint py [12.738303] ██████████████▏
440
441
  │├analysis.flake8 py [ 0.798575] ▉
441
442
  │├analysis.mypy py [ 0.335984] ▍
@@ -468,8 +469,8 @@ usage: runem.py [-h] [--jobs JOBS [JOBS ...]] [--not-jobs JOBS_EXCLUDED [JOBS_EX
468
469
  [--not-phases PHASES_EXCLUDED [PHASES_EXCLUDED ...]] [--tags TAGS [TAGS ...]] [--not-tags TAGS_EXCLUDED [TAGS_EXCLUDED ...]]
469
470
  [--black] [--no-black] [--check-only] [--no-check-only] [--coverage] [--no-coverage] [--docformatter] [--no-docformatter]
470
471
  [--generate-call-graphs] [--no-generate-call-graphs] [--install-deps] [--no-install-deps] [--isort] [--no-isort] [--profile]
471
- [--no-profile] [--update-snapshots] [--no-update-snapshots] [--unit-test] [--no-unit-test] [--unit-test-firebase-data]
472
- [--no-unit-test-firebase-data] [--unit-test-python] [--no-unit-test-python] [--call-graphs | --no-call-graphs]
472
+ [--no-profile] [--unit-test] [--no-unit-test]
473
+ [--call-graphs | --no-call-graphs]
473
474
  [--procs PROCS] [--root ROOT_DIR] [--verbose | --no-verbose | -v]
474
475
 
475
476
  Runs the Lursight Lang test-suite
@@ -523,18 +524,8 @@ job-param overrides:
523
524
  --no-isort turn off allow/disallows isort from running on python files
524
525
  --profile generate profile information in jobs that can
525
526
  --no-profile turn off generate profile information in jobs that can
526
- --update-snapshots update snapshots in jobs that can update data snapshots
527
- --no-update-snapshots
528
- turn off update snapshots in jobs that can update data snapshots
529
527
  --unit-test run unit tests
530
528
  --no-unit-test turn off run unit tests
531
- --unit-test-firebase-data
532
- run unit tests for the firebase function's data
533
- --no-unit-test-firebase-data
534
- turn off run unit tests for the firebase function's data
535
- --unit-test-python run unit tests for the python code
536
- --no-unit-test-python
537
- turn off run unit tests for the python code
538
529
  ```
539
530
  </details>
540
531
 
@@ -0,0 +1,33 @@
1
+ runem/VERSION,sha256=gEtWWt0L1z5lxa4WmXDkvO_ucp0v_0QZPdvkbSU-bNs,7
2
+ runem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ runem/__main__.py,sha256=dsOiVZegpfK9JOs5n7UmbX5iwwbj7iFkEbLoVeEgAn4,136
4
+ runem/base.py,sha256=EZfR7FIlwEdU9Vfe47Wk2DOO8GQqpKxxLNKp6YHueZ4,316
5
+ runem/blocking_print.py,sha256=S9dtgAeuTzc2-ht-vk9Wl6l-0PwS2tYbHDHDQQitrlA,841
6
+ runem/cli.py,sha256=wEt_Jnumhl8SiOdKdSJzLkJpWv6n3_Odhi_HeIixr1k,134
7
+ runem/command_line.py,sha256=1H1wZDfJrNCRly5yUBodYDvvKw8-4uLd3q-tcCvk1jM,11019
8
+ runem/config.py,sha256=y-e6j84FDiLSKKw9ShDzRlnS5t2e81MW8fKSKtxtJtg,5935
9
+ runem/config_metadata.py,sha256=Vy7dx8F-Z5jEp16OP2y6vHHoGkyhoCaTG4KIVkMWR7M,3232
10
+ runem/config_parse.py,sha256=6mCamzWu7HTotmqFJmLZg9FFE6qe1-rpmo8_v5ESPW8,13401
11
+ runem/files.py,sha256=CrwEiwPV0ZrrU3Ve0RWTTw9AtOQLekNXua347YYqcqQ,2748
12
+ runem/hook_manager.py,sha256=9T-4omyjBPZ6ua_37UWpT1dwNMbb4SKwvxYcN6fVxLE,4163
13
+ runem/informative_dict.py,sha256=U7p9z78UwOT4TAfng1iDXCEyeYz6C-XZlx9Z1pWNVrI,1548
14
+ runem/job.py,sha256=QVXvzz67fJk__-h0womFQsB80-w41E3XRcHpxmRnv3o,2912
15
+ runem/job_execute.py,sha256=xmH-O0qnsS2P_s3NCpXmla_kjsGgGCy0QdFH4pbY8iI,4000
16
+ runem/job_filter.py,sha256=fuxyKCHpTB4HlT_QagBk-IhhmWMlOr9Y9s5voP4yzYU,5370
17
+ runem/job_runner_simple_command.py,sha256=jxBukPm9bTLNhfQCkqNG5VepvB2ysmWAZwhBPHoTA6o,1091
18
+ runem/job_wrapper.py,sha256=wwPeWkMqhORl_Po6V-ofYZ-v9Ho0cFMprLRpY-30DyQ,964
19
+ runem/job_wrapper_python.py,sha256=m5xbWQxkDRtawjCcgxctzouv_Pny6bKiG2OPVE1hlgo,4226
20
+ runem/log.py,sha256=dIrocigvIJs1ZGkAzTogXkAK-0ZW3q5FkjpDgLdeW-E,630
21
+ runem/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ runem/report.py,sha256=IBCtMgGwnvVbEEqDWbYBGUZmTIzBLnpXqYSK5uu3vgk,8987
23
+ runem/run_command.py,sha256=Egl_j4bJ9mwi2JEFCsl0W6WH2IRgIdpMN7qdj8voClQ,6386
24
+ runem/runem.py,sha256=RIKF-l_ziGs0oKEueVkfygmnc_xiIdQo2qNDpiA-2Zs,13013
25
+ runem/runem_version.py,sha256=MbETwZO2Tb1Y3hX_OYZjKepEMKA1cjNvr-7Cqhz6e3s,271
26
+ runem/types.py,sha256=TLagRdB6-4gKqETAeJzo7-HFwBqQWGTwHcw2slSKN0U,7445
27
+ runem/utils.py,sha256=3N_kel9LsriiMq7kOjT14XhfxUOgz4hdDg97wlLKm3U,221
28
+ runem-0.0.30.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
29
+ runem-0.0.30.dist-info/METADATA,sha256=HVftDpbRdnyeVk3Xi1c3VtWIcyVJH_2CUCkJy4qoKFs,29789
30
+ runem-0.0.30.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
31
+ runem-0.0.30.dist-info/entry_points.txt,sha256=nu0g_vBeuPihYtimbtlNusxWovylMppvJ8UxdJlJfvM,46
32
+ runem-0.0.30.dist-info/top_level.txt,sha256=gK6iqh9OfHDDpErioCC9ul_zx2Q5zWTALtcuGU7Vil4,6
33
+ runem-0.0.30.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,32 +0,0 @@
1
- runem/VERSION,sha256=OxyrjQ7_oAN-lyTJKtSbtO2cnFta3aSZUdc3Av47CAg,7
2
- runem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- runem/__main__.py,sha256=dsOiVZegpfK9JOs5n7UmbX5iwwbj7iFkEbLoVeEgAn4,136
4
- runem/base.py,sha256=EZfR7FIlwEdU9Vfe47Wk2DOO8GQqpKxxLNKp6YHueZ4,316
5
- runem/blocking_print.py,sha256=S9dtgAeuTzc2-ht-vk9Wl6l-0PwS2tYbHDHDQQitrlA,841
6
- runem/cli.py,sha256=LTkxwALR67TM8GlkwrfISoYxcBZ848d9Mp75lQtDTAE,133
7
- runem/command_line.py,sha256=gRiT_fdRt4_xh_kFVoEY9GyTCcg-LmoKSs4y7HVtHqY,10379
8
- runem/config.py,sha256=dBQks5ERVTwdxw0PlOm0ioDrsxfgTCfGlBTuE2RFtn8,3866
9
- runem/config_metadata.py,sha256=FaMLZOUNKpg77yowyAKSDH9rmKbZfIwAmkDVbZMX4xU,2925
10
- runem/config_parse.py,sha256=B_hQPYSMIxzy5XUVWFuQ--0WZnCuDqgP3bQUYHwKc1A,8389
11
- runem/files.py,sha256=vAI17m-Y1tRGot6_vDpTuBTkKm8xdByGoh7HCfNkMFU,1900
12
- runem/informative_dict.py,sha256=U7p9z78UwOT4TAfng1iDXCEyeYz6C-XZlx9Z1pWNVrI,1548
13
- runem/job.py,sha256=QVXvzz67fJk__-h0womFQsB80-w41E3XRcHpxmRnv3o,2912
14
- runem/job_execute.py,sha256=KM6NpdSVQBZyB4tUZlo-2m4GiPir9q4JaFPXuWFJg9c,3685
15
- runem/job_filter.py,sha256=-qinE3cmFsk6Q9N2Hxp_vm0olIzvRgrWczmvegcd7yc,5352
16
- runem/job_runner_simple_command.py,sha256=H4LuAgzLAiy_T2juRO0qL7ULH9OpWhcXmeuAALi8JaI,836
17
- runem/job_wrapper.py,sha256=c2im3YTBmrNlULbQs9kKWlIy45B6PRuogDZcfitmX7A,752
18
- runem/job_wrapper_python.py,sha256=sjKRUTnjiAR0JKmdzoKBPM5YHIjv2q86IUUyJmV7f0s,4263
19
- runem/log.py,sha256=YddguLhhLrdbEuHxJlolNdIg_LMTEN09nqiqEWWjDzU,517
20
- runem/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- runem/report.py,sha256=GdTavjbkaOX-cwXE0KFzTIYMN58vCQRDD2esaTqB6H0,4808
22
- runem/run_command.py,sha256=wlhM6U9fseV8dsRijETuWkOoQoBkkkGH_-5jEo2KiDQ,5784
23
- runem/runem.py,sha256=DVsenr1pSSfFR-3X4RneK3SK-M5pQMk9Ws5kTc6vkcM,12099
24
- runem/runem_version.py,sha256=MbETwZO2Tb1Y3hX_OYZjKepEMKA1cjNvr-7Cqhz6e3s,271
25
- runem/types.py,sha256=WYzvITiClPWn6_x8nnKmK1q-VTsVGNAjEe3__FVLkxQ,5994
26
- runem/utils.py,sha256=3N_kel9LsriiMq7kOjT14XhfxUOgz4hdDg97wlLKm3U,221
27
- runem-0.0.28.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
28
- runem-0.0.28.dist-info/METADATA,sha256=G6TkRwsSDi4ZYlyvtVrNnWu1rOME7ejL5PPIN59LpeE,30525
29
- runem-0.0.28.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
30
- runem-0.0.28.dist-info/entry_points.txt,sha256=nu0g_vBeuPihYtimbtlNusxWovylMppvJ8UxdJlJfvM,46
31
- runem-0.0.28.dist-info/top_level.txt,sha256=gK6iqh9OfHDDpErioCC9ul_zx2Q5zWTALtcuGU7Vil4,6
32
- runem-0.0.28.dist-info/RECORD,,