-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_yaml.txt
160 lines (104 loc) · 3.61 KB
/
test_yaml.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
YAML Marshaller
***************
>>> from cromlech.marshallers import YAMLMarshaller
>>> marshaller = YAMLMarshaller()
The `yaml` marshaller handles data as a string:
>>> marshaller.binary
False
Straightforward dump/load
=========================
Respecting the conventions set by the `marshal` and `json` native
packages, we use the `dumps` and `loads` to handle strings.
>>> data = marshaller.dumps({'test': 'this is a test'})
>>> data
'test: this is a test\n'
>>> marshaller.loads(data)
{'test': 'this is a test'}
Non-basic types
---------------
YAML can handle most of Python structures.
Our usual date/datetime test is trivial for YAML :
>>> from datetime import datetime
>>> mydatetime = datetime(2017, 12, 19, 11, 30, 25)
>>> structure = {
... 'datetime': mydatetime,
... }
>>> data = marshaller.dumps(structure)
>>> data
'datetime: 2017-12-19 11:30:25\n'
>>> marshaller.loads(data)
{'datetime': datetime.datetime(2017, 12, 19, 11, 30, 25)}
Decorator
---------
We can use the marshaller as a decorator :
>>> @marshaller.wraps
... def my_renderer():
... return {"three": 12.145}
>>> my_renderer
<function my_renderer at ...>
>>> my_renderer()
'three: 12.145\n'
>>> marshaller.loads(my_renderer())
{'three': 12.145}
Streams and files
=================
Each marshaller has 4 methods devoted to handling file or stream.
`dump` and `load` work with streams. `dump_to` and `load_from` work
with filesystem paths.
Files
-----
>>> import os
>>> path = str(getfixture('tmpdir'))
>>> filepath = os.path.join(path, 'data.yaml')
>>> struct = [1, "two", 3.00001]
>>> marshaller.dump_to(struct, filepath)
The `dump_to` method is in charge of writing the data in the file.
We can load the content of this file using the `load_from` method :
>>> marshaller.load_from(filepath)
[1, 'two', 3.00001]
We can check manually the content of the file :
>>> with open(filepath, 'r') as fd:
... fd.read()
'- 1\n- two\n- 3.00001\n'
Streams
--------
The `dump` method is in charge writing the data in the stream.
We can interpret the content of this stream using the `load` method.
We use a string stream since our marshaller handles non-binary data.
>>> from io import StringIO
>>> stream = StringIO()
>>> marshaller.dump(struct, stream)
>>> stream.getvalue()
'- 1\n- two\n- 3.00001\n'
We now return to the offset 0 of the file and we can load it:
>>> assert stream.seek(0) == 0
>>> marshaller.load(stream)
[1, 'two', 3.00001]
Concurrency and timeout
-----------------------
Concurrency is handled via a file lock. We use the cross-os `portalocker`
package.
For our test, let's simulate a lock in place :
>>> import portalocker
>>> lock = portalocker.Lock(filepath)
>>> assert lock.acquire()
When we try to write to this file, we get an `OSError` raised by our
marshaller in response of the lock timeout :
>>> import pytest
>>> with pytest.raises(IOError) as timeout:
... marshaller.dump_to(struct, filepath, timeout=0)
>>> timeout.value
OSError('Resource is busy and could not be freed.')
Once we release the problematic timeout, we can write :
>>> lock.release()
>>> marshaller.dump_to(struct, filepath, timeout=0)
The same happens with the read :
>>> assert lock.acquire()
>>> with pytest.raises(IOError) as timeout:
... marshaller.load_from(filepath, timeout=0)
>>> timeout.value
OSError('Resource is busy and could not be freed.')
>>> lock.release()
>>> assert marshaller.load_from(filepath, timeout=0) == struct
Please note that the read/write are tied by the same lock. You can't read
and write at the same time.