outerbounds 0.3.68__py3-none-any.whl → 0.3.104__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- outerbounds/_vendor/PyYAML.LICENSE +20 -0
- outerbounds/_vendor/__init__.py +0 -0
- outerbounds/_vendor/_yaml/__init__.py +34 -0
- outerbounds/_vendor/click/__init__.py +73 -0
- outerbounds/_vendor/click/_compat.py +626 -0
- outerbounds/_vendor/click/_termui_impl.py +717 -0
- outerbounds/_vendor/click/_textwrap.py +49 -0
- outerbounds/_vendor/click/_winconsole.py +279 -0
- outerbounds/_vendor/click/core.py +2998 -0
- outerbounds/_vendor/click/decorators.py +497 -0
- outerbounds/_vendor/click/exceptions.py +287 -0
- outerbounds/_vendor/click/formatting.py +301 -0
- outerbounds/_vendor/click/globals.py +68 -0
- outerbounds/_vendor/click/parser.py +529 -0
- outerbounds/_vendor/click/py.typed +0 -0
- outerbounds/_vendor/click/shell_completion.py +580 -0
- outerbounds/_vendor/click/termui.py +787 -0
- outerbounds/_vendor/click/testing.py +479 -0
- outerbounds/_vendor/click/types.py +1073 -0
- outerbounds/_vendor/click/utils.py +580 -0
- outerbounds/_vendor/click.LICENSE +28 -0
- outerbounds/_vendor/vendor_any.txt +2 -0
- outerbounds/_vendor/yaml/__init__.py +471 -0
- outerbounds/_vendor/yaml/_yaml.cpython-311-darwin.so +0 -0
- outerbounds/_vendor/yaml/composer.py +146 -0
- outerbounds/_vendor/yaml/constructor.py +862 -0
- outerbounds/_vendor/yaml/cyaml.py +177 -0
- outerbounds/_vendor/yaml/dumper.py +138 -0
- outerbounds/_vendor/yaml/emitter.py +1239 -0
- outerbounds/_vendor/yaml/error.py +94 -0
- outerbounds/_vendor/yaml/events.py +104 -0
- outerbounds/_vendor/yaml/loader.py +62 -0
- outerbounds/_vendor/yaml/nodes.py +51 -0
- outerbounds/_vendor/yaml/parser.py +629 -0
- outerbounds/_vendor/yaml/reader.py +208 -0
- outerbounds/_vendor/yaml/representer.py +378 -0
- outerbounds/_vendor/yaml/resolver.py +245 -0
- outerbounds/_vendor/yaml/scanner.py +1555 -0
- outerbounds/_vendor/yaml/serializer.py +127 -0
- outerbounds/_vendor/yaml/tokens.py +129 -0
- outerbounds/command_groups/apps_cli.py +586 -0
- outerbounds/command_groups/cli.py +9 -5
- outerbounds/command_groups/local_setup_cli.py +1 -5
- outerbounds/command_groups/perimeters_cli.py +198 -25
- outerbounds/command_groups/tutorials_cli.py +111 -0
- outerbounds/command_groups/workstations_cli.py +2 -2
- outerbounds/utils/kubeconfig.py +2 -2
- outerbounds/utils/metaflowconfig.py +68 -9
- outerbounds/utils/schema.py +2 -2
- outerbounds/utils/utils.py +19 -0
- outerbounds/vendor.py +159 -0
- {outerbounds-0.3.68.dist-info → outerbounds-0.3.104.dist-info}/METADATA +14 -7
- outerbounds-0.3.104.dist-info/RECORD +59 -0
- {outerbounds-0.3.68.dist-info → outerbounds-0.3.104.dist-info}/WHEEL +1 -1
- outerbounds-0.3.68.dist-info/RECORD +0 -15
- {outerbounds-0.3.68.dist-info → outerbounds-0.3.104.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,208 @@
|
|
1
|
+
# This module contains abstractions for the input stream. You don't have to
|
2
|
+
# looks further, there are no pretty code.
|
3
|
+
#
|
4
|
+
# We define two classes here.
|
5
|
+
#
|
6
|
+
# Mark(source, line, column)
|
7
|
+
# It's just a record and its only use is producing nice error messages.
|
8
|
+
# Parser does not use it for any other purposes.
|
9
|
+
#
|
10
|
+
# Reader(source, data)
|
11
|
+
# Reader determines the encoding of `data` and converts it to unicode.
|
12
|
+
# Reader provides the following methods and attributes:
|
13
|
+
# reader.peek(length=1) - return the next `length` characters
|
14
|
+
# reader.forward(length=1) - move the current position to `length` characters.
|
15
|
+
# reader.index - the number of the current character.
|
16
|
+
# reader.line, stream.column - the line and the column of the current character.
|
17
|
+
|
18
|
+
__all__ = ["Reader", "ReaderError"]
|
19
|
+
|
20
|
+
from .error import YAMLError, Mark
|
21
|
+
|
22
|
+
import codecs, re
|
23
|
+
|
24
|
+
|
25
|
+
class ReaderError(YAMLError):
|
26
|
+
def __init__(self, name, position, character, encoding, reason):
|
27
|
+
self.name = name
|
28
|
+
self.character = character
|
29
|
+
self.position = position
|
30
|
+
self.encoding = encoding
|
31
|
+
self.reason = reason
|
32
|
+
|
33
|
+
def __str__(self):
|
34
|
+
if isinstance(self.character, bytes):
|
35
|
+
return (
|
36
|
+
"'%s' codec can't decode byte #x%02x: %s\n"
|
37
|
+
' in "%s", position %d'
|
38
|
+
% (
|
39
|
+
self.encoding,
|
40
|
+
ord(self.character),
|
41
|
+
self.reason,
|
42
|
+
self.name,
|
43
|
+
self.position,
|
44
|
+
)
|
45
|
+
)
|
46
|
+
else:
|
47
|
+
return "unacceptable character #x%04x: %s\n" ' in "%s", position %d' % (
|
48
|
+
self.character,
|
49
|
+
self.reason,
|
50
|
+
self.name,
|
51
|
+
self.position,
|
52
|
+
)
|
53
|
+
|
54
|
+
|
55
|
+
class Reader(object):
|
56
|
+
# Reader:
|
57
|
+
# - determines the data encoding and converts it to a unicode string,
|
58
|
+
# - checks if characters are in allowed range,
|
59
|
+
# - adds '\0' to the end.
|
60
|
+
|
61
|
+
# Reader accepts
|
62
|
+
# - a `bytes` object,
|
63
|
+
# - a `str` object,
|
64
|
+
# - a file-like object with its `read` method returning `str`,
|
65
|
+
# - a file-like object with its `read` method returning `unicode`.
|
66
|
+
|
67
|
+
# Yeah, it's ugly and slow.
|
68
|
+
|
69
|
+
def __init__(self, stream):
|
70
|
+
self.name = None
|
71
|
+
self.stream = None
|
72
|
+
self.stream_pointer = 0
|
73
|
+
self.eof = True
|
74
|
+
self.buffer = ""
|
75
|
+
self.pointer = 0
|
76
|
+
self.raw_buffer = None
|
77
|
+
self.raw_decode = None
|
78
|
+
self.encoding = None
|
79
|
+
self.index = 0
|
80
|
+
self.line = 0
|
81
|
+
self.column = 0
|
82
|
+
if isinstance(stream, str):
|
83
|
+
self.name = "<unicode string>"
|
84
|
+
self.check_printable(stream)
|
85
|
+
self.buffer = stream + "\0"
|
86
|
+
elif isinstance(stream, bytes):
|
87
|
+
self.name = "<byte string>"
|
88
|
+
self.raw_buffer = stream
|
89
|
+
self.determine_encoding()
|
90
|
+
else:
|
91
|
+
self.stream = stream
|
92
|
+
self.name = getattr(stream, "name", "<file>")
|
93
|
+
self.eof = False
|
94
|
+
self.raw_buffer = None
|
95
|
+
self.determine_encoding()
|
96
|
+
|
97
|
+
def peek(self, index=0):
|
98
|
+
try:
|
99
|
+
return self.buffer[self.pointer + index]
|
100
|
+
except IndexError:
|
101
|
+
self.update(index + 1)
|
102
|
+
return self.buffer[self.pointer + index]
|
103
|
+
|
104
|
+
def prefix(self, length=1):
|
105
|
+
if self.pointer + length >= len(self.buffer):
|
106
|
+
self.update(length)
|
107
|
+
return self.buffer[self.pointer : self.pointer + length]
|
108
|
+
|
109
|
+
def forward(self, length=1):
|
110
|
+
if self.pointer + length + 1 >= len(self.buffer):
|
111
|
+
self.update(length + 1)
|
112
|
+
while length:
|
113
|
+
ch = self.buffer[self.pointer]
|
114
|
+
self.pointer += 1
|
115
|
+
self.index += 1
|
116
|
+
if ch in "\n\x85\u2028\u2029" or (
|
117
|
+
ch == "\r" and self.buffer[self.pointer] != "\n"
|
118
|
+
):
|
119
|
+
self.line += 1
|
120
|
+
self.column = 0
|
121
|
+
elif ch != "\uFEFF":
|
122
|
+
self.column += 1
|
123
|
+
length -= 1
|
124
|
+
|
125
|
+
def get_mark(self):
|
126
|
+
if self.stream is None:
|
127
|
+
return Mark(
|
128
|
+
self.name, self.index, self.line, self.column, self.buffer, self.pointer
|
129
|
+
)
|
130
|
+
else:
|
131
|
+
return Mark(self.name, self.index, self.line, self.column, None, None)
|
132
|
+
|
133
|
+
def determine_encoding(self):
|
134
|
+
while not self.eof and (self.raw_buffer is None or len(self.raw_buffer) < 2):
|
135
|
+
self.update_raw()
|
136
|
+
if isinstance(self.raw_buffer, bytes):
|
137
|
+
if self.raw_buffer.startswith(codecs.BOM_UTF16_LE):
|
138
|
+
self.raw_decode = codecs.utf_16_le_decode
|
139
|
+
self.encoding = "utf-16-le"
|
140
|
+
elif self.raw_buffer.startswith(codecs.BOM_UTF16_BE):
|
141
|
+
self.raw_decode = codecs.utf_16_be_decode
|
142
|
+
self.encoding = "utf-16-be"
|
143
|
+
else:
|
144
|
+
self.raw_decode = codecs.utf_8_decode
|
145
|
+
self.encoding = "utf-8"
|
146
|
+
self.update(1)
|
147
|
+
|
148
|
+
NON_PRINTABLE = re.compile(
|
149
|
+
"[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010ffff]"
|
150
|
+
)
|
151
|
+
|
152
|
+
def check_printable(self, data):
|
153
|
+
match = self.NON_PRINTABLE.search(data)
|
154
|
+
if match:
|
155
|
+
character = match.group()
|
156
|
+
position = self.index + (len(self.buffer) - self.pointer) + match.start()
|
157
|
+
raise ReaderError(
|
158
|
+
self.name,
|
159
|
+
position,
|
160
|
+
ord(character),
|
161
|
+
"unicode",
|
162
|
+
"special characters are not allowed",
|
163
|
+
)
|
164
|
+
|
165
|
+
def update(self, length):
|
166
|
+
if self.raw_buffer is None:
|
167
|
+
return
|
168
|
+
self.buffer = self.buffer[self.pointer :]
|
169
|
+
self.pointer = 0
|
170
|
+
while len(self.buffer) < length:
|
171
|
+
if not self.eof:
|
172
|
+
self.update_raw()
|
173
|
+
if self.raw_decode is not None:
|
174
|
+
try:
|
175
|
+
data, converted = self.raw_decode(
|
176
|
+
self.raw_buffer, "strict", self.eof
|
177
|
+
)
|
178
|
+
except UnicodeDecodeError as exc:
|
179
|
+
character = self.raw_buffer[exc.start]
|
180
|
+
if self.stream is not None:
|
181
|
+
position = (
|
182
|
+
self.stream_pointer - len(self.raw_buffer) + exc.start
|
183
|
+
)
|
184
|
+
else:
|
185
|
+
position = exc.start
|
186
|
+
raise ReaderError(
|
187
|
+
self.name, position, character, exc.encoding, exc.reason
|
188
|
+
)
|
189
|
+
else:
|
190
|
+
data = self.raw_buffer
|
191
|
+
converted = len(data)
|
192
|
+
self.check_printable(data)
|
193
|
+
self.buffer += data
|
194
|
+
self.raw_buffer = self.raw_buffer[converted:]
|
195
|
+
if self.eof:
|
196
|
+
self.buffer += "\0"
|
197
|
+
self.raw_buffer = None
|
198
|
+
break
|
199
|
+
|
200
|
+
def update_raw(self, size=4096):
|
201
|
+
data = self.stream.read(size)
|
202
|
+
if self.raw_buffer is None:
|
203
|
+
self.raw_buffer = data
|
204
|
+
else:
|
205
|
+
self.raw_buffer += data
|
206
|
+
self.stream_pointer += len(data)
|
207
|
+
if not data:
|
208
|
+
self.eof = True
|
@@ -0,0 +1,378 @@
|
|
1
|
+
__all__ = ["BaseRepresenter", "SafeRepresenter", "Representer", "RepresenterError"]
|
2
|
+
|
3
|
+
from .error import *
|
4
|
+
from .nodes import *
|
5
|
+
|
6
|
+
import datetime, copyreg, types, base64, collections
|
7
|
+
|
8
|
+
|
9
|
+
class RepresenterError(YAMLError):
|
10
|
+
pass
|
11
|
+
|
12
|
+
|
13
|
+
class BaseRepresenter:
|
14
|
+
|
15
|
+
yaml_representers = {}
|
16
|
+
yaml_multi_representers = {}
|
17
|
+
|
18
|
+
def __init__(self, default_style=None, default_flow_style=False, sort_keys=True):
|
19
|
+
self.default_style = default_style
|
20
|
+
self.sort_keys = sort_keys
|
21
|
+
self.default_flow_style = default_flow_style
|
22
|
+
self.represented_objects = {}
|
23
|
+
self.object_keeper = []
|
24
|
+
self.alias_key = None
|
25
|
+
|
26
|
+
def represent(self, data):
|
27
|
+
node = self.represent_data(data)
|
28
|
+
self.serialize(node)
|
29
|
+
self.represented_objects = {}
|
30
|
+
self.object_keeper = []
|
31
|
+
self.alias_key = None
|
32
|
+
|
33
|
+
def represent_data(self, data):
|
34
|
+
if self.ignore_aliases(data):
|
35
|
+
self.alias_key = None
|
36
|
+
else:
|
37
|
+
self.alias_key = id(data)
|
38
|
+
if self.alias_key is not None:
|
39
|
+
if self.alias_key in self.represented_objects:
|
40
|
+
node = self.represented_objects[self.alias_key]
|
41
|
+
# if node is None:
|
42
|
+
# raise RepresenterError("recursive objects are not allowed: %r" % data)
|
43
|
+
return node
|
44
|
+
# self.represented_objects[alias_key] = None
|
45
|
+
self.object_keeper.append(data)
|
46
|
+
data_types = type(data).__mro__
|
47
|
+
if data_types[0] in self.yaml_representers:
|
48
|
+
node = self.yaml_representers[data_types[0]](self, data)
|
49
|
+
else:
|
50
|
+
for data_type in data_types:
|
51
|
+
if data_type in self.yaml_multi_representers:
|
52
|
+
node = self.yaml_multi_representers[data_type](self, data)
|
53
|
+
break
|
54
|
+
else:
|
55
|
+
if None in self.yaml_multi_representers:
|
56
|
+
node = self.yaml_multi_representers[None](self, data)
|
57
|
+
elif None in self.yaml_representers:
|
58
|
+
node = self.yaml_representers[None](self, data)
|
59
|
+
else:
|
60
|
+
node = ScalarNode(None, str(data))
|
61
|
+
# if alias_key is not None:
|
62
|
+
# self.represented_objects[alias_key] = node
|
63
|
+
return node
|
64
|
+
|
65
|
+
@classmethod
|
66
|
+
def add_representer(cls, data_type, representer):
|
67
|
+
if not "yaml_representers" in cls.__dict__:
|
68
|
+
cls.yaml_representers = cls.yaml_representers.copy()
|
69
|
+
cls.yaml_representers[data_type] = representer
|
70
|
+
|
71
|
+
@classmethod
|
72
|
+
def add_multi_representer(cls, data_type, representer):
|
73
|
+
if not "yaml_multi_representers" in cls.__dict__:
|
74
|
+
cls.yaml_multi_representers = cls.yaml_multi_representers.copy()
|
75
|
+
cls.yaml_multi_representers[data_type] = representer
|
76
|
+
|
77
|
+
def represent_scalar(self, tag, value, style=None):
|
78
|
+
if style is None:
|
79
|
+
style = self.default_style
|
80
|
+
node = ScalarNode(tag, value, style=style)
|
81
|
+
if self.alias_key is not None:
|
82
|
+
self.represented_objects[self.alias_key] = node
|
83
|
+
return node
|
84
|
+
|
85
|
+
def represent_sequence(self, tag, sequence, flow_style=None):
|
86
|
+
value = []
|
87
|
+
node = SequenceNode(tag, value, flow_style=flow_style)
|
88
|
+
if self.alias_key is not None:
|
89
|
+
self.represented_objects[self.alias_key] = node
|
90
|
+
best_style = True
|
91
|
+
for item in sequence:
|
92
|
+
node_item = self.represent_data(item)
|
93
|
+
if not (isinstance(node_item, ScalarNode) and not node_item.style):
|
94
|
+
best_style = False
|
95
|
+
value.append(node_item)
|
96
|
+
if flow_style is None:
|
97
|
+
if self.default_flow_style is not None:
|
98
|
+
node.flow_style = self.default_flow_style
|
99
|
+
else:
|
100
|
+
node.flow_style = best_style
|
101
|
+
return node
|
102
|
+
|
103
|
+
def represent_mapping(self, tag, mapping, flow_style=None):
|
104
|
+
value = []
|
105
|
+
node = MappingNode(tag, value, flow_style=flow_style)
|
106
|
+
if self.alias_key is not None:
|
107
|
+
self.represented_objects[self.alias_key] = node
|
108
|
+
best_style = True
|
109
|
+
if hasattr(mapping, "items"):
|
110
|
+
mapping = list(mapping.items())
|
111
|
+
if self.sort_keys:
|
112
|
+
try:
|
113
|
+
mapping = sorted(mapping)
|
114
|
+
except TypeError:
|
115
|
+
pass
|
116
|
+
for item_key, item_value in mapping:
|
117
|
+
node_key = self.represent_data(item_key)
|
118
|
+
node_value = self.represent_data(item_value)
|
119
|
+
if not (isinstance(node_key, ScalarNode) and not node_key.style):
|
120
|
+
best_style = False
|
121
|
+
if not (isinstance(node_value, ScalarNode) and not node_value.style):
|
122
|
+
best_style = False
|
123
|
+
value.append((node_key, node_value))
|
124
|
+
if flow_style is None:
|
125
|
+
if self.default_flow_style is not None:
|
126
|
+
node.flow_style = self.default_flow_style
|
127
|
+
else:
|
128
|
+
node.flow_style = best_style
|
129
|
+
return node
|
130
|
+
|
131
|
+
def ignore_aliases(self, data):
|
132
|
+
return False
|
133
|
+
|
134
|
+
|
135
|
+
class SafeRepresenter(BaseRepresenter):
|
136
|
+
def ignore_aliases(self, data):
|
137
|
+
if data is None:
|
138
|
+
return True
|
139
|
+
if isinstance(data, tuple) and data == ():
|
140
|
+
return True
|
141
|
+
if isinstance(data, (str, bytes, bool, int, float)):
|
142
|
+
return True
|
143
|
+
|
144
|
+
def represent_none(self, data):
|
145
|
+
return self.represent_scalar("tag:yaml.org,2002:null", "null")
|
146
|
+
|
147
|
+
def represent_str(self, data):
|
148
|
+
return self.represent_scalar("tag:yaml.org,2002:str", data)
|
149
|
+
|
150
|
+
def represent_binary(self, data):
|
151
|
+
if hasattr(base64, "encodebytes"):
|
152
|
+
data = base64.encodebytes(data).decode("ascii")
|
153
|
+
else:
|
154
|
+
data = base64.encodestring(data).decode("ascii")
|
155
|
+
return self.represent_scalar("tag:yaml.org,2002:binary", data, style="|")
|
156
|
+
|
157
|
+
def represent_bool(self, data):
|
158
|
+
if data:
|
159
|
+
value = "true"
|
160
|
+
else:
|
161
|
+
value = "false"
|
162
|
+
return self.represent_scalar("tag:yaml.org,2002:bool", value)
|
163
|
+
|
164
|
+
def represent_int(self, data):
|
165
|
+
return self.represent_scalar("tag:yaml.org,2002:int", str(data))
|
166
|
+
|
167
|
+
inf_value = 1e300
|
168
|
+
while repr(inf_value) != repr(inf_value * inf_value):
|
169
|
+
inf_value *= inf_value
|
170
|
+
|
171
|
+
def represent_float(self, data):
|
172
|
+
if data != data or (data == 0.0 and data == 1.0):
|
173
|
+
value = ".nan"
|
174
|
+
elif data == self.inf_value:
|
175
|
+
value = ".inf"
|
176
|
+
elif data == -self.inf_value:
|
177
|
+
value = "-.inf"
|
178
|
+
else:
|
179
|
+
value = repr(data).lower()
|
180
|
+
# Note that in some cases `repr(data)` represents a float number
|
181
|
+
# without the decimal parts. For instance:
|
182
|
+
# >>> repr(1e17)
|
183
|
+
# '1e17'
|
184
|
+
# Unfortunately, this is not a valid float representation according
|
185
|
+
# to the definition of the `!!float` tag. We fix this by adding
|
186
|
+
# '.0' before the 'e' symbol.
|
187
|
+
if "." not in value and "e" in value:
|
188
|
+
value = value.replace("e", ".0e", 1)
|
189
|
+
return self.represent_scalar("tag:yaml.org,2002:float", value)
|
190
|
+
|
191
|
+
def represent_list(self, data):
|
192
|
+
# pairs = (len(data) > 0 and isinstance(data, list))
|
193
|
+
# if pairs:
|
194
|
+
# for item in data:
|
195
|
+
# if not isinstance(item, tuple) or len(item) != 2:
|
196
|
+
# pairs = False
|
197
|
+
# break
|
198
|
+
# if not pairs:
|
199
|
+
return self.represent_sequence("tag:yaml.org,2002:seq", data)
|
200
|
+
|
201
|
+
# value = []
|
202
|
+
# for item_key, item_value in data:
|
203
|
+
# value.append(self.represent_mapping(u'tag:yaml.org,2002:map',
|
204
|
+
# [(item_key, item_value)]))
|
205
|
+
# return SequenceNode(u'tag:yaml.org,2002:pairs', value)
|
206
|
+
|
207
|
+
def represent_dict(self, data):
|
208
|
+
return self.represent_mapping("tag:yaml.org,2002:map", data)
|
209
|
+
|
210
|
+
def represent_set(self, data):
|
211
|
+
value = {}
|
212
|
+
for key in data:
|
213
|
+
value[key] = None
|
214
|
+
return self.represent_mapping("tag:yaml.org,2002:set", value)
|
215
|
+
|
216
|
+
def represent_date(self, data):
|
217
|
+
value = data.isoformat()
|
218
|
+
return self.represent_scalar("tag:yaml.org,2002:timestamp", value)
|
219
|
+
|
220
|
+
def represent_datetime(self, data):
|
221
|
+
value = data.isoformat(" ")
|
222
|
+
return self.represent_scalar("tag:yaml.org,2002:timestamp", value)
|
223
|
+
|
224
|
+
def represent_yaml_object(self, tag, data, cls, flow_style=None):
|
225
|
+
if hasattr(data, "__getstate__"):
|
226
|
+
state = data.__getstate__()
|
227
|
+
else:
|
228
|
+
state = data.__dict__.copy()
|
229
|
+
return self.represent_mapping(tag, state, flow_style=flow_style)
|
230
|
+
|
231
|
+
def represent_undefined(self, data):
|
232
|
+
raise RepresenterError("cannot represent an object", data)
|
233
|
+
|
234
|
+
|
235
|
+
SafeRepresenter.add_representer(type(None), SafeRepresenter.represent_none)
|
236
|
+
|
237
|
+
SafeRepresenter.add_representer(str, SafeRepresenter.represent_str)
|
238
|
+
|
239
|
+
SafeRepresenter.add_representer(bytes, SafeRepresenter.represent_binary)
|
240
|
+
|
241
|
+
SafeRepresenter.add_representer(bool, SafeRepresenter.represent_bool)
|
242
|
+
|
243
|
+
SafeRepresenter.add_representer(int, SafeRepresenter.represent_int)
|
244
|
+
|
245
|
+
SafeRepresenter.add_representer(float, SafeRepresenter.represent_float)
|
246
|
+
|
247
|
+
SafeRepresenter.add_representer(list, SafeRepresenter.represent_list)
|
248
|
+
|
249
|
+
SafeRepresenter.add_representer(tuple, SafeRepresenter.represent_list)
|
250
|
+
|
251
|
+
SafeRepresenter.add_representer(dict, SafeRepresenter.represent_dict)
|
252
|
+
|
253
|
+
SafeRepresenter.add_representer(set, SafeRepresenter.represent_set)
|
254
|
+
|
255
|
+
SafeRepresenter.add_representer(datetime.date, SafeRepresenter.represent_date)
|
256
|
+
|
257
|
+
SafeRepresenter.add_representer(datetime.datetime, SafeRepresenter.represent_datetime)
|
258
|
+
|
259
|
+
SafeRepresenter.add_representer(None, SafeRepresenter.represent_undefined)
|
260
|
+
|
261
|
+
|
262
|
+
class Representer(SafeRepresenter):
|
263
|
+
def represent_complex(self, data):
|
264
|
+
if data.imag == 0.0:
|
265
|
+
data = "%r" % data.real
|
266
|
+
elif data.real == 0.0:
|
267
|
+
data = "%rj" % data.imag
|
268
|
+
elif data.imag > 0:
|
269
|
+
data = "%r+%rj" % (data.real, data.imag)
|
270
|
+
else:
|
271
|
+
data = "%r%rj" % (data.real, data.imag)
|
272
|
+
return self.represent_scalar("tag:yaml.org,2002:python/complex", data)
|
273
|
+
|
274
|
+
def represent_tuple(self, data):
|
275
|
+
return self.represent_sequence("tag:yaml.org,2002:python/tuple", data)
|
276
|
+
|
277
|
+
def represent_name(self, data):
|
278
|
+
name = "%s.%s" % (data.__module__, data.__name__)
|
279
|
+
return self.represent_scalar("tag:yaml.org,2002:python/name:" + name, "")
|
280
|
+
|
281
|
+
def represent_module(self, data):
|
282
|
+
return self.represent_scalar(
|
283
|
+
"tag:yaml.org,2002:python/module:" + data.__name__, ""
|
284
|
+
)
|
285
|
+
|
286
|
+
def represent_object(self, data):
|
287
|
+
# We use __reduce__ API to save the data. data.__reduce__ returns
|
288
|
+
# a tuple of length 2-5:
|
289
|
+
# (function, args, state, listitems, dictitems)
|
290
|
+
|
291
|
+
# For reconstructing, we calls function(*args), then set its state,
|
292
|
+
# listitems, and dictitems if they are not None.
|
293
|
+
|
294
|
+
# A special case is when function.__name__ == '__newobj__'. In this
|
295
|
+
# case we create the object with args[0].__new__(*args).
|
296
|
+
|
297
|
+
# Another special case is when __reduce__ returns a string - we don't
|
298
|
+
# support it.
|
299
|
+
|
300
|
+
# We produce a !!python/object, !!python/object/new or
|
301
|
+
# !!python/object/apply node.
|
302
|
+
|
303
|
+
cls = type(data)
|
304
|
+
if cls in copyreg.dispatch_table:
|
305
|
+
reduce = copyreg.dispatch_table[cls](data)
|
306
|
+
elif hasattr(data, "__reduce_ex__"):
|
307
|
+
reduce = data.__reduce_ex__(2)
|
308
|
+
elif hasattr(data, "__reduce__"):
|
309
|
+
reduce = data.__reduce__()
|
310
|
+
else:
|
311
|
+
raise RepresenterError("cannot represent an object", data)
|
312
|
+
reduce = (list(reduce) + [None] * 5)[:5]
|
313
|
+
function, args, state, listitems, dictitems = reduce
|
314
|
+
args = list(args)
|
315
|
+
if state is None:
|
316
|
+
state = {}
|
317
|
+
if listitems is not None:
|
318
|
+
listitems = list(listitems)
|
319
|
+
if dictitems is not None:
|
320
|
+
dictitems = dict(dictitems)
|
321
|
+
if function.__name__ == "__newobj__":
|
322
|
+
function = args[0]
|
323
|
+
args = args[1:]
|
324
|
+
tag = "tag:yaml.org,2002:python/object/new:"
|
325
|
+
newobj = True
|
326
|
+
else:
|
327
|
+
tag = "tag:yaml.org,2002:python/object/apply:"
|
328
|
+
newobj = False
|
329
|
+
function_name = "%s.%s" % (function.__module__, function.__name__)
|
330
|
+
if (
|
331
|
+
not args
|
332
|
+
and not listitems
|
333
|
+
and not dictitems
|
334
|
+
and isinstance(state, dict)
|
335
|
+
and newobj
|
336
|
+
):
|
337
|
+
return self.represent_mapping(
|
338
|
+
"tag:yaml.org,2002:python/object:" + function_name, state
|
339
|
+
)
|
340
|
+
if not listitems and not dictitems and isinstance(state, dict) and not state:
|
341
|
+
return self.represent_sequence(tag + function_name, args)
|
342
|
+
value = {}
|
343
|
+
if args:
|
344
|
+
value["args"] = args
|
345
|
+
if state or not isinstance(state, dict):
|
346
|
+
value["state"] = state
|
347
|
+
if listitems:
|
348
|
+
value["listitems"] = listitems
|
349
|
+
if dictitems:
|
350
|
+
value["dictitems"] = dictitems
|
351
|
+
return self.represent_mapping(tag + function_name, value)
|
352
|
+
|
353
|
+
def represent_ordered_dict(self, data):
|
354
|
+
# Provide uniform representation across different Python versions.
|
355
|
+
data_type = type(data)
|
356
|
+
tag = "tag:yaml.org,2002:python/object/apply:%s.%s" % (
|
357
|
+
data_type.__module__,
|
358
|
+
data_type.__name__,
|
359
|
+
)
|
360
|
+
items = [[key, value] for key, value in data.items()]
|
361
|
+
return self.represent_sequence(tag, [items])
|
362
|
+
|
363
|
+
|
364
|
+
Representer.add_representer(complex, Representer.represent_complex)
|
365
|
+
|
366
|
+
Representer.add_representer(tuple, Representer.represent_tuple)
|
367
|
+
|
368
|
+
Representer.add_multi_representer(type, Representer.represent_name)
|
369
|
+
|
370
|
+
Representer.add_representer(collections.OrderedDict, Representer.represent_ordered_dict)
|
371
|
+
|
372
|
+
Representer.add_representer(types.FunctionType, Representer.represent_name)
|
373
|
+
|
374
|
+
Representer.add_representer(types.BuiltinFunctionType, Representer.represent_name)
|
375
|
+
|
376
|
+
Representer.add_representer(types.ModuleType, Representer.represent_module)
|
377
|
+
|
378
|
+
Representer.add_multi_representer(object, Representer.represent_object)
|