opentf-toolkit-nightly 0.62.0.dev1302__py3-none-any.whl → 0.62.0.dev1311__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.
@@ -790,3 +790,89 @@ def validate_pipeline(
790
790
  return True, [list(items) for items in toposort(jobs)]
791
791
  except CircularDependencyError as err:
792
792
  return False, str(err)
793
+
794
+
795
+ def _normalize_inputs(inputs: Dict[str, Any]) -> None:
796
+ """Normalize inputs.
797
+
798
+ The 'normalized' form for inputs is with `-` separators, not `_`.
799
+
800
+ Non-normalized inputs are removed from the dictionary.
801
+
802
+ # Raised exceptions
803
+
804
+ A _ValueError_ exception is raised if an input is provided twice, in
805
+ a normalized as well as a non-normalized form.
806
+ """
807
+ for key in inputs.copy():
808
+ if '_' in key:
809
+ normalized = key.replace('_', '-')
810
+ if normalized in inputs:
811
+ raise ValueError(
812
+ f'Both "{key}" and "{normalized}" specified in inputs.'
813
+ )
814
+ inputs[normalized] = inputs.pop(key)
815
+
816
+
817
+ def _set_default(inputs: Dict[str, Any], key: str, definition: Dict[str, Any]) -> None:
818
+ if (default := definition.get('default')) is not None:
819
+ inputs[key] = default
820
+ elif type_ := definition.get('type'):
821
+ if type_ == 'string':
822
+ inputs[key] = ''
823
+ elif type_ == 'number':
824
+ inputs[key] = 0
825
+ elif type_ == 'boolean':
826
+ inputs[key] = False
827
+
828
+
829
+ def validate_inputs(
830
+ declaration: Dict[str, Dict[str, Any]],
831
+ inputs: Dict[str, Any],
832
+ additional_inputs: bool = False,
833
+ ) -> None:
834
+ """Validate inputs.
835
+
836
+ Default values are filled in `inputs` as appropriate.
837
+
838
+ Input names are normalized to use hyphens instead of underscores.
839
+
840
+ Non-normalized inputs are removed from the dictionary.
841
+
842
+ # Required parameters
843
+
844
+ - declaration: a dictionary
845
+ - inputs: a dictionary
846
+
847
+ # Optional parameters
848
+
849
+ - additional_inputs: a boolean (False by default)
850
+
851
+ # Raised exceptions
852
+
853
+ A _ValueError_ exception is raised if inputs do not match
854
+ declaration.
855
+ """
856
+ for key in declaration:
857
+ if key.startswith('{'): # Skip template entries
858
+ break
859
+ else:
860
+ _normalize_inputs(inputs)
861
+
862
+ for key, definition in declaration.items():
863
+ if key.startswith('{'):
864
+ continue
865
+ if key not in inputs:
866
+ if definition.get('required', False):
867
+ raise ValueError(f'Mandatory input "{key}" not provided.')
868
+ _set_default(inputs, key, definition)
869
+
870
+ if additional_inputs:
871
+ return
872
+
873
+ for key in inputs:
874
+ if key not in declaration and key.replace('_', '-') not in declaration:
875
+ allowed = ', '.join(sorted([f'"{k}"' for k in declaration.keys()]))
876
+ raise ValueError(
877
+ f'Unexpected input "{key}" found. Allowed inputs: {allowed}.'
878
+ )
@@ -39,9 +39,10 @@ from opentf.commons import (
39
39
  GENERATORCOMMAND,
40
40
  SERVICECONFIG,
41
41
  CHANNEL_HOOKS,
42
- validate_schema,
43
- make_status_response,
44
42
  make_dispatchqueue,
43
+ make_status_response,
44
+ validate_inputs,
45
+ validate_schema,
45
46
  )
46
47
  from opentf.toolkit import core
47
48
 
@@ -72,28 +73,6 @@ def _one_and_only_one(*args) -> bool:
72
73
  return len([arg for arg in args if arg is not None]) == 1
73
74
 
74
75
 
75
- def _normalize_inputs(inputs: Dict[str, Any]) -> None:
76
- """Normalize inputs.
77
-
78
- The 'normalized' form for inputs is with `-` separators, not `_`.
79
-
80
- Non-normalized inputs are removed from the dictionary.
81
-
82
- # Raised exceptions
83
-
84
- A _core.ExecutionError_ is raised if an input is provided twice, in
85
- a normalized as well as a non-normalized form.
86
- """
87
- for key in inputs.copy():
88
- if '_' in key:
89
- normalized = key.replace('_', '-')
90
- if normalized in inputs:
91
- raise core.ExecutionError(
92
- f"Both '{key}' and '{normalized}' specified in inputs."
93
- )
94
- inputs[normalized] = inputs.pop(key)
95
-
96
-
97
76
  def _get_pcv(
98
77
  labels: Dict[str, str], default: Optional[str] = None
99
78
  ) -> Tuple[Optional[str], Optional[str], Optional[str]]:
@@ -127,7 +106,10 @@ def _ensure_inputs_match(
127
106
  """Check inputs.
128
107
 
129
108
  Normalize inputs, fills missing optional inputs with their default
130
- values if specified.
109
+ values.
110
+
111
+ If one of the inputs is a template (name starting with '{'), no
112
+ normalization is performed.
131
113
 
132
114
  # Raised exceptions
133
115
 
@@ -139,27 +121,10 @@ def _ensure_inputs_match(
139
121
  return
140
122
 
141
123
  declaration, additional_inputs = entry
142
- for key in declaration:
143
- if key.startswith('{'):
144
- break
145
- else:
146
- _normalize_inputs(inputs)
147
- for key, definition in declaration.items():
148
- if key not in inputs:
149
- if definition.get('required'):
150
- raise core.ExecutionError(f"Mandatory input '{key}' not provided.")
151
- if (default := definition.get('default')) is not None:
152
- inputs[key] = default
153
-
154
- if additional_inputs:
155
- return
156
-
157
- for key in inputs:
158
- if key not in declaration and key.replace('_', '-') not in declaration:
159
- allowed = ', '.join(sorted([f"'{k}'" for k in declaration.keys()]))
160
- raise core.ExecutionError(
161
- f"Unexpected input '{key}' found in function step. Allowed inputs: {allowed}."
162
- )
124
+ try:
125
+ validate_inputs(declaration, inputs, additional_inputs)
126
+ except ValueError as err:
127
+ raise core.ExecutionError(str(err))
163
128
 
164
129
 
165
130
  def _get_target(
@@ -256,15 +221,15 @@ def _read_hooks_definition(
256
221
  hooks = yaml.safe_load(src)
257
222
  if not isinstance(hooks, dict) or not 'hooks' in hooks:
258
223
  plugin.logger.error(
259
- "Hooks definition file '%s' needs a 'hooks' entry, ignoring.", hooksfile
224
+ 'Hooks definition file "%s" needs a "hooks" entry, ignoring.', hooksfile
260
225
  )
261
226
  config['hooks'] = [invalid]
262
227
  return
263
228
 
264
229
  if config.get('hooks'):
265
- plugin.logger.info("Replacing hooks definition using '%s'.", hooksfile)
230
+ plugin.logger.info('Replacing hooks definition using "%s".', hooksfile)
266
231
  else:
267
- plugin.logger.info("Reading hooks definition from '%s'.", hooksfile)
232
+ plugin.logger.info('Reading hooks definition from "%s".', hooksfile)
268
233
 
269
234
  config['hooks'] = hooks['hooks']
270
235
  valid, extra = validate_schema(schema, config)
@@ -272,11 +237,11 @@ def _read_hooks_definition(
272
237
  return
273
238
 
274
239
  plugin.logger.error(
275
- "Error while verifying '%s' hooks definition: %s.", hooksfile, extra
240
+ 'Error while verifying "%s" hooks definition: %s.', hooksfile, extra
276
241
  )
277
242
  except Exception as err:
278
243
  plugin.logger.error(
279
- "Error while reading '%s' hooks definition: %s.", hooksfile, err
244
+ 'Error while reading "%s" hooks definition: %s.', hooksfile, err
280
245
  )
281
246
 
282
247
  config['hooks'] = [invalid]
@@ -351,7 +316,7 @@ def _run_handlers(plugin: Flask, file, handlers) -> None:
351
316
  handler(plugin, file, *args, **kwargs)
352
317
  except Exception as err:
353
318
  plugin.logger.error(
354
- "Handler '%s' for file '%s' failed: %s. Ignoring.", handler, file, err
319
+ 'Handler "%s" for file "%s" failed: %s. Ignoring.', handler, file, err
355
320
  )
356
321
 
357
322
 
@@ -421,7 +386,7 @@ def watch_file(plugin: Flask, path: str, handler, *args, **kwargs) -> None:
421
386
  if need_init:
422
387
  plugin.config[WATCHEDFILES_KEY] = defaultdict(list)
423
388
  plugin.config[WATCHEDFILES_EVENT_KEY] = threading.Event()
424
- plugin.logger.debug("Adding configuration watcher for '%s'.", path)
389
+ plugin.logger.debug('Adding configuration watcher for "%s".', path)
425
390
  plugin.config[WATCHEDFILES_KEY][path].append((handler, args, kwargs))
426
391
  if need_init:
427
392
  _start_watchdog(plugin)
@@ -503,14 +468,14 @@ def _subscribe(
503
468
  }
504
469
  except KeyError as err:
505
470
  plugin.logger.error(
506
- "Invalid descriptor 'outputs' section, could not find key %s in: %s.",
471
+ 'Invalid descriptor "outputs" section, could not find key %s in: %s.',
507
472
  err,
508
473
  manifest.get('outputs', {}),
509
474
  )
510
475
  sys.exit(2)
511
476
  except Exception as err:
512
477
  plugin.logger.error(
513
- "Invalid descriptor 'outputs' section, got %s while parsing outputs.", err
478
+ 'Invalid descriptor "outputs" section, got %s while parsing outputs.', err
514
479
  )
515
480
  sys.exit(2)
516
481
  return subscribe(kind=kind, target='inbox', app=plugin, labels=labels)
@@ -546,7 +511,7 @@ def run_plugin(plugin: Flask) -> None:
546
511
  )
547
512
  else:
548
513
  plugin.logger.warning(
549
- "At least one of 'category', 'categoryPrefix' required, ignoring."
514
+ 'At least one of "category", "categoryPrefix" required, ignoring.'
550
515
  )
551
516
  elif context[KIND_KEY] == EXECUTIONCOMMAND:
552
517
  context[SUBSCRIPTION_KEY].append(
@@ -663,15 +628,15 @@ def make_plugin(
663
628
 
664
629
  if not _one_and_only_one(channel, generator, provider, providers, publisher):
665
630
  raise ValueError(
666
- "One and only one of 'channel', 'generator', 'provider', 'providers', or 'publisher' is required."
631
+ 'One and only one of "channel", "generator", "provider", "providers", or "publisher" is required.'
667
632
  )
668
633
  if not (descriptor is None or isinstance(descriptor, (dict, list))):
669
634
  raise ValueError(
670
- "'descriptor', if specified, must be a dictionary or a list of dictionaries."
635
+ '"descriptor", if specified, must be a dictionary or a list of dictionaries.'
671
636
  )
672
637
  if channel and (not isinstance(args, list) or len(args) != 1):
673
638
  raise ValueError(
674
- "'args' is required for channel plugins and must be a list of one element."
639
+ '"args" is required for channel plugins and must be a list of one element.'
675
640
  )
676
641
 
677
642
  kind = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: opentf-toolkit-nightly
3
- Version: 0.62.0.dev1302
3
+ Version: 0.62.0.dev1311
4
4
  Summary: OpenTestFactory Orchestrator Toolkit
5
5
  Home-page: https://gitlab.com/henixdevelopment/open-source/opentestfactory/python-toolkit
6
6
  Author: Martin Lafaix
@@ -1,4 +1,4 @@
1
- opentf/commons/__init__.py,sha256=2hd1g14g9pnZl1uip6Sh90YSmLDWzkH1SGeZweRJ4z8,24180
1
+ opentf/commons/__init__.py,sha256=HvqRbKN7QbHrL4eSNp3q7hdf1OEo4-qvTzwVH_nx5js,26712
2
2
  opentf/commons/auth.py,sha256=gXRp_0Tf3bfd65F4QiQmh6C6vR9y3ugag_0DSvozJFk,15898
3
3
  opentf/commons/config.py,sha256=RVSSdQhMle4oCo_z_AR2EQ4U6sUjSxw-qVBtjKuJVfo,10219
4
4
  opentf/commons/exceptions.py,sha256=7dhUXO8iyAbqVwlUKxZhgRzGqVcb7LkG39hFlm-VxIA,2407
@@ -55,11 +55,11 @@ opentf/schemas/opentestfactory.org/v1beta1/Workflow.json,sha256=QZ8mM9PhzsI9gTmw
55
55
  opentf/schemas/opentestfactory.org/v1beta2/ServiceConfig.json,sha256=rEvK2YWL5lG94_qYgR_GnLWNsaQhaQ-2kuZdWJr5NnY,3517
56
56
  opentf/scripts/launch_java_service.sh,sha256=S0jAaCuv2sZy0Gf2NGBuPX-eD531rcM-b0fNyhmzSjw,2423
57
57
  opentf/scripts/startup.py,sha256=AcVXU2auPvqMb_6OpGzkVqrpgYV6vz7x_Rnv8YbAEkk,23114
58
- opentf/toolkit/__init__.py,sha256=ohrde5mcMY26p64E0Z2XunZAWYOiEkXKTg5E1J4TGGc,23571
58
+ opentf/toolkit/__init__.py,sha256=xh0XggCuR4jumiYDeMGaklktMmV8_9HAb6K5z1oJzdU,22327
59
59
  opentf/toolkit/channels.py,sha256=6qKSsAgq_oJpuDRiKqVUz-EAjdfikcCG3SFAGmKZdhQ,25551
60
60
  opentf/toolkit/core.py,sha256=fqnGgaYnuVcd4fyeNIwpc0QtyUo7jsKeVgdkBfY3iqo,9443
61
- opentf_toolkit_nightly-0.62.0.dev1302.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
62
- opentf_toolkit_nightly-0.62.0.dev1302.dist-info/METADATA,sha256=lva7suqvsswuh12Bjo-ZGIcaCepyWpzylYpxRlVUqQo,2192
63
- opentf_toolkit_nightly-0.62.0.dev1302.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
64
- opentf_toolkit_nightly-0.62.0.dev1302.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
65
- opentf_toolkit_nightly-0.62.0.dev1302.dist-info/RECORD,,
61
+ opentf_toolkit_nightly-0.62.0.dev1311.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
62
+ opentf_toolkit_nightly-0.62.0.dev1311.dist-info/METADATA,sha256=i_WxoxnBB2QmspW3dzimmGitEDI4dn008lIyif90GiE,2192
63
+ opentf_toolkit_nightly-0.62.0.dev1311.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
64
+ opentf_toolkit_nightly-0.62.0.dev1311.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
65
+ opentf_toolkit_nightly-0.62.0.dev1311.dist-info/RECORD,,