opentf-toolkit-nightly 0.50.0.dev696__py3-none-any.whl → 0.50.0.dev705__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.
@@ -34,8 +34,9 @@ from .config import (
34
34
  ConfigError,
35
35
  make_argparser,
36
36
  configure_logging,
37
- read_configfile,
38
- read_manifest,
37
+ read_config,
38
+ read_descriptor,
39
+ get_named,
39
40
  )
40
41
  from .auth import (
41
42
  initialize_authn_authz,
@@ -49,7 +50,6 @@ from .schemas import *
49
50
  ########################################################################
50
51
  # Constants
51
52
 
52
-
53
53
  DEFAULT_NAMESPACE = 'default'
54
54
 
55
55
  # Misc. constants
@@ -63,13 +63,6 @@ DEFAULT_HEADERS = {
63
63
  'Content-Security-Policy': 'default-src \'none\'',
64
64
  }
65
65
 
66
- DEFAULT_CONTEXT = {
67
- 'host': '127.0.0.1',
68
- 'port': 443,
69
- 'ssl_context': 'adhoc',
70
- 'eventbus': {'endpoint': 'https://127.0.0.1:38368', 'token': 'invalid-token'},
71
- }
72
-
73
66
  REASON_STATUS = {
74
67
  'OK': 200,
75
68
  'Created': 201,
@@ -105,6 +98,8 @@ ACCESSLOG_FORMAT = (
105
98
 
106
99
  DEBUG_LEVELS = {'CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'}
107
100
 
101
+ PARAMETERS_KEY = '__PARAMETERS__'
102
+
108
103
  ########################################################################
109
104
  # Config Helpers
110
105
 
@@ -204,6 +199,39 @@ def _get_debug_level(name: str) -> str:
204
199
  return level if level in DEBUG_LEVELS else 'INFO'
205
200
 
206
201
 
202
+ def _get_contextparameter_spec(app: Flask, name: str) -> Optional[Dict[str, Any]]:
203
+ """Get context parameter specification.
204
+
205
+ Initialize cache if needed, ignoring context parameters specs from
206
+ other services.
207
+
208
+ Adds the `watchdog_polling_delay_seconds` spec.
209
+ """
210
+ if PARAMETERS_KEY not in app.config:
211
+ app.config[PARAMETERS_KEY] = []
212
+ for manifest in app.config['DESCRIPTOR']:
213
+ if manifest.get('metadata', {}).get('name', '').lower() != app.name.lower():
214
+ continue
215
+ app.config[PARAMETERS_KEY] += manifest.get('spec', {}).get(
216
+ 'contextParameters', []
217
+ )
218
+ app.config[PARAMETERS_KEY] += [
219
+ {
220
+ 'name': 'watchdog_polling_delay_seconds',
221
+ 'descriptiveName': 'polling delay in seconds',
222
+ 'default': 30,
223
+ 'type': 'int',
224
+ }
225
+ ]
226
+ app.logger.info('Configuration:')
227
+ parameters = app.config[PARAMETERS_KEY]
228
+ try:
229
+ spec = get_named(name, parameters)
230
+ except ValueError:
231
+ spec = None
232
+ return spec
233
+
234
+
207
235
  ########################################################################
208
236
 
209
237
 
@@ -379,7 +407,7 @@ def make_app(
379
407
  configfile: str,
380
408
  schema: Optional[str] = None,
381
409
  defaultcontext: Optional[Dict[str, Any]] = None,
382
- manifest: Optional[Union[str, Dict[str, Any], List[Dict[str, Any]]]] = None,
410
+ descriptor: Optional[Union[str, Dict[str, Any], List[Dict[str, Any]]]] = None,
383
411
  ) -> Flask:
384
412
  """Create a new app.
385
413
 
@@ -393,7 +421,7 @@ def make_app(
393
421
 
394
422
  - schema: a string or None (None by default)
395
423
  - defaultcontext: a dictionary or None (None by default)
396
- - manifest: a filename, a dictionary or a list of dictionaries or
424
+ - descriptor: a filename, a dictionary or a list of dictionaries or
397
425
  None (None by default)
398
426
 
399
427
  # Returned value
@@ -403,7 +431,7 @@ def make_app(
403
431
 
404
432
  `CONFIG` is a dictionary, the complete config file. `CONTEXT` is a
405
433
  subset of `CONFIG`, the current entry in `CONFIG['context']`. It is
406
- also a dictionary. `MANIFEST` is the service manifest.
434
+ also a dictionary. `DESCRIPTOR` is the service descriptor.
407
435
 
408
436
  # Raised Exception
409
437
 
@@ -415,27 +443,13 @@ def make_app(
415
443
  configure_logging(name, _get_debug_level(name))
416
444
  app = Flask(name)
417
445
  try:
418
- if args.config is None and not os.path.isfile(configfile):
419
- if args.context:
420
- raise ConfigError(
421
- 'Cannot specify a context when using default configuration.'
422
- )
423
- context = defaultcontext or DEFAULT_CONTEXT
424
- config = {}
425
- else:
426
- configfile, config = read_configfile(args.config, configfile)
427
- valid, extra = validate_schema(schema or SERVICECONFIG, config)
428
- if not valid:
429
- raise ConfigError(f'Config file "{configfile}" is invalid: {extra}.')
446
+ context, config = read_config(
447
+ args.config, args.context, configfile, defaultcontext, schema
448
+ )
430
449
 
431
- context_name = args.context or config['current-context']
432
- try:
433
- context = get_named(context_name, config['contexts'])['context']
434
- except ValueError as err:
435
- raise ConfigError(f'Could not find context "{context_name}": {err}.')
450
+ if args.descriptor or descriptor is None or isinstance(descriptor, str):
451
+ _, descriptor = read_descriptor(args.descriptor, descriptor)
436
452
 
437
- if args.manifest is not None or manifest is None or isinstance(manifest, str):
438
- _, manifest = read_manifest(args.manifest, manifest)
439
453
  if args.host:
440
454
  context['host'] = args.host
441
455
  if args.port:
@@ -450,21 +464,14 @@ def make_app(
450
464
 
451
465
  app.config['CONTEXT'] = context
452
466
  app.config['CONFIG'] = config
453
- app.config['MANIFEST'] = manifest if isinstance(manifest, list) else [manifest]
467
+ app.config['DESCRIPTOR'] = (
468
+ descriptor if isinstance(descriptor, list) else [descriptor]
469
+ )
454
470
  app.before_request(_make_authenticator(context))
455
471
  app.after_request(_add_securityheaders)
456
472
  return app
457
473
 
458
474
 
459
- def get_named(name: str, entries: List[Dict[str, Any]]) -> Dict[str, Any]:
460
- items = [entry for entry in entries if entry.get('name') == name]
461
- if not items:
462
- raise ValueError(f'Found no entry with name "{name}"')
463
- if len(items) > 1:
464
- raise ValueError(f'Found more than one entry with name "{name}"')
465
- return items.pop()
466
-
467
-
468
475
  def get_context_parameter(
469
476
  app: Flask, name: str, validator: Optional[Any] = None
470
477
  ) -> int:
@@ -472,10 +479,6 @@ def get_context_parameter(
472
479
 
473
480
  Exits with an error code of 2 if the parameter is not an integer.
474
481
 
475
- Configuration: (on first call only)
476
- descriptiveName (name): %d
477
- [DescriptiveName must be greater that %d, aborting.]
478
- descriptiveName (name): %d (was defined as %d, but {reason})
479
482
  # Required parameters
480
483
 
481
484
  - app: a Flask object
@@ -503,35 +506,13 @@ def get_context_parameter(
503
506
  app.logger.error(*msg)
504
507
  sys.exit(2)
505
508
 
506
- # maybe_initialize()
507
- if '__PARAMETERS__' not in app.config:
508
- app.config['__PARAMETERS__'] = []
509
- for manifest in app.config['MANIFEST']:
510
- if manifest.get('metadata', {}).get('name', '').lower() != app.name.lower():
511
- continue
512
- app.config['__PARAMETERS__'] += manifest.get('spec', {}).get(
513
- 'contextParameters', []
514
- )
515
- app.config['__PARAMETERS__'] += [
516
- {
517
- 'name': 'watchdog_polling_delay_seconds',
518
- 'descriptiveName': 'polling delay in seconds',
519
- 'default': 30,
520
- 'type': 'int',
521
- }
522
- ]
523
- app.logger.info('Configuration:')
524
- parameters = app.config['__PARAMETERS__']
525
- try:
526
- spec = get_named(name, parameters)
527
- except ValueError:
528
- spec = None
509
+ spec = _get_contextparameter_spec(app, name)
529
510
  try:
530
511
  if name not in app.config['CONTEXT']:
531
512
  if spec and 'default' in spec:
532
513
  return _maybe_validate(spec['default'])
533
514
  _fatal(
534
- 'Context parameter %s not found in current context and no default value specified.',
515
+ 'Context parameter %s not in current context and no default value specified.',
535
516
  name,
536
517
  )
537
518
 
@@ -540,17 +521,14 @@ def get_context_parameter(
540
521
  return _maybe_validate(val)
541
522
  if spec.get('type') == 'int':
542
523
  val = int(val)
524
+ desc = spec['descriptiveName']
543
525
  if (low := spec.get('minValue')) and val < low:
544
526
  _fatal(
545
- spec['descriptiveName'][0].upper()
546
- + spec['descriptiveName'][1:]
547
- + f' must be greater than {low-1}, aborting.'
527
+ desc[0].upper() + desc[1:] + f' must be greater than {low-1}, aborting.'
548
528
  )
549
529
  if (high := spec.get('maxValue')) and val > high:
550
530
  _fatal(
551
- spec['descriptiveName'][0].upper()
552
- + spec['descriptiveName'][1:]
553
- + f' must be less that {high+1}, aborting.'
531
+ desc[0].upper() + desc[1:] + f' must be less that {high+1}, aborting.'
554
532
  )
555
533
  return _maybe_validate(val)
556
534
  except ValueError as err:
@@ -580,7 +558,7 @@ def get_context_service(app: Flask, service: str) -> Dict[str, Any]:
580
558
  sys.exit(2)
581
559
 
582
560
 
583
- def run_app(app) -> None:
561
+ def run_app(app: Flask) -> None:
584
562
  """Start the app.
585
563
 
586
564
  Using waitress as the wsgi server. The logging service is
@@ -595,12 +573,13 @@ def run_app(app) -> None:
595
573
  if _get_debug_level(app.name) == 'DEBUG':
596
574
  from paste.translogger import TransLogger
597
575
 
598
- app = TransLogger(app, format=ACCESSLOG_FORMAT, setup_console_handler=False)
576
+ _app = TransLogger(app, format=ACCESSLOG_FORMAT, setup_console_handler=False)
599
577
  else:
600
578
  logging.getLogger('waitress').setLevel('ERROR')
601
579
  app.logger.info(f'Serving on http://{context["host"]}:{context["port"]}')
580
+ _app = app
602
581
 
603
- serve(app, host=context['host'], port=context['port'])
582
+ serve(_app, host=context['host'], port=context['port'])
604
583
 
605
584
 
606
585
  ########################################################################
opentf/commons/config.py CHANGED
@@ -14,6 +14,7 @@
14
14
 
15
15
  """Helpers for the OpenTestFactory config."""
16
16
 
17
+ from typing import Any, Dict, List, Optional, Tuple
17
18
 
18
19
  import argparse
19
20
  import inspect
@@ -23,11 +24,20 @@ from logging.config import dictConfig
23
24
 
24
25
  import yaml
25
26
 
27
+ from .schemas import validate_schema, SERVICECONFIG
28
+
26
29
 
27
30
  ########################################################################
28
31
 
29
32
  NOTIFICATION_LOGGER_EXCLUSIONS = 'eventbus'
30
33
 
34
+ DEFAULT_CONTEXT = {
35
+ 'host': '127.0.0.1',
36
+ 'port': 443,
37
+ 'ssl_context': 'adhoc',
38
+ 'eventbus': {'endpoint': 'https://127.0.0.1:38368', 'token': 'invalid-token'},
39
+ }
40
+
31
41
 
32
42
  ########################################################################
33
43
 
@@ -38,7 +48,7 @@ class ConfigError(Exception):
38
48
 
39
49
  def make_argparser(description: str, configfile: str) -> argparse.ArgumentParser:
40
50
  parser = argparse.ArgumentParser(description=description)
41
- parser.add_argument('--manifest', help='alternate manifest file')
51
+ parser.add_argument('--descriptor', help='alternate descriptor file')
42
52
  parser.add_argument(
43
53
  '--config', help=f'alternate config file (default to {configfile})'
44
54
  )
@@ -117,32 +127,91 @@ def configure_logging(name: str, debug_level: str) -> None:
117
127
  dictConfig(logging_conf)
118
128
 
119
129
 
120
- def read_configfile(argsconfig, configfile: str):
130
+ def _read_configfile(
131
+ argsconfig: Optional[str], configfile: str
132
+ ) -> Tuple[str, Dict[str, Any]]:
121
133
  try:
122
- configfile = argsconfig or configfile
123
- with open(configfile, 'r', encoding='utf-8') as cnf:
134
+ filename = argsconfig or configfile
135
+ with open(filename, 'r', encoding='utf-8') as cnf:
124
136
  config = yaml.safe_load(cnf)
125
- return configfile, config
137
+ if not isinstance(config, dict):
138
+ raise ValueError('Config file is not an object.')
139
+ return filename, config
126
140
  except Exception as err:
127
- raise ConfigError(f'Could not get configfile "{configfile}", aborting: {err}.')
128
-
129
-
130
- def read_manifest(argsmanifest, manifest):
141
+ raise ConfigError(f'Could not get configfile "{filename}", aborting: {err}.')
142
+
143
+
144
+ def read_config(
145
+ argsconfig: Optional[str],
146
+ argscontext: Optional[str],
147
+ configfile: str,
148
+ defaultcontext,
149
+ schema,
150
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
151
+ if argsconfig is None and not os.path.isfile(configfile):
152
+ if argscontext:
153
+ raise ConfigError(
154
+ 'Cannot specify a context when using default configuration.'
155
+ )
156
+ context = defaultcontext or DEFAULT_CONTEXT
157
+ config = {}
158
+ else:
159
+ configfile, config = _read_configfile(argsconfig, configfile)
160
+ valid, extra = validate_schema(schema or SERVICECONFIG, config)
161
+ if not valid:
162
+ raise ConfigError(f'Config file "{configfile}" is invalid: {extra}.')
163
+
164
+ context_name = argscontext or config['current-context']
165
+ try:
166
+ context = get_named(context_name, config['contexts'])['context']
167
+ except ValueError as err:
168
+ raise ConfigError(f'Could not find context "{context_name}": {err}.')
169
+ return context, config
170
+
171
+
172
+ def read_descriptor(
173
+ argsdescriptor: Optional[str], descriptor: Any
174
+ ) -> Tuple[str, List[Dict[str, Any]]]:
131
175
  try:
132
- if argsmanifest:
133
- manifestfile = argsmanifest
176
+ if argsdescriptor:
177
+ filename = argsdescriptor
134
178
  else:
135
179
  for frame in inspect.stack():
136
180
  if frame.frame.f_code.co_name == '<module>':
137
181
  break
138
182
  else:
139
183
  raise ConfigError('Could not get module location, aborting.')
140
- manifestfile = os.path.join(
184
+ filename = os.path.join(
141
185
  os.path.dirname(frame.filename),
142
- manifest or 'service.yaml',
186
+ descriptor or 'service.yaml',
143
187
  )
144
- with open(manifestfile, 'r', encoding='utf-8') as definition:
145
- manifest = list(yaml.safe_load_all(definition))
146
- return manifestfile, manifest
188
+ with open(filename, 'r', encoding='utf-8') as definition:
189
+ manifests = list(yaml.safe_load_all(definition))
190
+ return filename, manifests
147
191
  except Exception as err:
148
- raise ConfigError(f'Could not get manifest "{manifestfile}", aborting: {err}.')
192
+ raise ConfigError(f'Could not get descriptor "{filename}", aborting: {err}.')
193
+
194
+
195
+ def get_named(name: str, entries: List[Dict[str, Any]]) -> Dict[str, Any]:
196
+ """Get an entry from a list of entries.
197
+
198
+ # Required parameters
199
+
200
+ - name: a string, the entry 'name'
201
+ - entries: a list of dictionaries
202
+
203
+ # Returned value
204
+
205
+ A dictionary, the entry with the 'name' `name`.
206
+
207
+ # Raised exceptions
208
+
209
+ A _ValueError_ exception is raised if no entry is found or if more
210
+ than one entry is found.
211
+ """
212
+ items = [entry for entry in entries if entry.get('name') == name]
213
+ if not items:
214
+ raise ValueError(f'Found no entry with name "{name}"')
215
+ if len(items) > 1:
216
+ raise ValueError(f'Found more than one entry with name "{name}"')
217
+ return items.pop()
@@ -41,31 +41,7 @@
41
41
  "additionalProperties": false
42
42
  },
43
43
  "matchExpressions": {
44
- "type": "array",
45
- "minItems": 1,
46
- "items":{
47
- "type": "object",
48
- "properties": {
49
- "key": { "type": "string" },
50
- "operator": {
51
- "enum": [
52
- "In",
53
- "NotIn",
54
- "Exists",
55
- "DoesNotExist"
56
- ]
57
- },
58
- "values": {
59
- "type": "array",
60
- "minItems": 0,
61
- "items": {
62
- "type": "string"
63
- }
64
- }
65
- },
66
- "additionalProperties": false,
67
- "required": [ "key", "operator" ]
68
- }
44
+ "$ref": "#/definitions/expressions"
69
45
  },
70
46
  "matchFields": {
71
47
  "type": "object",
@@ -76,6 +52,9 @@
76
52
  },
77
53
  "minProperties": 1,
78
54
  "additionalProperties": false
55
+ },
56
+ "matchFieldExpressions": {
57
+ "$ref": "#/definitions/expressions"
79
58
  }
80
59
  },
81
60
  "minProperties": 1,
@@ -109,5 +88,61 @@
109
88
  "metadata",
110
89
  "spec"
111
90
  ],
112
- "additionalProperties": false
91
+ "additionalProperties": false,
92
+ "definitions": {
93
+ "expressions": {
94
+ "type": "array",
95
+ "minItems": 1,
96
+ "items": {
97
+ "anyOf": [
98
+ {
99
+ "type": "object",
100
+ "properties": {
101
+ "key": {
102
+ "type": "string"
103
+ },
104
+ "operator": {
105
+ "enum": [
106
+ "In",
107
+ "NotIn"
108
+ ]
109
+ },
110
+ "values": {
111
+ "type": "array",
112
+ "minItems": 1,
113
+ "items": {
114
+ "type": "string"
115
+ }
116
+ }
117
+ },
118
+ "additionalProperties": false,
119
+ "required": [
120
+ "key",
121
+ "operator",
122
+ "values"
123
+ ]
124
+ },
125
+ {
126
+ "type": "object",
127
+ "properties": {
128
+ "key": {
129
+ "type": "string"
130
+ },
131
+ "operator": {
132
+ "enum": [
133
+ "Exists",
134
+ "DoesNotExist"
135
+ ]
136
+ }
137
+ },
138
+ "additionalProperties": false,
139
+ "required": [
140
+ "key",
141
+ "operator"
142
+ ]
143
+ }
144
+ ]
145
+ }
146
+ }
147
+ }
113
148
  }
@@ -409,7 +409,7 @@ def run_plugin(plugin):
409
409
  context[SUBSCRIPTION_KEY] = []
410
410
  context[INPUTS_KEY] = {}
411
411
  if context[KIND_KEY] == PROVIDERCOMMAND:
412
- for manifest in plugin.config['MANIFEST']:
412
+ for manifest in plugin.config['DESCRIPTOR']:
413
413
  metadata = manifest.get('metadata', {})
414
414
  if metadata.get('name', '').lower() != plugin.name.lower():
415
415
  continue
@@ -445,7 +445,7 @@ def make_plugin(
445
445
  provider: Optional[Handler] = None,
446
446
  providers: Optional[Dict[str, Handler]] = None,
447
447
  publisher: Optional[Handler] = None,
448
- manifest=None,
448
+ descriptor=None,
449
449
  schema=None,
450
450
  configfile=None,
451
451
  ):
@@ -454,7 +454,7 @@ def make_plugin(
454
454
  One and only one of `channel`, `generator`, `provider`, `providers`,
455
455
  or `publisher` must be specified.
456
456
 
457
- If no `manifest` is specified, there must be `plugin.yaml` file in
457
+ If no `descriptor` is specified, there must be `plugin.yaml` file in
458
458
  the same directory as the caller source file. If none is found the
459
459
  execution stops.
460
460
 
@@ -472,8 +472,8 @@ def make_plugin(
472
472
 
473
473
  # Optional parameters
474
474
 
475
- - manifest: a dictionary or a list of dictionaries or None (None by
476
- default)
475
+ - descriptor: a dictionary or a list of dictionaries or None (None
476
+ by default)
477
477
  - schema: a string or None (None by default)
478
478
  - configfile: a string or None (None by default)
479
479
 
@@ -522,9 +522,9 @@ def make_plugin(
522
522
  raise ValueError(
523
523
  "One and only one of 'channel', 'generator', 'provider', 'providers', or 'publisher' is required."
524
524
  )
525
- if not (manifest is None or isinstance(manifest, (dict, list))):
525
+ if not (descriptor is None or isinstance(descriptor, (dict, list))):
526
526
  raise ValueError(
527
- "'manifest', if specified, must be a dictionary or a list of dictionaries."
527
+ "'descriptor', if specified, must be a dictionary or a list of dictionaries."
528
528
  )
529
529
 
530
530
  kind = (
@@ -542,7 +542,7 @@ def make_plugin(
542
542
  description,
543
543
  configfile=configfile or f'conf/{name}.yaml',
544
544
  schema=schema,
545
- manifest=manifest if manifest is not None else 'plugin.yaml',
545
+ descriptor=descriptor if descriptor is not None else 'plugin.yaml',
546
546
  )
547
547
  plugin.route('/inbox', methods=['POST'])(process_inbox)
548
548
  plugin.config['CONTEXT'][KIND_KEY] = kind
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opentf-toolkit-nightly
3
- Version: 0.50.0.dev696
3
+ Version: 0.50.0.dev705
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,6 +1,6 @@
1
- opentf/commons/__init__.py,sha256=nw4kltwMXlHQmgPS1l37-fbLLaIDkHzyWXNqrgmq0-s,23222
1
+ opentf/commons/__init__.py,sha256=06GO6FXo0zq7IJzDr4718FQ5IIze6EyReC0UACF3L0M,22063
2
2
  opentf/commons/auth.py,sha256=ADMygTSGy6voOQUAD9EtusPR_hgJ6jUK_uJE8CCpBoE,14481
3
- opentf/commons/config.py,sha256=baDqduth1iPedcnnfLEH6X1VlDVK17S7zCIy7c2cOhI,4797
3
+ opentf/commons/config.py,sha256=CJ3xGc9dmva08zek9FIMqFHkgwoPOukiXmafN2nm000,7006
4
4
  opentf/commons/expressions.py,sha256=dKcYYc7j3laueZEcV00djvE7UFPLMiUTNeNvKGla3cQ,19069
5
5
  opentf/commons/pubsub.py,sha256=_Psa3wdE_OB6wDHhUwr9zdxHpu5rSz19qtpM1Qo2WsY,5675
6
6
  opentf/commons/schemas.py,sha256=kMhZH47dpBk_HDMZk-1AlTb1dIYF-N6SPiEUmkEtWX0,3909
@@ -25,7 +25,7 @@ opentf/schemas/opentestfactory.org/v1alpha1/QualityGate.json,sha256=BLIPkLiENjN-
25
25
  opentf/schemas/opentestfactory.org/v1alpha1/RetentionPolicy.json,sha256=EvTha15eFVbvaZhzy60IeHt-oKOqOZVWiPuS3PZejTI,1182
26
26
  opentf/schemas/opentestfactory.org/v1alpha1/SSHServiceConfig.json,sha256=qqFoI-Ltn6O25YgjSiumhh0KEgm-Ftl3v56AxnCP7Cs,6301
27
27
  opentf/schemas/opentestfactory.org/v1alpha1/ServiceConfig.json,sha256=hRhJj4CkvB6p0IKKLMIwyxnbTmJkyEiDJSUxqzv0exI,2835
28
- opentf/schemas/opentestfactory.org/v1alpha1/Subscription.json,sha256=I0lhUvRg0lV1Xi7NDSP8qYLKv4vy7J9IH3-qryaiDG4,4115
28
+ opentf/schemas/opentestfactory.org/v1alpha1/Subscription.json,sha256=sc32NWjbmw2fFlvU6Guh7VhlHfp7kLzOisDFL6-BDRU,5031
29
29
  opentf/schemas/opentestfactory.org/v1alpha1/Workflow.json,sha256=PKuAGeyQnGjoYNbd3IUng4k8SIecIVelXzzOncewhyw,9899
30
30
  opentf/schemas/opentestfactory.org/v1alpha1/WorkflowCanceled.json,sha256=hLGQnrSXjvKZTzegucHrtGjAgS8dZeC7dZZ6mZVvclc,1351
31
31
  opentf/schemas/opentestfactory.org/v1alpha1/WorkflowCompleted.json,sha256=O1wpwhSawF9u64RtX38Lv2sptq8w3q8dvdvHxFwG20U,1292
@@ -42,11 +42,11 @@ opentf/schemas/opentestfactory.org/v1beta1/Workflow.json,sha256=QZ8mM9PhzsI9gTmw
42
42
  opentf/schemas/opentestfactory.org/v1beta2/ServiceConfig.json,sha256=rEvK2YWL5lG94_qYgR_GnLWNsaQhaQ-2kuZdWJr5NnY,3517
43
43
  opentf/scripts/launch_java_service.sh,sha256=Ut_STdFqMhTV7cekPVp4JkBTqZKcJSAh1UNUn9Ylv3g,2427
44
44
  opentf/scripts/startup.py,sha256=CjKrFqbLyDKdUca-fWB-QkDURjdypkbrBUpEFNy3qQo,18719
45
- opentf/toolkit/__init__.py,sha256=HRh7YRtjlkqL_RJfAsEuVJGLHLEYFYkJUJj4We4ZwLM,18351
45
+ opentf/toolkit/__init__.py,sha256=4bL02Q3DgtMWZhaCvlJ7eOp9rPGIG9p-xNcs8hynhhQ,18371
46
46
  opentf/toolkit/channels.py,sha256=GGIPuUN7sFM_FwoqbUgLk7smggLty3rSDZTma5jAAt4,16185
47
47
  opentf/toolkit/core.py,sha256=40S-pUKXWidbI4JwkmQjGq46WlxJshj6d-wEl4e5TxU,7312
48
- opentf_toolkit_nightly-0.50.0.dev696.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
49
- opentf_toolkit_nightly-0.50.0.dev696.dist-info/METADATA,sha256=Q7pm0prFiz8R7xw-JnA3RFe7KJqX3OS8jewmq0fDt38,1965
50
- opentf_toolkit_nightly-0.50.0.dev696.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
51
- opentf_toolkit_nightly-0.50.0.dev696.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
52
- opentf_toolkit_nightly-0.50.0.dev696.dist-info/RECORD,,
48
+ opentf_toolkit_nightly-0.50.0.dev705.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
49
+ opentf_toolkit_nightly-0.50.0.dev705.dist-info/METADATA,sha256=2BuuxKrik9f7f_7FliEYZwaqUaov-XJbjPyIzAe4Er4,1965
50
+ opentf_toolkit_nightly-0.50.0.dev705.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
51
+ opentf_toolkit_nightly-0.50.0.dev705.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
52
+ opentf_toolkit_nightly-0.50.0.dev705.dist-info/RECORD,,