looper 2.0.0a1__py3-none-any.whl → 2.0.0a2__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.
looper/_version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "2.0.0a1"
1
+ __version__ = "2.0.0a2"
2
2
  # You must change the version in parser = pydantic_argparse.ArgumentParser in cli_pydantic.py!!!
looper/cli_divvy.py CHANGED
@@ -53,10 +53,10 @@ def build_argparser():
53
53
 
54
54
  for sp in [sps["list"], sps["write"], sps["submit"], sps["inspect"]]:
55
55
  sp.add_argument(
56
- "config", nargs="?", default=None, help="Divvy configuration file."
56
+ "--config", nargs="?", default=None, help="Divvy configuration file."
57
57
  )
58
58
 
59
- sps["init"].add_argument("config", default=None, help="Divvy configuration file.")
59
+ sps["init"].add_argument("--config", default=None, help="Divvy configuration file.")
60
60
 
61
61
  for sp in [sps["inspect"]]:
62
62
  sp.add_argument(
@@ -124,9 +124,11 @@ def main():
124
124
  sys.exit(0)
125
125
 
126
126
  _LOGGER.debug("Divvy config: {}".format(args.config))
127
+
127
128
  divcfg = select_divvy_config(args.config)
129
+
128
130
  _LOGGER.info("Using divvy config: {}".format(divcfg))
129
- dcc = ComputingConfiguration(filepath=divcfg)
131
+ dcc = ComputingConfiguration.from_yaml_file(filepath=divcfg)
130
132
 
131
133
  if args.command == "list":
132
134
  # Output header via logger and content via print so the user can
@@ -142,11 +144,13 @@ def main():
142
144
  for pkg_name, pkg in dcc.compute_packages.items():
143
145
  if pkg_name == args.package:
144
146
  found = True
145
- with open(pkg.submission_template, "r") as f:
147
+ with open(pkg["submission_template"], "r") as f:
146
148
  print(f.read())
147
- _LOGGER.info("Submission command is: " + pkg.submission_command + "\n")
149
+ _LOGGER.info(
150
+ "Submission command is: " + pkg["submission_command"] + "\n"
151
+ )
148
152
  if pkg_name == "docker":
149
- print("Docker args are: " + pkg.docker_args)
153
+ print("Docker args are: " + pkg["docker_args"])
150
154
 
151
155
  if not found:
152
156
  _LOGGER.info("Package not found. Use 'divvy list' to see list of packages.")
looper/cli_pydantic.py CHANGED
@@ -26,8 +26,6 @@ from eido import inspect_project
26
26
  from pephubclient import PEPHubClient
27
27
  from pydantic_argparse.argparse.parser import ArgumentParser
28
28
 
29
- from divvy import select_divvy_config
30
-
31
29
  from . import __version__
32
30
 
33
31
  from .command_models.arguments import ArgumentEnum
@@ -128,15 +126,8 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
128
126
  console = Console()
129
127
  console.clear()
130
128
  console.rule(f"\n[magenta]Looper initialization[/magenta]")
131
- console.print(
132
- "[bold]Would you like to follow a guided tutorial?[/bold] [green]Y[/green] / [red]n[/red]..."
133
- )
134
-
135
- selection = None
136
- while selection not in ["y", "n"]:
137
- selection = console.input("\nSelection: ").lower().strip()
138
-
139
- if selection == "n":
129
+ selection = subcommand_args.generic
130
+ if selection is True:
140
131
  console.clear()
141
132
  return int(
142
133
  not initiate_looper_config(
@@ -172,11 +163,14 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
172
163
  else:
173
164
  setattr(subcommand_args, looper_config_key, looper_config_item)
174
165
 
175
- except OSError:
176
- parser.print_help(sys.stderr)
177
- _LOGGER.warning(
178
- f"Looper config file does not exist. Use looper init to create one at {looper_cfg_path}."
179
- )
166
+ except OSError as e:
167
+ if subcommand_args.config:
168
+ _LOGGER.warning(
169
+ f"\nLooper config file does not exist at given path {subcommand_args.config}. Use looper init to create one at {looper_cfg_path}."
170
+ )
171
+ else:
172
+ _LOGGER.warning(e)
173
+
180
174
  sys.exit(1)
181
175
 
182
176
  subcommand_args = enrich_args_via_cfg(
@@ -225,7 +219,7 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
225
219
  amendments=subcommand_args.amend,
226
220
  divcfg_path=divcfg,
227
221
  runp=subcommand_name == "runp",
228
- project_dict=PEPHubClient()._load_raw_pep(
222
+ project_dict=PEPHubClient().load_raw_pep(
229
223
  registry_path=subcommand_args.pep_config
230
224
  ),
231
225
  **{
@@ -340,13 +334,13 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
340
334
  _LOGGER.warning("No looper configuration was supplied.")
341
335
 
342
336
 
343
- def main(test_args=None) -> None:
337
+ def main(test_args=None) -> dict:
344
338
  parser = pydantic_argparse.ArgumentParser(
345
339
  model=TopLevelParser,
346
340
  prog="looper",
347
341
  description="Looper: A job submitter for Portable Encapsulated Projects",
348
342
  add_help=True,
349
- version="2.0.0a1",
343
+ version="2.0.0a2",
350
344
  )
351
345
 
352
346
  parser = add_short_arguments(parser, ArgumentEnum)
@@ -359,6 +353,10 @@ def main(test_args=None) -> None:
359
353
  return run_looper(args, parser, test_args=test_args)
360
354
 
361
355
 
356
+ def main_cli() -> None:
357
+ main()
358
+
359
+
362
360
  def _proc_resources_spec(args):
363
361
  """
364
362
  Process CLI-sources compute setting specification. There are two sources
@@ -385,20 +383,29 @@ def _proc_resources_spec(args):
385
383
  settings_data = {}
386
384
  if not spec:
387
385
  return settings_data
388
- pairs = [(kv, kv.split("=")) for kv in spec]
389
- bads = []
390
- for orig, pair in pairs:
391
- try:
392
- k, v = pair
393
- except ValueError:
394
- bads.append(orig)
395
- else:
396
- settings_data[k] = v
397
- if bads:
398
- raise ValueError(
399
- "Could not correctly parse itemized compute specification. "
400
- "Correct format: " + EXAMPLE_COMPUTE_SPEC_FMT
401
- )
386
+ if isinstance(
387
+ spec, str
388
+ ): # compute: "partition=standard time='01-00:00:00' cores='32' mem='32000'"
389
+ spec = spec.split(sep=" ")
390
+ if isinstance(spec, list):
391
+ pairs = [(kv, kv.split("=")) for kv in spec]
392
+ bads = []
393
+ for orig, pair in pairs:
394
+ try:
395
+ k, v = pair
396
+ except ValueError:
397
+ bads.append(orig)
398
+ else:
399
+ settings_data[k] = v
400
+ if bads:
401
+ raise ValueError(
402
+ "Could not correctly parse itemized compute specification. "
403
+ "Correct format: " + EXAMPLE_COMPUTE_SPEC_FMT
404
+ )
405
+ elif isinstance(spec, dict):
406
+ for key, value in spec.items():
407
+ settings_data[key] = value
408
+
402
409
  return settings_data
403
410
 
404
411
 
@@ -184,6 +184,14 @@ class ArgumentEnum(enum.Enum):
184
184
  default=(str, None),
185
185
  description="Output directory",
186
186
  )
187
+
188
+ GENERIC = Argument(
189
+ name="generic",
190
+ alias="-g",
191
+ default=(bool, False),
192
+ description="Use generic looper config?",
193
+ )
194
+
187
195
  SAMPLE_PIPELINE_INTERFACES = Argument(
188
196
  name="sample_pipeline_interfaces",
189
197
  alias="-S",
@@ -228,6 +236,7 @@ class ArgumentEnum(enum.Enum):
228
236
  )
229
237
  PACKAGE = Argument(
230
238
  name="package",
239
+ alias="-p",
231
240
  default=(str, None),
232
241
  description="Name of computing resource package to use",
233
242
  )
@@ -187,6 +187,7 @@ InitParser = Command(
187
187
  ArgumentEnum.PEP_CONFIG.value,
188
188
  ArgumentEnum.SAMPLE_PIPELINE_INTERFACES.value,
189
189
  ArgumentEnum.PROJECT_PIPELINE_INTERFACES.value,
190
+ ArgumentEnum.GENERIC.value,
190
191
  ],
191
192
  )
192
193
 
looper/conductor.py CHANGED
@@ -661,6 +661,7 @@ class SubmissionConductor(object):
661
661
  "record_identifier": psm.record_identifier,
662
662
  "config_file": psm.config_path,
663
663
  "output_schema": psm.cfg["_schema_path"],
664
+ "pephub_path": psm.cfg["pephub_path"],
664
665
  }
665
666
  filtered_namespace = {k: v for k, v in full_namespace.items() if v}
666
667
  return YAMLConfigManager(filtered_namespace)
looper/divvy.py CHANGED
@@ -200,6 +200,11 @@ class ComputingConfiguration(YAMLConfigManager):
200
200
  """
201
201
  return self.compute
202
202
 
203
+ @property
204
+ def compute_packages(self):
205
+
206
+ return self["compute_packages"]
207
+
203
208
  def list_compute_packages(self):
204
209
  """
205
210
  Returns a list of available compute packages.
@@ -396,11 +401,13 @@ def divvy_init(config_path, template_config_path):
396
401
  _LOGGER.error("You must specify a template config file path.")
397
402
  return
398
403
 
404
+ if not os.path.isabs(config_path):
405
+ config_path = os.path.abspath(config_path)
406
+
399
407
  if config_path and not os.path.exists(config_path):
400
- # dcc.write(config_path)
401
408
  # Init should *also* write the templates.
402
409
  dest_folder = os.path.dirname(config_path)
403
- copytree(os.path.dirname(template_config_path), dest_folder)
410
+ copytree(os.path.dirname(template_config_path), dest_folder, dirs_exist_ok=True)
404
411
  template_subfolder = os.path.join(dest_folder, "divvy_templates")
405
412
  _LOGGER.info("Wrote divvy templates to folder: {}".format(template_subfolder))
406
413
  new_template = os.path.join(
looper/exceptions.py CHANGED
@@ -31,7 +31,7 @@ class SampleFailedException(LooperError):
31
31
 
32
32
 
33
33
  class MisconfigurationException(LooperError):
34
- """Duplication of pipeline identifier precludes unique pipeline ref."""
34
+ """Looper not properly configured"""
35
35
 
36
36
  def __init__(self, key):
37
37
  super(MisconfigurationException, self).__init__(key)
looper/utils.py CHANGED
@@ -17,6 +17,7 @@ from ubiquerg import convert_value, expandpath, parse_registry_path, deep_update
17
17
  from pephubclient.constants import RegistryPath
18
18
  from pydantic import ValidationError
19
19
  from yacman import load_yaml
20
+ from yaml.parser import ParserError
20
21
 
21
22
  from .const import *
22
23
  from .command_models.commands import SUPPORTED_COMMANDS
@@ -263,31 +264,29 @@ def enrich_args_via_cfg(
263
264
  cli_modifiers=None,
264
265
  ):
265
266
  """
266
- Read in a looper dotfile and set arguments.
267
+ Read in a looper dotfile, pep config and set arguments.
267
268
 
268
- Priority order: CLI > dotfile/config > parser default
269
+ Priority order: CLI > dotfile/config > pep_config > parser default
269
270
 
270
271
  :param subcommand name: the name of the command used
271
272
  :param argparse.Namespace parser_args: parsed args by the original parser
272
- :param argparse.Namespace aux_parser: parsed args by the a parser
273
+ :param argparse.Namespace aux_parser: parsed args by the argument parser
273
274
  with defaults suppressed
275
+ :param dict test_args: dict of args used for pytesting
276
+ :param dict cli_modifiers: dict of args existing if user supplied cli args in looper config file
274
277
  :return argparse.Namespace: selected argument values
275
278
  """
279
+
280
+ # Did the user provide arguments in the PEP config?
276
281
  cfg_args_all = (
277
282
  _get_subcommand_args(subcommand_name, parser_args)
278
283
  if os.path.exists(parser_args.pep_config)
279
284
  else dict()
280
285
  )
281
-
282
- # If user provided project-level modifiers in the looper config, they are prioritized
283
- if cfg_args_all:
284
- for key, value in cfg_args_all.items():
285
- if getattr(parser_args, key, None):
286
- new_value = getattr(parser_args, key)
287
- cfg_args_all[key] = new_value
288
- else:
286
+ if not cfg_args_all:
289
287
  cfg_args_all = {}
290
288
 
289
+ # Did the user provide arguments/modifiers in the looper config file?
291
290
  looper_config_cli_modifiers = None
292
291
  if cli_modifiers:
293
292
  if str(subcommand_name) in cli_modifiers:
@@ -312,6 +311,13 @@ def enrich_args_via_cfg(
312
311
  else:
313
312
  cli_args, _ = aux_parser.parse_known_args()
314
313
 
314
+ # If any CLI args were provided, make sure they take priority
315
+ if cli_args:
316
+ r = getattr(cli_args, subcommand_name)
317
+ for k, v in cfg_args_all.items():
318
+ if k in r:
319
+ cfg_args_all[k] = getattr(r, k)
320
+
315
321
  def set_single_arg(argname, default_source_namespace, result_namespace):
316
322
  if argname not in POSITIONAL or not hasattr(result, argname):
317
323
  if argname in cli_args:
@@ -324,6 +330,8 @@ def enrich_args_via_cfg(
324
330
  elif cfg_args_all is not None and argname in cfg_args_all:
325
331
  if isinstance(cfg_args_all[argname], list):
326
332
  r = [convert_value(i) for i in cfg_args_all[argname]]
333
+ elif isinstance(cfg_args_all[argname], dict):
334
+ r = cfg_args_all[argname]
327
335
  else:
328
336
  r = convert_value(cfg_args_all[argname])
329
337
  else:
@@ -432,9 +440,8 @@ def init_generic_pipeline(pipelinepath: Optional[str] = None):
432
440
  generic_pipeline_dict = {
433
441
  "pipeline_name": "default_pipeline_name",
434
442
  "output_schema": "output_schema.yaml",
435
- "var_templates": {"pipeline": "{looper.piface_dir}/count_lines.sh"},
436
443
  "sample_interface": {
437
- "command_template": "{pipeline.var_templates.pipeline} {sample.file} "
444
+ "command_template": "{looper.piface_dir}/count_lines.sh {sample.file} "
438
445
  "--output-parent {looper.sample_output_folder}"
439
446
  },
440
447
  }
@@ -627,8 +634,6 @@ def looper_config_tutorial():
627
634
  console.print("Use [yellow]`looper run`[/yellow] afterwards to run the pipeline.")
628
635
  console.print("Press [yellow]^C[/yellow] at any time to quit.\n")
629
636
 
630
- console.input("> ... ")
631
-
632
637
  DEFAULTS = { # What you get if you just press enter
633
638
  "pep_config": "databio/example",
634
639
  "output_dir": "results",
@@ -636,73 +641,58 @@ def looper_config_tutorial():
636
641
  "project_name": os.path.basename(os.getcwd()),
637
642
  }
638
643
 
639
- creating = True
644
+ cfg["project_name"] = (
645
+ console.input(f"Project name: [yellow]({DEFAULTS['project_name']})[/yellow] >")
646
+ or DEFAULTS["project_name"]
647
+ )
640
648
 
641
- while creating:
642
- cfg["project_name"] = (
643
- console.input(
644
- f"Project name: [yellow]({DEFAULTS['project_name']})[/yellow] >"
645
- )
646
- or DEFAULTS["project_name"]
649
+ cfg["pep_config"] = (
650
+ console.input(
651
+ f"Registry path or file path to PEP: [yellow]({DEFAULTS['pep_config']})[/yellow] >"
647
652
  )
653
+ or DEFAULTS["pep_config"]
654
+ )
648
655
 
649
- cfg["pep_config"] = (
650
- console.input(
651
- f"Registry path or file path to PEP: [yellow]({DEFAULTS['pep_config']})[/yellow] >"
652
- )
653
- or DEFAULTS["pep_config"]
656
+ if not os.path.exists(cfg["pep_config"]) and not is_pephub_registry_path(
657
+ cfg["pep_config"]
658
+ ):
659
+ console.print(
660
+ f"Warning: PEP file does not exist at [yellow]'{cfg['pep_config']}[/yellow]'"
654
661
  )
655
662
 
656
- if not os.path.exists(cfg["pep_config"]):
657
- console.print(
658
- f"Warning: PEP file does not exist at [yellow]'{cfg['pep_config']}[/yellow]'"
659
- )
663
+ cfg["output_dir"] = (
664
+ console.input(
665
+ f"Path to output directory: [yellow]({DEFAULTS['output_dir']})[/yellow] >"
666
+ )
667
+ or DEFAULTS["output_dir"]
668
+ )
660
669
 
661
- cfg["output_dir"] = (
670
+ add_more_pifaces = True
671
+ piface_paths = []
672
+ while add_more_pifaces:
673
+ piface_path = (
662
674
  console.input(
663
- f"Path to output directory: [yellow]({DEFAULTS['output_dir']})[/yellow] >"
675
+ "Add each path to a pipeline interface: [yellow](pipeline_interface.yaml)[/yellow] >"
664
676
  )
665
- or DEFAULTS["output_dir"]
677
+ or None
666
678
  )
679
+ if piface_path is None:
680
+ if piface_paths == []:
681
+ piface_paths.append(DEFAULTS["piface_path"])
682
+ add_more_pifaces = False
683
+ else:
684
+ piface_paths.append(piface_path)
667
685
 
668
- add_more_pifaces = True
669
- piface_paths = []
670
- while add_more_pifaces:
671
- piface_path = (
672
- console.input(
673
- "Add each path to a pipeline interface: [yellow](pipeline_interface.yaml)[/yellow] >"
674
- )
675
- or None
676
- )
677
- if piface_path is None:
678
- if piface_paths == []:
679
- piface_paths.append(DEFAULTS["piface_path"])
680
- add_more_pifaces = False
681
- else:
682
- piface_paths.append(piface_path)
683
-
684
- console.print("\n")
685
-
686
- console.print(
687
- f"""\
688
- [yellow]pep_config:[/yellow] {cfg['pep_config']}
689
- [yellow]output_dir:[/yellow] {cfg['output_dir']}
690
- [yellow]pipeline_interfaces:[/yellow]
691
- - {piface_paths}
692
- """
693
- )
686
+ console.print("\n")
694
687
 
695
- console.print(
696
- "[bold]Does this look good?[/bold] [bold green]Y[/bold green]/[red]n[/red]..."
697
- )
698
- selection = None
699
- while selection not in ["y", "n"]:
700
- selection = console.input("\nSelection: ").lower().strip()
701
- if selection == "n":
702
- console.print("Starting over...")
703
- pass
704
- if selection == "y":
705
- creating = False
688
+ console.print(
689
+ f"""\
690
+ [yellow]pep_config:[/yellow] {cfg['pep_config']}
691
+ [yellow]output_dir:[/yellow] {cfg['output_dir']}
692
+ [yellow]pipeline_interfaces:[/yellow]
693
+ - {piface_paths}
694
+ """
695
+ )
706
696
 
707
697
  for piface_path in piface_paths:
708
698
  if not os.path.exists(piface_path):
@@ -727,7 +717,7 @@ def looper_config_tutorial():
727
717
  looper_config_dict = {}
728
718
  looper_config_dict["pep_config"] = cfg["pep_config"]
729
719
  looper_config_dict["output_dir"] = cfg["output_dir"]
730
- looper_config_dict["pipeline_interfaces"] = [piface_paths]
720
+ looper_config_dict["pipeline_interfaces"] = piface_paths
731
721
 
732
722
  with open(looper_cfg_path, "w") as fp:
733
723
  yaml.dump(looper_config_dict, fp)
@@ -747,7 +737,15 @@ def determine_pipeline_type(piface_path: str, looper_config_path: str):
747
737
 
748
738
  if piface_path is None:
749
739
  return None, None
750
- piface_path = expandpath(piface_path)
740
+ try:
741
+ piface_path = expandpath(piface_path)
742
+ except TypeError as e:
743
+ _LOGGER.warning(
744
+ f"Pipeline interface not found at given path: {piface_path}. Type Error: "
745
+ + str(e)
746
+ )
747
+ return None, None
748
+
751
749
  if not os.path.isabs(piface_path):
752
750
  piface_path = os.path.realpath(
753
751
  os.path.join(os.path.dirname(looper_config_path), piface_path)
@@ -755,6 +753,7 @@ def determine_pipeline_type(piface_path: str, looper_config_path: str):
755
753
  try:
756
754
  piface_dict = load_yaml(piface_path)
757
755
  except FileNotFoundError:
756
+ _LOGGER.warning(f"Pipeline interface not found at given path: {piface_path}")
758
757
  return None, None
759
758
 
760
759
  pipeline_types = []
@@ -783,12 +782,18 @@ def read_looper_config_file(looper_config_path: str) -> dict:
783
782
  :raise MisconfigurationException: incorrect configuration.
784
783
  """
785
784
  return_dict = {}
786
- with open(looper_config_path, "r") as dotfile:
787
- dp_data = yaml.safe_load(dotfile)
785
+
786
+ try:
787
+ with open(looper_config_path, "r") as dotfile:
788
+ dp_data = yaml.safe_load(dotfile)
789
+ except ParserError as e:
790
+ _LOGGER.warning(
791
+ "Could not load looper config file due to the following exception"
792
+ )
793
+ raise ParserError(context=str(e))
788
794
 
789
795
  if PEP_CONFIG_KEY in dp_data:
790
796
  return_dict[PEP_CONFIG_KEY] = dp_data[PEP_CONFIG_KEY]
791
-
792
797
  else:
793
798
  raise MisconfigurationException(
794
799
  f"Looper dotfile ({looper_config_path}) is missing '{PEP_CONFIG_KEY}' key"
@@ -846,6 +851,7 @@ def read_looper_config_file(looper_config_path: str) -> dict:
846
851
  for k, v in return_dict.items():
847
852
  if k == SAMPLE_PL_ARG or k == PROJECT_PL_ARG:
848
853
  # Pipeline interfaces are resolved at a later point. Do it there only to maintain consistency. #474
854
+
849
855
  pass
850
856
  if isinstance(v, str):
851
857
  v = expandpath(v)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: looper
3
- Version: 2.0.0a1
3
+ Version: 2.0.0a2
4
4
  Summary: A pipeline submission engine that parses sample inputs and submits pipelines for each sample.
5
5
  Home-page: https://github.com/pepkit/looper
6
6
  Author: Nathan Sheffield, Vince Reuter, Michal Stolarczyk, Johanna Klughammer, Andre Rendeiro
@@ -15,20 +15,19 @@ Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE.txt
18
- Requires-Dist: colorama >=0.3.9
19
- Requires-Dist: divvy >=0.5.0
20
- Requires-Dist: eido >=0.2.1
18
+ Requires-Dist: colorama>=0.3.9
19
+ Requires-Dist: eido>=0.2.3
21
20
  Requires-Dist: jinja2
22
- Requires-Dist: logmuse >=0.2.0
23
- Requires-Dist: pandas >=2.0.2
24
- Requires-Dist: pephubclient >=0.4.0
25
- Requires-Dist: pipestat >=0.9.2
26
- Requires-Dist: peppy >=0.40.2
27
- Requires-Dist: pyyaml >=3.12
28
- Requires-Dist: rich >=9.10.0
29
- Requires-Dist: ubiquerg >=0.8.1a1
30
- Requires-Dist: yacman ==0.9.3
31
- Requires-Dist: pydantic-argparse >=0.9.0
21
+ Requires-Dist: logmuse>=0.2.0
22
+ Requires-Dist: pandas>=2.0.2
23
+ Requires-Dist: pephubclient>=0.4.0
24
+ Requires-Dist: pipestat>=0.10.2
25
+ Requires-Dist: peppy>=0.40.6
26
+ Requires-Dist: pyyaml>=3.12
27
+ Requires-Dist: rich>=9.10.0
28
+ Requires-Dist: ubiquerg>=0.8.1a1
29
+ Requires-Dist: yacman==0.9.3
30
+ Requires-Dist: pydantic-argparse>=0.9.0
32
31
  Requires-Dist: psutil
33
32
 
34
33
  # <img src="docs/img/looper_logo.svg" alt="looper logo" height="70">
@@ -1,24 +1,24 @@
1
1
  looper/__init__.py,sha256=f_z9YY4ibOk7eyWoaViH_VaCXMlPQeiftbnibSFj-3E,1333
2
2
  looper/__main__.py,sha256=OOCmI-dPUvInnJHkHNMf54cblNJ3Yl9ELOwZcfOXmD8,240
3
- looper/_version.py,sha256=wJ2KiFRb6QXaKu1tfxwKmo9CE2xP4f3BkEUYoIJeUkQ,121
4
- looper/cli_divvy.py,sha256=J07x83sqC4jJeu3_yS6KOARPWmwKGAV7JvN33T5zDac,5907
5
- looper/cli_pydantic.py,sha256=saAD0dwizLi_VajVKElQmYRqtn0Yyl_r712znxZMxRQ,14209
6
- looper/conductor.py,sha256=oNfqANA2tIhQTAQFxd-rQ4ccPA60D933EGo3rfbJGFo,35061
3
+ looper/_version.py,sha256=mX3fglKqsJRTjP938X3Xm2eAJT9fve28fdydFnJFimc,121
4
+ looper/cli_divvy.py,sha256=_VGbOFLkXtKdkZA6omlzgXbXkuUM5aLQ50aTTtbTrVI,5975
5
+ looper/cli_pydantic.py,sha256=uysPJfTrfG7-k7u6oDpaLG-3hD6U8YVrDiOW54ySniI,14425
6
+ looper/conductor.py,sha256=lzY6Gzsb8oX-KLzLkRa0XrYWSxLeiy6jRmmD15WNAkw,35116
7
7
  looper/const.py,sha256=OscEELQsyLKlSrmwuXfyLRwpAUJUEpGD2UxBeLJDXgw,8703
8
- looper/divvy.py,sha256=5x8hV1lT5tEQdAUtVjn0rNwYnJroNij0RyDn-wHf4QE,15251
9
- looper/exceptions.py,sha256=r6SKKt-m8CXQnXGDnuiwoA6zBJhIZflygBKjX4RCloI,3419
8
+ looper/divvy.py,sha256=eiYhcp8ZgQ0uzlk0c5yJp0QaiVrQYfSeEtmQBJiScOM,15417
9
+ looper/exceptions.py,sha256=AxYCTLxKb_fJFgU9VBnPYaRX2lGhmMEYaCbJOi-27Wk,3384
10
10
  looper/looper.py,sha256=ZWTulMz6NobnYFUjev513TJwXqknrb4_gZrV-a_fT9g,30041
11
11
  looper/parser_types.py,sha256=d3FHt54f9jo9VZMr5SQkbghcAdABqiYZW2JBGO5EBnw,2327
12
12
  looper/pipeline_interface.py,sha256=mN4-XICyZzuVLTOq3b0ijppYe6ib_Ljlyf6KxZCJh2A,14537
13
13
  looper/plugins.py,sha256=MaMdPmK9U_4FkNJE5kccohBbY1i2qj1NTEucubFOJek,5747
14
14
  looper/processed_project.py,sha256=jZxoMYafvr-OHFxylc5ivGty1VwXBZhl0kgoFkY-174,9837
15
15
  looper/project.py,sha256=SFHdi58eRBWtye5lUFhwzBcG7ejrMurmDzmkrC3XAic,34339
16
- looper/utils.py,sha256=VXKaEYXW0XEQNy__hNBv42i-sz5qB7QiwpXzhXs_3Wk,39556
16
+ looper/utils.py,sha256=-4QlScIB7eewIbmEJdAv2d0ZE0qr_q9acm2XUOiMEek,39769
17
17
  looper/command_models/DEVELOPER.md,sha256=eRxnrO-vqNJjExzamXKEq5wr_-Zw6PQEwkS9RPinYrk,2775
18
18
  looper/command_models/README.md,sha256=3RGegeZlTZYnhcHXRu6bdI_81WZom2q7QYMV-KGYY7U,588
19
19
  looper/command_models/__init__.py,sha256=6QWC2TewowEL7dATli5YpMmFWuXaLEPktofJCXkYUBI,187
20
- looper/command_models/arguments.py,sha256=sRrJWCSQmnjGLnOo-Wl6_PnvTZz8VIWII79svI3BqFk,8653
21
- looper/command_models/commands.py,sha256=EvKyjNdUBspXnOUMprxIY0C4VPka2PBj8CJgtd5Ya9w,9680
20
+ looper/command_models/arguments.py,sha256=wGGc5tleHC31F0etbiYaumHwP5xlJsSXapJ10lhltHg,8830
21
+ looper/command_models/commands.py,sha256=RMTiHg0txBGDb_fHfhTWujP3VnnB6ROCHqByiwgMS4c,9716
22
22
  looper/default_config/divvy_config.yaml,sha256=wK5kLDGBV2wwoyqg2rl3X8SXjds4x0mwBUjUzF1Ln7g,1705
23
23
  looper/default_config/divvy_templates/localhost_bulker_template.sub,sha256=yn5VB9Brt7Hck9LT17hD2o8Kn-76gYJQk_A-8C1Gr4k,164
24
24
  looper/default_config/divvy_templates/localhost_docker_template.sub,sha256=XRr7AlR7-TP1L3hyBMfka_RgWRL9vzOlS5Kd1xSNwT0,183
@@ -60,9 +60,9 @@ looper/schemas/divvy_config_schema.yaml,sha256=7GJfKLc3VX4RGjHnOE1zxwsHXhj_ur9za
60
60
  looper/schemas/pipeline_interface_schema_generic.yaml,sha256=3YfKFyRUIwxG41FEidR1dXe9IU6ye51LSUBfSpmMuss,1773
61
61
  looper/schemas/pipeline_interface_schema_project.yaml,sha256=-ZWyA0lKXWik3obuLNVk3IsAZYfbLVbCDvJnD-Fcluo,1567
62
62
  looper/schemas/pipeline_interface_schema_sample.yaml,sha256=x0OwVnijJpvm50DscvvJujdK4UAI7d71pqVemQS-D-0,1564
63
- looper-2.0.0a1.dist-info/LICENSE.txt,sha256=oB6ZGDa4kcznznJKJsLLFFcOZyi8Y6e2Jv0rJozgp-I,1269
64
- looper-2.0.0a1.dist-info/METADATA,sha256=OZPEqy9PPCjzJ110u-HazaRkaUIiuesCZMC3jpfl2vQ,1800
65
- looper-2.0.0a1.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
66
- looper-2.0.0a1.dist-info/entry_points.txt,sha256=ejZpghZG3OoTK69u9rTW-yLyI6SC63bBTUb-Vw26HG4,87
67
- looper-2.0.0a1.dist-info/top_level.txt,sha256=I0Yf7djsoQAMzwHBbDiQi9hGtq4Z41_Ma5CX8qXG8Y8,7
68
- looper-2.0.0a1.dist-info/RECORD,,
63
+ looper-2.0.0a2.dist-info/LICENSE.txt,sha256=oB6ZGDa4kcznznJKJsLLFFcOZyi8Y6e2Jv0rJozgp-I,1269
64
+ looper-2.0.0a2.dist-info/METADATA,sha256=s4IlCgd597EhgR8H0LIB-3Qz02absf63sudpuFG1rKM,1760
65
+ looper-2.0.0a2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
66
+ looper-2.0.0a2.dist-info/entry_points.txt,sha256=iHltI2_Jdved27vccmWhvmcHWUZ7Mf6CfDV6QkY1Lc8,91
67
+ looper-2.0.0a2.dist-info/top_level.txt,sha256=I0Yf7djsoQAMzwHBbDiQi9hGtq4Z41_Ma5CX8qXG8Y8,7
68
+ looper-2.0.0a2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,3 @@
1
1
  [console_scripts]
2
2
  divvy = looper.__main__:divvy_main
3
- looper = looper.cli_pydantic:main
3
+ looper = looper.cli_pydantic:main_cli