Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/pyaml/tests/dump.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
| author | shellac |
|---|---|
| date | Thu, 14 May 2020 14:56:58 -0400 |
| parents | 26e78fe6e8c4 |
| children |
comparison
equal
deleted
inserted
replaced
| 1:75ca89e9b81c | 2:6af9afd405e9 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 from __future__ import unicode_literals, print_function | |
| 3 | |
| 4 import itertools as it, operator as op, functools as ft | |
| 5 from collections import Mapping, OrderedDict, namedtuple | |
| 6 import os, sys, io, yaml, unittest | |
| 7 | |
| 8 if sys.version_info.major > 2: unicode = str | |
| 9 | |
| 10 try: import pyaml | |
| 11 except ImportError: | |
| 12 sys.path.insert(1, os.path.join(__file__, *['..']*3)) | |
| 13 import pyaml | |
| 14 | |
| 15 | |
| 16 large_yaml = b''' | |
| 17 ### Default (baseline) configuration parameters. | |
| 18 ### DO NOT ever change this config, use -c commandline option instead! | |
| 19 | |
| 20 # Note that this file is YAML, so YAML types can be used here, see http://yaml.org/type/ | |
| 21 # For instance, large number can be specified as "10_000_000" or "!!float 10e6". | |
| 22 | |
| 23 source: | |
| 24 # Path or glob pattern (to match path) to backup, required | |
| 25 path: # example: /srv/backups/weekly.* | |
| 26 | |
| 27 queue: | |
| 28 # Path to intermediate backup queue-file (list of paths to upload), required | |
| 29 path: # example: /srv/backups/queue.txt | |
| 30 # Don't rebuild queue-file if it's newer than source.path | |
| 31 check_mtime: true | |
| 32 | |
| 33 entry_cache: | |
| 34 # Path to persistent db (sqlite) of remote directory nodes, required | |
| 35 path: # example: /srv/backups/dentries.sqlite | |
| 36 | |
| 37 # How to pick a path among those matched by "path" glob | |
| 38 pick_policy: alphasort_last # only one supported | |
| 39 | |
| 40 | |
| 41 destination: | |
| 42 # URL of Tahoe-LAFS node webapi | |
| 43 url: http://localhost:3456/uri | |
| 44 | |
| 45 result: # what to do with a cap (URI) of a resulting tree (with full backup) | |
| 46 print_to_stdout: true | |
| 47 # Append the entry to the specified file (creating it, if doesn't exists) | |
| 48 # Example entry: "2012-10-10T23:12:43.904543 /srv/backups/weekly.2012-10-10 URI:DIR2-CHK:..." | |
| 49 append_to_file: # example: /srv/backups/lafs_caps | |
| 50 # Append the entry to specified tahoe-lafs directory (i.e. put it into that dir) | |
| 51 append_to_lafs_dir: # example: URI:DIR2:... | |
| 52 | |
| 53 encoding: | |
| 54 xz: | |
| 55 enabled: true | |
| 56 options: # see lzma.LZMAOptions, empty = module defaults | |
| 57 min_size: 5120 # don't compress files smaller than 5 KiB (unless overidden in "path_filter") | |
| 58 path_filter: | |
| 59 # List of include/exclude regexp path-rules, similar to "filter" section below. | |
| 60 # Same as with "filter", rules can be tuples with '+' or '-' (implied for strings) as first element. | |
| 61 # '+' will indicate that file is compressible, if it's size >= "min_size" option. | |
| 62 # Unlike "filter", first element of rule-tuple can also be a number, | |
| 63 # overriding "min_size" parameter for matched (by that rule) paths. | |
| 64 # If none of the patterns match path, file is handled as if it was matched by '+' rule. | |
| 65 | |
| 66 - '\.(gz|bz2|t[gb]z2?|xz|lzma|7z|zip|rar)$' | |
| 67 - '\.(rpm|deb|iso)$' | |
| 68 - '\.(jpe?g|gif|png|mov|avi|ogg|mkv|webm|mp[34g]|flv|flac|ape|pdf|djvu)$' | |
| 69 - '\.(sqlite3?|fossil|fsl)$' | |
| 70 - '\.git/objects/[0-9a-f]+/[0-9a-f]+$' | |
| 71 # - [500, '\.(txt|csv|log|md|rst|cat|(ba|z|k|c|fi)?sh|env)$'] | |
| 72 # - [500, '\.(cgi|py|p[lm]|php|c|h|[ce]l|lisp|hs|patch|diff|xml|xsl|css|x?html[45]?|js)$'] | |
| 73 # - [500, '\.(co?nf|cfg?|li?st|ini|ya?ml|jso?n|vg|tab)(\.(sample|default|\w+-new))?$'] | |
| 74 # - [500, '\.(unit|service|taget|mount|desktop|rules|rc|menu)$'] | |
| 75 # - [2000, '^/etc/'] | |
| 76 | |
| 77 | |
| 78 http: | |
| 79 request_pool_options: | |
| 80 maxPersistentPerHost: 10 | |
| 81 cachedConnectionTimeout: 600 | |
| 82 retryAutomatically: true | |
| 83 ca_certs_files: /etc/ssl/certs/ca-certificates.crt # can be a list | |
| 84 debug_requests: false # insecure! logs will contain tahoe caps | |
| 85 | |
| 86 | |
| 87 filter: | |
| 88 # Either tuples like "[action ('+' or '-'), regexp]" or just exclude-patterns (python | |
| 89 # regexps) to match relative (to source.path, starting with "/") paths to backup. | |
| 90 # Patterns are matched against each path in order they're listed here. | |
| 91 # Leaf directories are matched with the trailing slash | |
| 92 # (as with rsync) to be distinguishable from files with the same name. | |
| 93 # If path doesn't match any regexp on the list, it will be included. | |
| 94 # | |
| 95 # Examples: | |
| 96 # - ['+', '/\.git/config$'] # backup git repository config files | |
| 97 # - '/\.git/' # *don't* backup any repository objects | |
| 98 # - ['-', '/\.git/'] # exactly same thing as above (redundant) | |
| 99 # - '/(?i)\.?svn(/.*|ignore)$' # exclude (case-insensitive) svn (or .svn) paths and ignore-lists | |
| 100 | |
| 101 - '/(CVS|RCS|SCCS|_darcs|\{arch\})/$' | |
| 102 - '/\.(git|hg|bzr|svn|cvs)(/|ignore|attributes|tags)?$' | |
| 103 - '/=(RELEASE-ID|meta-update|update)$' | |
| 104 | |
| 105 | |
| 106 operation: | |
| 107 queue_only: false # only generate upload queue file, don't upload anything | |
| 108 reuse_queue: false # don't generate upload queue file, use existing one as-is | |
| 109 disable_deduplication: false # make no effort to de-duplicate data (should still work on tahoe-level for files) | |
| 110 | |
| 111 # Rate limiting might be useful to avoid excessive cpu/net usage on nodes, | |
| 112 # and especially when uploading to rate-limited api's (like free cloud storages). | |
| 113 # Only used when uploading objects to the grid, not when building queue file. | |
| 114 # Format of each value is "interval[:burst]", where "interval" can be specified as rate (e.g. "1/3e5"). | |
| 115 # Simple token bucket algorithm is used. Empty values mean "no limit". | |
| 116 # Examples: | |
| 117 # "objects: 1/10:50" - 10 objects per second, up to 50 at once (if rate was lower before). | |
| 118 # "objects: 0.1:50" - same as above. | |
| 119 # "objects: 10:20" - 1 object in 10 seconds, up to 20 at once. | |
| 120 # "objects: 5" - make interval between object uploads equal 5 seconds. | |
| 121 # "bytes: 1/3e6:50e6" - 3 MB/s max, up to 50 MB/s if connection was underutilized before. | |
| 122 rate_limit: | |
| 123 bytes: # limit on rate of *file* bytes upload, example: 1/3e5:20e6 | |
| 124 objects: # limit on rate of uploaded objects, example: 10:50 | |
| 125 | |
| 126 | |
| 127 logging: # see http://docs.python.org/library/logging.config.html | |
| 128 # "custom" level means WARNING/DEBUG/NOISE, depending on CLI options | |
| 129 warnings: true # capture python warnings | |
| 130 sql_queries: false # log executed sqlite queries (very noisy, caps will be there) | |
| 131 | |
| 132 version: 1 | |
| 133 formatters: | |
| 134 basic: | |
| 135 format: '%(asctime)s :: %(name)s :: %(levelname)s: %(message)s' | |
| 136 datefmt: '%Y-%m-%d %H:%M:%S' | |
| 137 handlers: | |
| 138 console: | |
| 139 class: logging.StreamHandler | |
| 140 stream: ext://sys.stderr | |
| 141 formatter: basic | |
| 142 level: custom | |
| 143 debug_logfile: | |
| 144 class: logging.handlers.RotatingFileHandler | |
| 145 filename: /srv/backups/debug.log | |
| 146 formatter: basic | |
| 147 encoding: utf-8 | |
| 148 maxBytes: 5242880 # 5 MiB | |
| 149 backupCount: 2 | |
| 150 level: NOISE | |
| 151 loggers: | |
| 152 twisted: | |
| 153 handlers: [console] | |
| 154 level: 0 | |
| 155 root: | |
| 156 level: custom | |
| 157 handlers: [console] | |
| 158 ''' | |
| 159 | |
| 160 data = dict( | |
| 161 path='/some/path', | |
| 162 query_dump=OrderedDict([ | |
| 163 ('key1', 'тест1'), | |
| 164 ('key2', 'тест2'), | |
| 165 ('key3', 'тест3'), | |
| 166 ('последний', None) ]), | |
| 167 ids=OrderedDict(), | |
| 168 a=[1,None,'asd', 'не-ascii'], b=3.5, c=None, | |
| 169 asd=OrderedDict([('b', 1), ('a', 2)]) ) | |
| 170 data['query_dump_clone'] = data['query_dump'] | |
| 171 data['ids']['id в уникоде'] = [4, 5, 6] | |
| 172 data['ids']['id2 в уникоде'] = data['ids']['id в уникоде'] | |
| 173 # data["'asd'\n!\0\1"] =OrderedDict([('b', 1), ('a', 2)]) <-- fails in many ways | |
| 174 | |
| 175 data_str_multiline = dict(cert=( | |
| 176 '-----BEGIN CERTIFICATE-----\n' | |
| 177 'MIIDUjCCAjoCCQD0/aLLkLY/QDANBgkqhkiG9w0BAQUFADBqMRAwDgYDVQQKFAdm\n' | |
| 178 'Z19jb3JlMRYwFAYDVQQHEw1ZZWthdGVyaW5idXJnMR0wGwYDVQQIExRTdmVyZGxv\n' | |
| 179 'dnNrYXlhIG9ibGFzdDELMAkGA1UEBhMCUlUxEjAQBgNVBAMTCWxvY2FsaG9zdDAg\n' | |
| 180 'Fw0xMzA0MjQwODUxMTRaGA8yMDUzMDQxNDA4NTExNFowajEQMA4GA1UEChQHZmdf\n' | |
| 181 'Y29yZTEWMBQGA1UEBxMNWWVrYXRlcmluYnVyZzEdMBsGA1UECBMUU3ZlcmRsb3Zz\n' | |
| 182 'a2F5YSBvYmxhc3QxCzAJBgNVBAYTAlJVMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEi\n' | |
| 183 'MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnZr3jbhfb5bUhORhmXOXOml8N\n' | |
| 184 'fAli/ak6Yv+LRBtmOjke2gFybPZFuXYr0lYGQ4KgarN904vEg7WUbSlwwJuszJxQ\n' | |
| 185 'Lz3xSDqQDqF74m1XeBYywZQIywKIbA/rfop3qiMeDWo3WavYp2kaxW28Xd/ZcsTd\n' | |
| 186 'bN/eRo+Ft1bor1VPiQbkQKaOOi6K8M9a/2TK1ei2MceNbw6YrlCZe09l61RajCiz\n' | |
| 187 'y5eZc96/1j436wynmqJn46hzc1gC3APjrkuYrvUNKORp8y//ye+6TX1mVbYW+M5n\n' | |
| 188 'CZsIjjm9URUXf4wsacNlCHln1nwBxUe6D4e2Hxh2Oc0cocrAipxuNAa8Afn5AgMB\n' | |
| 189 'AAEwDQYJKoZIhvcNAQEFBQADggEBADUHf1UXsiKCOYam9u3c0GRjg4V0TKkIeZWc\n' | |
| 190 'uN59JWnpa/6RBJbykiZh8AMwdTonu02g95+13g44kjlUnK3WG5vGeUTrGv+6cnAf\n' | |
| 191 '4B4XwnWTHADQxbdRLja/YXqTkZrXkd7W3Ipxdi0bDCOSi/BXSmiblyWdbNU4cHF/\n' | |
| 192 'Ex4dTWeGFiTWY2upX8sa+1PuZjk/Ry+RPMLzuamvzP20mVXmKtEIfQTzz4b8+Pom\n' | |
| 193 'T1gqPkNEbe2j1DciRNUOH1iuY+cL/b7JqZvvdQK34w3t9Cz7GtMWKo+g+ZRdh3+q\n' | |
| 194 '2sn5m3EkrUb1hSKQbMWTbnaG4C/F3i4KVkH+8AZmR9OvOmZ+7Lo=\n' | |
| 195 '-----END CERTIFICATE-----' )) | |
| 196 | |
| 197 data_str_long = dict(cert=( | |
| 198 'MIIDUjCCAjoCCQD0/aLLkLY/QDANBgkqhkiG9w0BAQUFADBqMRAwDgYDVQQKFAdm' | |
| 199 'Z19jb3JlMRYwFAYDVQQHEw1ZZWthdGVyaW5idXJnMR0wGwYDVQQIExRTdmVyZGxv' | |
| 200 'dnNrYXlhIG9ibGFzdDELMAkGA1UEBhMCUlUxEjAQBgNVBAMTCWxvY2FsaG9zdDAg' | |
| 201 'Fw0xMzA0MjQwODUxMTRaGA8yMDUzMDQxNDA4NTExNFowajEQMA4GA1UEChQHZmdf' | |
| 202 'Y29yZTEWMBQGA1UEBxMNWWVrYXRlcmluYnVyZzEdMBsGA1UECBMUU3ZlcmRsb3Zz' | |
| 203 'a2F5YSBvYmxhc3QxCzAJBgNVBAYTAlJVMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEi' | |
| 204 'MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnZr3jbhfb5bUhORhmXOXOml8N' | |
| 205 'fAli/ak6Yv+LRBtmOjke2gFybPZFuXYr0lYGQ4KgarN904vEg7WUbSlwwJuszJxQ' | |
| 206 'Lz3xSDqQDqF74m1XeBYywZQIywKIbA/rfop3qiMeDWo3WavYp2kaxW28Xd/ZcsTd' | |
| 207 'bN/eRo+Ft1bor1VPiQbkQKaOOi6K8M9a/2TK1ei2MceNbw6YrlCZe09l61RajCiz' | |
| 208 'y5eZc96/1j436wynmqJn46hzc1gC3APjrkuYrvUNKORp8y//ye+6TX1mVbYW+M5n' | |
| 209 'CZsIjjm9URUXf4wsacNlCHln1nwBxUe6D4e2Hxh2Oc0cocrAipxuNAa8Afn5AgMB' | |
| 210 'AAEwDQYJKoZIhvcNAQEFBQADggEBADUHf1UXsiKCOYam9u3c0GRjg4V0TKkIeZWc' | |
| 211 'uN59JWnpa/6RBJbykiZh8AMwdTonu02g95+13g44kjlUnK3WG5vGeUTrGv+6cnAf' | |
| 212 '4B4XwnWTHADQxbdRLja/YXqTkZrXkd7W3Ipxdi0bDCOSi/BXSmiblyWdbNU4cHF/' | |
| 213 'Ex4dTWeGFiTWY2upX8sa+1PuZjk/Ry+RPMLzuamvzP20mVXmKtEIfQTzz4b8+Pom' | |
| 214 'T1gqPkNEbe2j1DciRNUOH1iuY+cL/b7JqZvvdQK34w3t9Cz7GtMWKo+g+ZRdh3+q' | |
| 215 '2sn5m3EkrUb1hSKQbMWTbnaG4C/F3i4KVkH+8AZmR9OvOmZ+7Lo=' )) | |
| 216 | |
| 217 | |
| 218 # Restore Python2-like heterogeneous list sorting functionality in Python3 | |
| 219 # Based on https://gist.github.com/pR0Ps/1e1a1e892aad5b691448 | |
| 220 def compare(x, y): | |
| 221 if x == y: return 0 | |
| 222 try: | |
| 223 if x < y: return -1 | |
| 224 else: return 1 | |
| 225 | |
| 226 except TypeError as e: | |
| 227 # The case where both are None is taken care of by the equality test | |
| 228 if x is None: return -1 | |
| 229 elif y is None: return 1 | |
| 230 | |
| 231 if type(x) != type(y): | |
| 232 return compare(*map(lambda t: type(t).__name__, [x, y])) | |
| 233 | |
| 234 # Types are the same but a native compare didn't work. | |
| 235 # x and y might be indexable, recursively compare elements | |
| 236 for a, b in zip(x, y): | |
| 237 c = compare(a, b) | |
| 238 if c != 0: return c | |
| 239 | |
| 240 return compare(len(x), len(y)) | |
| 241 | |
| 242 | |
| 243 class DumpTests(unittest.TestCase): | |
| 244 | |
| 245 def flatten(self, data, path=tuple()): | |
| 246 dst = list() | |
| 247 if isinstance(data, (tuple, list)): | |
| 248 for v in data: | |
| 249 dst.extend(self.flatten(v, path + (list,))) | |
| 250 elif isinstance(data, Mapping): | |
| 251 for k,v in data.items(): | |
| 252 dst.extend(self.flatten(v, path + (k,))) | |
| 253 else: dst.append((path, data)) | |
| 254 return tuple(sorted(dst, key=ft.cmp_to_key(compare))) | |
| 255 | |
| 256 def test_dst(self): | |
| 257 buff = io.BytesIO() | |
| 258 self.assertIs(pyaml.dump(data, buff), None) | |
| 259 self.assertIsInstance(pyaml.dump(data, str), str) | |
| 260 self.assertIsInstance(pyaml.dump(data, unicode), unicode) | |
| 261 | |
| 262 def test_simple(self): | |
| 263 a = self.flatten(data) | |
| 264 b = pyaml.dump(data, unicode) | |
| 265 self.assertEqual(a, self.flatten(yaml.safe_load(b))) | |
| 266 | |
| 267 def test_vspacing(self): | |
| 268 data = yaml.safe_load(large_yaml) | |
| 269 a = self.flatten(data) | |
| 270 b = pyaml.dump(data, unicode, vspacing=[2, 1]) | |
| 271 self.assertEqual(a, self.flatten(yaml.safe_load(b))) | |
| 272 pos, pos_list = 0, list() | |
| 273 while True: | |
| 274 pos = b.find(u'\n', pos+1) | |
| 275 if pos < 0: break | |
| 276 pos_list.append(pos) | |
| 277 self.assertEqual( pos_list, | |
| 278 [ 12, 13, 25, 33, 53, 74, 89, 108, 158, 185, 265, 300, 345, 346, 356, 376, 400, 426, 427, | |
| 279 460, 461, 462, 470, 508, 564, 603, 604, 605, 611, 612, 665, 666, 690, 691, 715, 748, | |
| 280 777, 806, 807, 808, 817, 818, 832, 843, 878, 948, 949, 961, 974, 1009, 1032, 1052, | |
| 281 1083, 1102, 1123, 1173, 1195, 1234, 1257, 1276, 1300, 1301, 1312, 1325, 1341, 1359, | |
| 282 1374, 1375, 1383, 1397, 1413, 1431, 1432, 1453, 1454, 1467, 1468, 1485, 1486, 1487, | |
| 283 1498, 1499, 1530, 1531, 1551, 1552, 1566, 1577, 1590, 1591, 1612, 1613, 1614, 1622, | |
| 284 1623, 1638, 1648, 1649, 1657, 1658, 1688, 1689, 1698, 1720, 1730 ] ) | |
| 285 b = pyaml.dump(data, unicode) | |
| 286 self.assertNotIn('\n\n', b) | |
| 287 | |
| 288 def test_ids(self): | |
| 289 b = pyaml.dump(data, unicode) | |
| 290 self.assertNotIn('&id00', b) | |
| 291 self.assertIn('query_dump_clone: *query_dump_clone', b) | |
| 292 self.assertIn("'id в уникоде': &ids_-_id2_v_unikode", b) # kinda bug - should be just "id" | |
| 293 | |
| 294 def test_force_embed(self): | |
| 295 b = pyaml.dump(data, unicode, force_embed=True) | |
| 296 c = pyaml.dump(data, unicode, safe=True, force_embed=True) | |
| 297 for char, dump in it.product('*&', [b, c]): | |
| 298 self.assertNotIn(char, dump) | |
| 299 | |
| 300 def test_encoding(self): | |
| 301 b = pyaml.dump(data, unicode, force_embed=True) | |
| 302 b_lines = list(map(unicode.strip, b.splitlines())) | |
| 303 chk = ['query_dump:', 'key1: тест1', 'key2: тест2', 'key3: тест3', 'последний:'] | |
| 304 pos = b_lines.index('query_dump:') | |
| 305 self.assertEqual(b_lines[pos:pos + len(chk)], chk) | |
| 306 | |
| 307 def test_str_long(self): | |
| 308 b = pyaml.dump(data_str_long, unicode) | |
| 309 self.assertNotIn('"', b) | |
| 310 self.assertNotIn("'", b) | |
| 311 self.assertEqual(len(b.splitlines()), 1) | |
| 312 | |
| 313 def test_str_multiline(self): | |
| 314 b = pyaml.dump(data_str_multiline, unicode) | |
| 315 b_lines = b.splitlines() | |
| 316 self.assertGreater(len(b_lines), len(data_str_multiline['cert'].splitlines())) | |
| 317 for line in b_lines: self.assertLess(len(line), 100) | |
| 318 | |
| 319 def test_dumps(self): | |
| 320 b = pyaml.dumps(data_str_multiline) | |
| 321 self.assertIsInstance(b, bytes) | |
| 322 | |
| 323 def test_print(self): | |
| 324 self.assertIs(pyaml.print, pyaml.pprint) | |
| 325 self.assertIs(pyaml.print, pyaml.p) | |
| 326 buff = io.BytesIO() | |
| 327 b = pyaml.dump(data_str_multiline, dst=bytes) | |
| 328 pyaml.print(data_str_multiline, file=buff) | |
| 329 self.assertEqual(b, buff.getvalue()) | |
| 330 | |
| 331 def test_print_args(self): | |
| 332 buff = io.BytesIO() | |
| 333 args = 1, 2, 3 | |
| 334 b = pyaml.dump(args, dst=bytes) | |
| 335 pyaml.print(*args, file=buff) | |
| 336 self.assertEqual(b, buff.getvalue()) | |
| 337 | |
| 338 def test_str_style_pick(self): | |
| 339 a = pyaml.dump(data_str_multiline) | |
| 340 b = pyaml.dump(data_str_multiline, string_val_style='|') | |
| 341 self.assertEqual(a, b) | |
| 342 b = pyaml.dump(data_str_multiline, string_val_style='plain') | |
| 343 self.assertNotEqual(a, b) | |
| 344 self.assertTrue(pyaml.dump('waka waka', string_val_style='|').startswith('|-\n')) | |
| 345 self.assertEqual(pyaml.dump(dict(a=1), string_val_style='|'), 'a: 1\n') | |
| 346 | |
| 347 def test_colons_in_strings(self): | |
| 348 val1 = {'foo': ['bar:', 'baz', 'bar:bazzo', 'a: b'], 'foo:': 'yak:'} | |
| 349 val1_str = pyaml.dump(val1) | |
| 350 val2 = yaml.safe_load(val1_str) | |
| 351 val2_str = pyaml.dump(val2) | |
| 352 val3 = yaml.safe_load(val2_str) | |
| 353 self.assertEqual(val1, val2) | |
| 354 self.assertEqual(val1_str, val2_str) | |
| 355 self.assertEqual(val2, val3) | |
| 356 | |
| 357 def test_empty_strings(self): | |
| 358 val1 = {'key': ['', 'stuff', '', 'more'], '': 'value', 'k3': ''} | |
| 359 val1_str = pyaml.dump(val1) | |
| 360 val2 = yaml.safe_load(val1_str) | |
| 361 val2_str = pyaml.dump(val2) | |
| 362 val3 = yaml.safe_load(val2_str) | |
| 363 self.assertEqual(val1, val2) | |
| 364 self.assertEqual(val1_str, val2_str) | |
| 365 self.assertEqual(val2, val3) | |
| 366 | |
| 367 def test_single_dash_strings(self): | |
| 368 strip_seq_dash = lambda line: line.lstrip().lstrip('-').lstrip() | |
| 369 val1 = {'key': ['-', '-stuff', '- -', '- more-', 'more-', '--']} | |
| 370 val1_str = pyaml.dump(val1) | |
| 371 val2 = yaml.safe_load(val1_str) | |
| 372 val2_str = pyaml.dump(val2) | |
| 373 val3 = yaml.safe_load(val2_str) | |
| 374 self.assertEqual(val1, val2) | |
| 375 self.assertEqual(val1_str, val2_str) | |
| 376 self.assertEqual(val2, val3) | |
| 377 val1_str_lines = val1_str.splitlines() | |
| 378 self.assertEqual(strip_seq_dash(val1_str_lines[2]), '-stuff') | |
| 379 self.assertEqual(strip_seq_dash(val1_str_lines[5]), 'more-') | |
| 380 self.assertEqual(strip_seq_dash(val1_str_lines[6]), '--') | |
| 381 val1 = {'key': '-'} | |
| 382 val1_str = pyaml.dump(val1) | |
| 383 val2 = yaml.safe_load(val1_str) | |
| 384 val2_str = pyaml.dump(val2) | |
| 385 val3 = yaml.safe_load(val2_str) | |
| 386 | |
| 387 def test_namedtuple(self): | |
| 388 TestTuple = namedtuple('TestTuple', 'y x z') | |
| 389 val = TestTuple(1, 2, 3) | |
| 390 val_str = pyaml.dump(val) | |
| 391 self.assertEqual(val_str, u'y: 1\nx: 2\nz: 3\n') # namedtuple order was preserved | |
| 392 | |
| 393 def test_ordereddict(self): | |
| 394 d = OrderedDict((i, '') for i in reversed(range(10))) | |
| 395 lines = pyaml.dump(d).splitlines() | |
| 396 self.assertEqual(lines, list(reversed(sorted(lines)))) | |
| 397 | |
| 398 def test_pyyaml_params(self): | |
| 399 d = {'foo': 'lorem ipsum ' * 30} # 300+ chars | |
| 400 for w in 40, 80, 200: | |
| 401 lines = pyaml.dump(d, width=w, indent=10).splitlines() | |
| 402 for n, line in enumerate(lines, 1): | |
| 403 self.assertLess(len(line), w*1.2) | |
| 404 if n != len(lines): self.assertGreater(len(line), w*0.8) | |
| 405 | |
| 406 def test_multiple_docs(self): | |
| 407 docs = [yaml.safe_load(large_yaml), dict(a=1, b=2, c=3)] | |
| 408 docs_str = pyaml.dump_all(docs, vspacing=[3, 2]) | |
| 409 self.assertTrue(docs_str.startswith('---')) | |
| 410 self.assertIn('---\n\n\n\na: 1\n\n\n\nb: 2\n\n\n\nc: 3\n', docs_str) | |
| 411 docs_str2 = pyaml.dump(docs, vspacing=[3, 2], multiple_docs=True) | |
| 412 self.assertEqual(docs_str, docs_str2) | |
| 413 docs_str2 = pyaml.dump(docs, vspacing=[3, 2]) | |
| 414 self.assertNotEqual(docs_str, docs_str2) | |
| 415 docs_str2 = pyaml.dump_all(docs, explicit_start=False) | |
| 416 self.assertFalse(docs_str2.startswith('---')) | |
| 417 self.assertNotEqual(docs_str, docs_str2) | |
| 418 docs_str = pyaml.dump(docs, multiple_docs=True, explicit_start=False) | |
| 419 self.assertEqual(docs_str, docs_str2) | |
| 420 | |
| 421 def test_ruamel_yaml(self): | |
| 422 try: from ruamel.yaml import YAML | |
| 423 except ImportError: return unittest.skip('No ruamel.yaml module to test it') | |
| 424 data = YAML(typ='safe').load(large_yaml) | |
| 425 yaml_str = pyaml.dump(data) | |
| 426 | |
| 427 | |
| 428 if __name__ == '__main__': | |
| 429 unittest.main() | |
| 430 # print('-'*80) | |
| 431 # pyaml.dump(yaml.safe_load(large_yaml), sys.stdout) | |
| 432 # print('-'*80) | |
| 433 # pyaml.dump(data, sys.stdout) |
