outerbounds 0.3.55rc8__py3-none-any.whl → 0.3.133__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. outerbounds/_vendor/PyYAML.LICENSE +20 -0
  2. outerbounds/_vendor/__init__.py +0 -0
  3. outerbounds/_vendor/_yaml/__init__.py +34 -0
  4. outerbounds/_vendor/click/__init__.py +73 -0
  5. outerbounds/_vendor/click/_compat.py +626 -0
  6. outerbounds/_vendor/click/_termui_impl.py +717 -0
  7. outerbounds/_vendor/click/_textwrap.py +49 -0
  8. outerbounds/_vendor/click/_winconsole.py +279 -0
  9. outerbounds/_vendor/click/core.py +2998 -0
  10. outerbounds/_vendor/click/decorators.py +497 -0
  11. outerbounds/_vendor/click/exceptions.py +287 -0
  12. outerbounds/_vendor/click/formatting.py +301 -0
  13. outerbounds/_vendor/click/globals.py +68 -0
  14. outerbounds/_vendor/click/parser.py +529 -0
  15. outerbounds/_vendor/click/py.typed +0 -0
  16. outerbounds/_vendor/click/shell_completion.py +580 -0
  17. outerbounds/_vendor/click/termui.py +787 -0
  18. outerbounds/_vendor/click/testing.py +479 -0
  19. outerbounds/_vendor/click/types.py +1073 -0
  20. outerbounds/_vendor/click/utils.py +580 -0
  21. outerbounds/_vendor/click.LICENSE +28 -0
  22. outerbounds/_vendor/vendor_any.txt +2 -0
  23. outerbounds/_vendor/yaml/__init__.py +471 -0
  24. outerbounds/_vendor/yaml/_yaml.cpython-311-darwin.so +0 -0
  25. outerbounds/_vendor/yaml/composer.py +146 -0
  26. outerbounds/_vendor/yaml/constructor.py +862 -0
  27. outerbounds/_vendor/yaml/cyaml.py +177 -0
  28. outerbounds/_vendor/yaml/dumper.py +138 -0
  29. outerbounds/_vendor/yaml/emitter.py +1239 -0
  30. outerbounds/_vendor/yaml/error.py +94 -0
  31. outerbounds/_vendor/yaml/events.py +104 -0
  32. outerbounds/_vendor/yaml/loader.py +62 -0
  33. outerbounds/_vendor/yaml/nodes.py +51 -0
  34. outerbounds/_vendor/yaml/parser.py +629 -0
  35. outerbounds/_vendor/yaml/reader.py +208 -0
  36. outerbounds/_vendor/yaml/representer.py +378 -0
  37. outerbounds/_vendor/yaml/resolver.py +245 -0
  38. outerbounds/_vendor/yaml/scanner.py +1555 -0
  39. outerbounds/_vendor/yaml/serializer.py +127 -0
  40. outerbounds/_vendor/yaml/tokens.py +129 -0
  41. outerbounds/command_groups/apps_cli.py +450 -0
  42. outerbounds/command_groups/cli.py +9 -5
  43. outerbounds/command_groups/local_setup_cli.py +247 -36
  44. outerbounds/command_groups/perimeters_cli.py +212 -32
  45. outerbounds/command_groups/tutorials_cli.py +111 -0
  46. outerbounds/command_groups/workstations_cli.py +2 -2
  47. outerbounds/utils/kubeconfig.py +2 -2
  48. outerbounds/utils/metaflowconfig.py +93 -16
  49. outerbounds/utils/schema.py +2 -2
  50. outerbounds/utils/utils.py +19 -0
  51. outerbounds/vendor.py +159 -0
  52. {outerbounds-0.3.55rc8.dist-info → outerbounds-0.3.133.dist-info}/METADATA +17 -6
  53. outerbounds-0.3.133.dist-info/RECORD +59 -0
  54. {outerbounds-0.3.55rc8.dist-info → outerbounds-0.3.133.dist-info}/WHEEL +1 -1
  55. outerbounds-0.3.55rc8.dist-info/RECORD +0 -15
  56. {outerbounds-0.3.55rc8.dist-info → outerbounds-0.3.133.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,862 @@
1
+ __all__ = [
2
+ "BaseConstructor",
3
+ "SafeConstructor",
4
+ "FullConstructor",
5
+ "UnsafeConstructor",
6
+ "Constructor",
7
+ "ConstructorError",
8
+ ]
9
+
10
+ from .error import *
11
+ from .nodes import *
12
+
13
+ import collections.abc, datetime, base64, binascii, re, sys, types
14
+
15
+
16
+ class ConstructorError(MarkedYAMLError):
17
+ pass
18
+
19
+
20
+ class BaseConstructor:
21
+
22
+ yaml_constructors = {}
23
+ yaml_multi_constructors = {}
24
+
25
+ def __init__(self):
26
+ self.constructed_objects = {}
27
+ self.recursive_objects = {}
28
+ self.state_generators = []
29
+ self.deep_construct = False
30
+
31
+ def check_data(self):
32
+ # If there are more documents available?
33
+ return self.check_node()
34
+
35
+ def check_state_key(self, key):
36
+ """Block special attributes/methods from being set in a newly created
37
+ object, to prevent user-controlled methods from being called during
38
+ deserialization"""
39
+ if self.get_state_keys_blacklist_regexp().match(key):
40
+ raise ConstructorError(
41
+ None,
42
+ None,
43
+ "blacklisted key '%s' in instance state found" % (key,),
44
+ None,
45
+ )
46
+
47
+ def get_data(self):
48
+ # Construct and return the next document.
49
+ if self.check_node():
50
+ return self.construct_document(self.get_node())
51
+
52
+ def get_single_data(self):
53
+ # Ensure that the stream contains a single document and construct it.
54
+ node = self.get_single_node()
55
+ if node is not None:
56
+ return self.construct_document(node)
57
+ return None
58
+
59
+ def construct_document(self, node):
60
+ data = self.construct_object(node)
61
+ while self.state_generators:
62
+ state_generators = self.state_generators
63
+ self.state_generators = []
64
+ for generator in state_generators:
65
+ for dummy in generator:
66
+ pass
67
+ self.constructed_objects = {}
68
+ self.recursive_objects = {}
69
+ self.deep_construct = False
70
+ return data
71
+
72
+ def construct_object(self, node, deep=False):
73
+ if node in self.constructed_objects:
74
+ return self.constructed_objects[node]
75
+ if deep:
76
+ old_deep = self.deep_construct
77
+ self.deep_construct = True
78
+ if node in self.recursive_objects:
79
+ raise ConstructorError(
80
+ None, None, "found unconstructable recursive node", node.start_mark
81
+ )
82
+ self.recursive_objects[node] = None
83
+ constructor = None
84
+ tag_suffix = None
85
+ if node.tag in self.yaml_constructors:
86
+ constructor = self.yaml_constructors[node.tag]
87
+ else:
88
+ for tag_prefix in self.yaml_multi_constructors:
89
+ if tag_prefix is not None and node.tag.startswith(tag_prefix):
90
+ tag_suffix = node.tag[len(tag_prefix) :]
91
+ constructor = self.yaml_multi_constructors[tag_prefix]
92
+ break
93
+ else:
94
+ if None in self.yaml_multi_constructors:
95
+ tag_suffix = node.tag
96
+ constructor = self.yaml_multi_constructors[None]
97
+ elif None in self.yaml_constructors:
98
+ constructor = self.yaml_constructors[None]
99
+ elif isinstance(node, ScalarNode):
100
+ constructor = self.__class__.construct_scalar
101
+ elif isinstance(node, SequenceNode):
102
+ constructor = self.__class__.construct_sequence
103
+ elif isinstance(node, MappingNode):
104
+ constructor = self.__class__.construct_mapping
105
+ if tag_suffix is None:
106
+ data = constructor(self, node)
107
+ else:
108
+ data = constructor(self, tag_suffix, node)
109
+ if isinstance(data, types.GeneratorType):
110
+ generator = data
111
+ data = next(generator)
112
+ if self.deep_construct:
113
+ for dummy in generator:
114
+ pass
115
+ else:
116
+ self.state_generators.append(generator)
117
+ self.constructed_objects[node] = data
118
+ del self.recursive_objects[node]
119
+ if deep:
120
+ self.deep_construct = old_deep
121
+ return data
122
+
123
+ def construct_scalar(self, node):
124
+ if not isinstance(node, ScalarNode):
125
+ raise ConstructorError(
126
+ None,
127
+ None,
128
+ "expected a scalar node, but found %s" % node.id,
129
+ node.start_mark,
130
+ )
131
+ return node.value
132
+
133
+ def construct_sequence(self, node, deep=False):
134
+ if not isinstance(node, SequenceNode):
135
+ raise ConstructorError(
136
+ None,
137
+ None,
138
+ "expected a sequence node, but found %s" % node.id,
139
+ node.start_mark,
140
+ )
141
+ return [self.construct_object(child, deep=deep) for child in node.value]
142
+
143
+ def construct_mapping(self, node, deep=False):
144
+ if not isinstance(node, MappingNode):
145
+ raise ConstructorError(
146
+ None,
147
+ None,
148
+ "expected a mapping node, but found %s" % node.id,
149
+ node.start_mark,
150
+ )
151
+ mapping = {}
152
+ for key_node, value_node in node.value:
153
+ key = self.construct_object(key_node, deep=deep)
154
+ if not isinstance(key, collections.abc.Hashable):
155
+ raise ConstructorError(
156
+ "while constructing a mapping",
157
+ node.start_mark,
158
+ "found unhashable key",
159
+ key_node.start_mark,
160
+ )
161
+ value = self.construct_object(value_node, deep=deep)
162
+ mapping[key] = value
163
+ return mapping
164
+
165
+ def construct_pairs(self, node, deep=False):
166
+ if not isinstance(node, MappingNode):
167
+ raise ConstructorError(
168
+ None,
169
+ None,
170
+ "expected a mapping node, but found %s" % node.id,
171
+ node.start_mark,
172
+ )
173
+ pairs = []
174
+ for key_node, value_node in node.value:
175
+ key = self.construct_object(key_node, deep=deep)
176
+ value = self.construct_object(value_node, deep=deep)
177
+ pairs.append((key, value))
178
+ return pairs
179
+
180
+ @classmethod
181
+ def add_constructor(cls, tag, constructor):
182
+ if not "yaml_constructors" in cls.__dict__:
183
+ cls.yaml_constructors = cls.yaml_constructors.copy()
184
+ cls.yaml_constructors[tag] = constructor
185
+
186
+ @classmethod
187
+ def add_multi_constructor(cls, tag_prefix, multi_constructor):
188
+ if not "yaml_multi_constructors" in cls.__dict__:
189
+ cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy()
190
+ cls.yaml_multi_constructors[tag_prefix] = multi_constructor
191
+
192
+
193
+ class SafeConstructor(BaseConstructor):
194
+ def construct_scalar(self, node):
195
+ if isinstance(node, MappingNode):
196
+ for key_node, value_node in node.value:
197
+ if key_node.tag == "tag:yaml.org,2002:value":
198
+ return self.construct_scalar(value_node)
199
+ return super().construct_scalar(node)
200
+
201
+ def flatten_mapping(self, node):
202
+ merge = []
203
+ index = 0
204
+ while index < len(node.value):
205
+ key_node, value_node = node.value[index]
206
+ if key_node.tag == "tag:yaml.org,2002:merge":
207
+ del node.value[index]
208
+ if isinstance(value_node, MappingNode):
209
+ self.flatten_mapping(value_node)
210
+ merge.extend(value_node.value)
211
+ elif isinstance(value_node, SequenceNode):
212
+ submerge = []
213
+ for subnode in value_node.value:
214
+ if not isinstance(subnode, MappingNode):
215
+ raise ConstructorError(
216
+ "while constructing a mapping",
217
+ node.start_mark,
218
+ "expected a mapping for merging, but found %s"
219
+ % subnode.id,
220
+ subnode.start_mark,
221
+ )
222
+ self.flatten_mapping(subnode)
223
+ submerge.append(subnode.value)
224
+ submerge.reverse()
225
+ for value in submerge:
226
+ merge.extend(value)
227
+ else:
228
+ raise ConstructorError(
229
+ "while constructing a mapping",
230
+ node.start_mark,
231
+ "expected a mapping or list of mappings for merging, but found %s"
232
+ % value_node.id,
233
+ value_node.start_mark,
234
+ )
235
+ elif key_node.tag == "tag:yaml.org,2002:value":
236
+ key_node.tag = "tag:yaml.org,2002:str"
237
+ index += 1
238
+ else:
239
+ index += 1
240
+ if merge:
241
+ node.value = merge + node.value
242
+
243
+ def construct_mapping(self, node, deep=False):
244
+ if isinstance(node, MappingNode):
245
+ self.flatten_mapping(node)
246
+ return super().construct_mapping(node, deep=deep)
247
+
248
+ def construct_yaml_null(self, node):
249
+ self.construct_scalar(node)
250
+ return None
251
+
252
+ bool_values = {
253
+ "yes": True,
254
+ "no": False,
255
+ "true": True,
256
+ "false": False,
257
+ "on": True,
258
+ "off": False,
259
+ }
260
+
261
+ def construct_yaml_bool(self, node):
262
+ value = self.construct_scalar(node)
263
+ return self.bool_values[value.lower()]
264
+
265
+ def construct_yaml_int(self, node):
266
+ value = self.construct_scalar(node)
267
+ value = value.replace("_", "")
268
+ sign = +1
269
+ if value[0] == "-":
270
+ sign = -1
271
+ if value[0] in "+-":
272
+ value = value[1:]
273
+ if value == "0":
274
+ return 0
275
+ elif value.startswith("0b"):
276
+ return sign * int(value[2:], 2)
277
+ elif value.startswith("0x"):
278
+ return sign * int(value[2:], 16)
279
+ elif value[0] == "0":
280
+ return sign * int(value, 8)
281
+ elif ":" in value:
282
+ digits = [int(part) for part in value.split(":")]
283
+ digits.reverse()
284
+ base = 1
285
+ value = 0
286
+ for digit in digits:
287
+ value += digit * base
288
+ base *= 60
289
+ return sign * value
290
+ else:
291
+ return sign * int(value)
292
+
293
+ inf_value = 1e300
294
+ while inf_value != inf_value * inf_value:
295
+ inf_value *= inf_value
296
+ nan_value = -inf_value / inf_value # Trying to make a quiet NaN (like C99).
297
+
298
+ def construct_yaml_float(self, node):
299
+ value = self.construct_scalar(node)
300
+ value = value.replace("_", "").lower()
301
+ sign = +1
302
+ if value[0] == "-":
303
+ sign = -1
304
+ if value[0] in "+-":
305
+ value = value[1:]
306
+ if value == ".inf":
307
+ return sign * self.inf_value
308
+ elif value == ".nan":
309
+ return self.nan_value
310
+ elif ":" in value:
311
+ digits = [float(part) for part in value.split(":")]
312
+ digits.reverse()
313
+ base = 1
314
+ value = 0.0
315
+ for digit in digits:
316
+ value += digit * base
317
+ base *= 60
318
+ return sign * value
319
+ else:
320
+ return sign * float(value)
321
+
322
+ def construct_yaml_binary(self, node):
323
+ try:
324
+ value = self.construct_scalar(node).encode("ascii")
325
+ except UnicodeEncodeError as exc:
326
+ raise ConstructorError(
327
+ None,
328
+ None,
329
+ "failed to convert base64 data into ascii: %s" % exc,
330
+ node.start_mark,
331
+ )
332
+ try:
333
+ if hasattr(base64, "decodebytes"):
334
+ return base64.decodebytes(value)
335
+ else:
336
+ return base64.decodestring(value)
337
+ except binascii.Error as exc:
338
+ raise ConstructorError(
339
+ None, None, "failed to decode base64 data: %s" % exc, node.start_mark
340
+ )
341
+
342
+ timestamp_regexp = re.compile(
343
+ r"""^(?P<year>[0-9][0-9][0-9][0-9])
344
+ -(?P<month>[0-9][0-9]?)
345
+ -(?P<day>[0-9][0-9]?)
346
+ (?:(?:[Tt]|[ \t]+)
347
+ (?P<hour>[0-9][0-9]?)
348
+ :(?P<minute>[0-9][0-9])
349
+ :(?P<second>[0-9][0-9])
350
+ (?:\.(?P<fraction>[0-9]*))?
351
+ (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
352
+ (?::(?P<tz_minute>[0-9][0-9]))?))?)?$""",
353
+ re.X,
354
+ )
355
+
356
+ def construct_yaml_timestamp(self, node):
357
+ value = self.construct_scalar(node)
358
+ match = self.timestamp_regexp.match(node.value)
359
+ values = match.groupdict()
360
+ year = int(values["year"])
361
+ month = int(values["month"])
362
+ day = int(values["day"])
363
+ if not values["hour"]:
364
+ return datetime.date(year, month, day)
365
+ hour = int(values["hour"])
366
+ minute = int(values["minute"])
367
+ second = int(values["second"])
368
+ fraction = 0
369
+ tzinfo = None
370
+ if values["fraction"]:
371
+ fraction = values["fraction"][:6]
372
+ while len(fraction) < 6:
373
+ fraction += "0"
374
+ fraction = int(fraction)
375
+ if values["tz_sign"]:
376
+ tz_hour = int(values["tz_hour"])
377
+ tz_minute = int(values["tz_minute"] or 0)
378
+ delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute)
379
+ if values["tz_sign"] == "-":
380
+ delta = -delta
381
+ tzinfo = datetime.timezone(delta)
382
+ elif values["tz"]:
383
+ tzinfo = datetime.timezone.utc
384
+ return datetime.datetime(
385
+ year, month, day, hour, minute, second, fraction, tzinfo=tzinfo
386
+ )
387
+
388
+ def construct_yaml_omap(self, node):
389
+ # Note: we do not check for duplicate keys, because it's too
390
+ # CPU-expensive.
391
+ omap = []
392
+ yield omap
393
+ if not isinstance(node, SequenceNode):
394
+ raise ConstructorError(
395
+ "while constructing an ordered map",
396
+ node.start_mark,
397
+ "expected a sequence, but found %s" % node.id,
398
+ node.start_mark,
399
+ )
400
+ for subnode in node.value:
401
+ if not isinstance(subnode, MappingNode):
402
+ raise ConstructorError(
403
+ "while constructing an ordered map",
404
+ node.start_mark,
405
+ "expected a mapping of length 1, but found %s" % subnode.id,
406
+ subnode.start_mark,
407
+ )
408
+ if len(subnode.value) != 1:
409
+ raise ConstructorError(
410
+ "while constructing an ordered map",
411
+ node.start_mark,
412
+ "expected a single mapping item, but found %d items"
413
+ % len(subnode.value),
414
+ subnode.start_mark,
415
+ )
416
+ key_node, value_node = subnode.value[0]
417
+ key = self.construct_object(key_node)
418
+ value = self.construct_object(value_node)
419
+ omap.append((key, value))
420
+
421
+ def construct_yaml_pairs(self, node):
422
+ # Note: the same code as `construct_yaml_omap`.
423
+ pairs = []
424
+ yield pairs
425
+ if not isinstance(node, SequenceNode):
426
+ raise ConstructorError(
427
+ "while constructing pairs",
428
+ node.start_mark,
429
+ "expected a sequence, but found %s" % node.id,
430
+ node.start_mark,
431
+ )
432
+ for subnode in node.value:
433
+ if not isinstance(subnode, MappingNode):
434
+ raise ConstructorError(
435
+ "while constructing pairs",
436
+ node.start_mark,
437
+ "expected a mapping of length 1, but found %s" % subnode.id,
438
+ subnode.start_mark,
439
+ )
440
+ if len(subnode.value) != 1:
441
+ raise ConstructorError(
442
+ "while constructing pairs",
443
+ node.start_mark,
444
+ "expected a single mapping item, but found %d items"
445
+ % len(subnode.value),
446
+ subnode.start_mark,
447
+ )
448
+ key_node, value_node = subnode.value[0]
449
+ key = self.construct_object(key_node)
450
+ value = self.construct_object(value_node)
451
+ pairs.append((key, value))
452
+
453
+ def construct_yaml_set(self, node):
454
+ data = set()
455
+ yield data
456
+ value = self.construct_mapping(node)
457
+ data.update(value)
458
+
459
+ def construct_yaml_str(self, node):
460
+ return self.construct_scalar(node)
461
+
462
+ def construct_yaml_seq(self, node):
463
+ data = []
464
+ yield data
465
+ data.extend(self.construct_sequence(node))
466
+
467
+ def construct_yaml_map(self, node):
468
+ data = {}
469
+ yield data
470
+ value = self.construct_mapping(node)
471
+ data.update(value)
472
+
473
+ def construct_yaml_object(self, node, cls):
474
+ data = cls.__new__(cls)
475
+ yield data
476
+ if hasattr(data, "__setstate__"):
477
+ state = self.construct_mapping(node, deep=True)
478
+ data.__setstate__(state)
479
+ else:
480
+ state = self.construct_mapping(node)
481
+ data.__dict__.update(state)
482
+
483
+ def construct_undefined(self, node):
484
+ raise ConstructorError(
485
+ None,
486
+ None,
487
+ "could not determine a constructor for the tag %r" % node.tag,
488
+ node.start_mark,
489
+ )
490
+
491
+
492
+ SafeConstructor.add_constructor(
493
+ "tag:yaml.org,2002:null", SafeConstructor.construct_yaml_null
494
+ )
495
+
496
+ SafeConstructor.add_constructor(
497
+ "tag:yaml.org,2002:bool", SafeConstructor.construct_yaml_bool
498
+ )
499
+
500
+ SafeConstructor.add_constructor(
501
+ "tag:yaml.org,2002:int", SafeConstructor.construct_yaml_int
502
+ )
503
+
504
+ SafeConstructor.add_constructor(
505
+ "tag:yaml.org,2002:float", SafeConstructor.construct_yaml_float
506
+ )
507
+
508
+ SafeConstructor.add_constructor(
509
+ "tag:yaml.org,2002:binary", SafeConstructor.construct_yaml_binary
510
+ )
511
+
512
+ SafeConstructor.add_constructor(
513
+ "tag:yaml.org,2002:timestamp", SafeConstructor.construct_yaml_timestamp
514
+ )
515
+
516
+ SafeConstructor.add_constructor(
517
+ "tag:yaml.org,2002:omap", SafeConstructor.construct_yaml_omap
518
+ )
519
+
520
+ SafeConstructor.add_constructor(
521
+ "tag:yaml.org,2002:pairs", SafeConstructor.construct_yaml_pairs
522
+ )
523
+
524
+ SafeConstructor.add_constructor(
525
+ "tag:yaml.org,2002:set", SafeConstructor.construct_yaml_set
526
+ )
527
+
528
+ SafeConstructor.add_constructor(
529
+ "tag:yaml.org,2002:str", SafeConstructor.construct_yaml_str
530
+ )
531
+
532
+ SafeConstructor.add_constructor(
533
+ "tag:yaml.org,2002:seq", SafeConstructor.construct_yaml_seq
534
+ )
535
+
536
+ SafeConstructor.add_constructor(
537
+ "tag:yaml.org,2002:map", SafeConstructor.construct_yaml_map
538
+ )
539
+
540
+ SafeConstructor.add_constructor(None, SafeConstructor.construct_undefined)
541
+
542
+
543
+ class FullConstructor(SafeConstructor):
544
+ # 'extend' is blacklisted because it is used by
545
+ # construct_python_object_apply to add `listitems` to a newly generate
546
+ # python instance
547
+ def get_state_keys_blacklist(self):
548
+ return ["^extend$", "^__.*__$"]
549
+
550
+ def get_state_keys_blacklist_regexp(self):
551
+ if not hasattr(self, "state_keys_blacklist_regexp"):
552
+ self.state_keys_blacklist_regexp = re.compile(
553
+ "(" + "|".join(self.get_state_keys_blacklist()) + ")"
554
+ )
555
+ return self.state_keys_blacklist_regexp
556
+
557
+ def construct_python_str(self, node):
558
+ return self.construct_scalar(node)
559
+
560
+ def construct_python_unicode(self, node):
561
+ return self.construct_scalar(node)
562
+
563
+ def construct_python_bytes(self, node):
564
+ try:
565
+ value = self.construct_scalar(node).encode("ascii")
566
+ except UnicodeEncodeError as exc:
567
+ raise ConstructorError(
568
+ None,
569
+ None,
570
+ "failed to convert base64 data into ascii: %s" % exc,
571
+ node.start_mark,
572
+ )
573
+ try:
574
+ if hasattr(base64, "decodebytes"):
575
+ return base64.decodebytes(value)
576
+ else:
577
+ return base64.decodestring(value)
578
+ except binascii.Error as exc:
579
+ raise ConstructorError(
580
+ None, None, "failed to decode base64 data: %s" % exc, node.start_mark
581
+ )
582
+
583
+ def construct_python_long(self, node):
584
+ return self.construct_yaml_int(node)
585
+
586
+ def construct_python_complex(self, node):
587
+ return complex(self.construct_scalar(node))
588
+
589
+ def construct_python_tuple(self, node):
590
+ return tuple(self.construct_sequence(node))
591
+
592
+ def find_python_module(self, name, mark, unsafe=False):
593
+ if not name:
594
+ raise ConstructorError(
595
+ "while constructing a Python module",
596
+ mark,
597
+ "expected non-empty name appended to the tag",
598
+ mark,
599
+ )
600
+ if unsafe:
601
+ try:
602
+ __import__(name)
603
+ except ImportError as exc:
604
+ raise ConstructorError(
605
+ "while constructing a Python module",
606
+ mark,
607
+ "cannot find module %r (%s)" % (name, exc),
608
+ mark,
609
+ )
610
+ if name not in sys.modules:
611
+ raise ConstructorError(
612
+ "while constructing a Python module",
613
+ mark,
614
+ "module %r is not imported" % name,
615
+ mark,
616
+ )
617
+ return sys.modules[name]
618
+
619
+ def find_python_name(self, name, mark, unsafe=False):
620
+ if not name:
621
+ raise ConstructorError(
622
+ "while constructing a Python object",
623
+ mark,
624
+ "expected non-empty name appended to the tag",
625
+ mark,
626
+ )
627
+ if "." in name:
628
+ module_name, object_name = name.rsplit(".", 1)
629
+ else:
630
+ module_name = "builtins"
631
+ object_name = name
632
+ if unsafe:
633
+ try:
634
+ __import__(module_name)
635
+ except ImportError as exc:
636
+ raise ConstructorError(
637
+ "while constructing a Python object",
638
+ mark,
639
+ "cannot find module %r (%s)" % (module_name, exc),
640
+ mark,
641
+ )
642
+ if module_name not in sys.modules:
643
+ raise ConstructorError(
644
+ "while constructing a Python object",
645
+ mark,
646
+ "module %r is not imported" % module_name,
647
+ mark,
648
+ )
649
+ module = sys.modules[module_name]
650
+ if not hasattr(module, object_name):
651
+ raise ConstructorError(
652
+ "while constructing a Python object",
653
+ mark,
654
+ "cannot find %r in the module %r" % (object_name, module.__name__),
655
+ mark,
656
+ )
657
+ return getattr(module, object_name)
658
+
659
+ def construct_python_name(self, suffix, node):
660
+ value = self.construct_scalar(node)
661
+ if value:
662
+ raise ConstructorError(
663
+ "while constructing a Python name",
664
+ node.start_mark,
665
+ "expected the empty value, but found %r" % value,
666
+ node.start_mark,
667
+ )
668
+ return self.find_python_name(suffix, node.start_mark)
669
+
670
+ def construct_python_module(self, suffix, node):
671
+ value = self.construct_scalar(node)
672
+ if value:
673
+ raise ConstructorError(
674
+ "while constructing a Python module",
675
+ node.start_mark,
676
+ "expected the empty value, but found %r" % value,
677
+ node.start_mark,
678
+ )
679
+ return self.find_python_module(suffix, node.start_mark)
680
+
681
+ def make_python_instance(
682
+ self, suffix, node, args=None, kwds=None, newobj=False, unsafe=False
683
+ ):
684
+ if not args:
685
+ args = []
686
+ if not kwds:
687
+ kwds = {}
688
+ cls = self.find_python_name(suffix, node.start_mark)
689
+ if not (unsafe or isinstance(cls, type)):
690
+ raise ConstructorError(
691
+ "while constructing a Python instance",
692
+ node.start_mark,
693
+ "expected a class, but found %r" % type(cls),
694
+ node.start_mark,
695
+ )
696
+ if newobj and isinstance(cls, type):
697
+ return cls.__new__(cls, *args, **kwds)
698
+ else:
699
+ return cls(*args, **kwds)
700
+
701
+ def set_python_instance_state(self, instance, state, unsafe=False):
702
+ if hasattr(instance, "__setstate__"):
703
+ instance.__setstate__(state)
704
+ else:
705
+ slotstate = {}
706
+ if isinstance(state, tuple) and len(state) == 2:
707
+ state, slotstate = state
708
+ if hasattr(instance, "__dict__"):
709
+ if not unsafe and state:
710
+ for key in state.keys():
711
+ self.check_state_key(key)
712
+ instance.__dict__.update(state)
713
+ elif state:
714
+ slotstate.update(state)
715
+ for key, value in slotstate.items():
716
+ if not unsafe:
717
+ self.check_state_key(key)
718
+ setattr(instance, key, value)
719
+
720
+ def construct_python_object(self, suffix, node):
721
+ # Format:
722
+ # !!python/object:module.name { ... state ... }
723
+ instance = self.make_python_instance(suffix, node, newobj=True)
724
+ yield instance
725
+ deep = hasattr(instance, "__setstate__")
726
+ state = self.construct_mapping(node, deep=deep)
727
+ self.set_python_instance_state(instance, state)
728
+
729
+ def construct_python_object_apply(self, suffix, node, newobj=False):
730
+ # Format:
731
+ # !!python/object/apply # (or !!python/object/new)
732
+ # args: [ ... arguments ... ]
733
+ # kwds: { ... keywords ... }
734
+ # state: ... state ...
735
+ # listitems: [ ... listitems ... ]
736
+ # dictitems: { ... dictitems ... }
737
+ # or short format:
738
+ # !!python/object/apply [ ... arguments ... ]
739
+ # The difference between !!python/object/apply and !!python/object/new
740
+ # is how an object is created, check make_python_instance for details.
741
+ if isinstance(node, SequenceNode):
742
+ args = self.construct_sequence(node, deep=True)
743
+ kwds = {}
744
+ state = {}
745
+ listitems = []
746
+ dictitems = {}
747
+ else:
748
+ value = self.construct_mapping(node, deep=True)
749
+ args = value.get("args", [])
750
+ kwds = value.get("kwds", {})
751
+ state = value.get("state", {})
752
+ listitems = value.get("listitems", [])
753
+ dictitems = value.get("dictitems", {})
754
+ instance = self.make_python_instance(suffix, node, args, kwds, newobj)
755
+ if state:
756
+ self.set_python_instance_state(instance, state)
757
+ if listitems:
758
+ instance.extend(listitems)
759
+ if dictitems:
760
+ for key in dictitems:
761
+ instance[key] = dictitems[key]
762
+ return instance
763
+
764
+ def construct_python_object_new(self, suffix, node):
765
+ return self.construct_python_object_apply(suffix, node, newobj=True)
766
+
767
+
768
+ FullConstructor.add_constructor(
769
+ "tag:yaml.org,2002:python/none", FullConstructor.construct_yaml_null
770
+ )
771
+
772
+ FullConstructor.add_constructor(
773
+ "tag:yaml.org,2002:python/bool", FullConstructor.construct_yaml_bool
774
+ )
775
+
776
+ FullConstructor.add_constructor(
777
+ "tag:yaml.org,2002:python/str", FullConstructor.construct_python_str
778
+ )
779
+
780
+ FullConstructor.add_constructor(
781
+ "tag:yaml.org,2002:python/unicode", FullConstructor.construct_python_unicode
782
+ )
783
+
784
+ FullConstructor.add_constructor(
785
+ "tag:yaml.org,2002:python/bytes", FullConstructor.construct_python_bytes
786
+ )
787
+
788
+ FullConstructor.add_constructor(
789
+ "tag:yaml.org,2002:python/int", FullConstructor.construct_yaml_int
790
+ )
791
+
792
+ FullConstructor.add_constructor(
793
+ "tag:yaml.org,2002:python/long", FullConstructor.construct_python_long
794
+ )
795
+
796
+ FullConstructor.add_constructor(
797
+ "tag:yaml.org,2002:python/float", FullConstructor.construct_yaml_float
798
+ )
799
+
800
+ FullConstructor.add_constructor(
801
+ "tag:yaml.org,2002:python/complex", FullConstructor.construct_python_complex
802
+ )
803
+
804
+ FullConstructor.add_constructor(
805
+ "tag:yaml.org,2002:python/list", FullConstructor.construct_yaml_seq
806
+ )
807
+
808
+ FullConstructor.add_constructor(
809
+ "tag:yaml.org,2002:python/tuple", FullConstructor.construct_python_tuple
810
+ )
811
+
812
+ FullConstructor.add_constructor(
813
+ "tag:yaml.org,2002:python/dict", FullConstructor.construct_yaml_map
814
+ )
815
+
816
+ FullConstructor.add_multi_constructor(
817
+ "tag:yaml.org,2002:python/name:", FullConstructor.construct_python_name
818
+ )
819
+
820
+
821
+ class UnsafeConstructor(FullConstructor):
822
+ def find_python_module(self, name, mark):
823
+ return super(UnsafeConstructor, self).find_python_module(
824
+ name, mark, unsafe=True
825
+ )
826
+
827
+ def find_python_name(self, name, mark):
828
+ return super(UnsafeConstructor, self).find_python_name(name, mark, unsafe=True)
829
+
830
+ def make_python_instance(self, suffix, node, args=None, kwds=None, newobj=False):
831
+ return super(UnsafeConstructor, self).make_python_instance(
832
+ suffix, node, args, kwds, newobj, unsafe=True
833
+ )
834
+
835
+ def set_python_instance_state(self, instance, state):
836
+ return super(UnsafeConstructor, self).set_python_instance_state(
837
+ instance, state, unsafe=True
838
+ )
839
+
840
+
841
+ UnsafeConstructor.add_multi_constructor(
842
+ "tag:yaml.org,2002:python/module:", UnsafeConstructor.construct_python_module
843
+ )
844
+
845
+ UnsafeConstructor.add_multi_constructor(
846
+ "tag:yaml.org,2002:python/object:", UnsafeConstructor.construct_python_object
847
+ )
848
+
849
+ UnsafeConstructor.add_multi_constructor(
850
+ "tag:yaml.org,2002:python/object/new:",
851
+ UnsafeConstructor.construct_python_object_new,
852
+ )
853
+
854
+ UnsafeConstructor.add_multi_constructor(
855
+ "tag:yaml.org,2002:python/object/apply:",
856
+ UnsafeConstructor.construct_python_object_apply,
857
+ )
858
+
859
+ # Constructor is same as UnsafeConstructor. Need to leave this in place in case
860
+ # people have extended it directly.
861
+ class Constructor(UnsafeConstructor):
862
+ pass