1# -*- coding: utf-8 -*-
2
3from __future__ import absolute_import, print_function, unicode_literals
4
5import os
6import unittest
7from io import StringIO
8
9import yaml
10
11from yamlinclude import YamlIncludeConstructor
12from ._internel import PYTHON_VERSION_MAYOR_MINOR, YAML_LOADERS, YAML1, YAML2, YAML_ZH_CN
13
14
15class DefaultLoaderTestCase(unittest.TestCase):
16
17    def setUp(self):
18        YamlIncludeConstructor.add_to_loader_class()
19
20    def test_no_loader_class_argument(self):
21        yml = '!include tests/data/include.d/1.yaml'
22        if yaml.__version__ >= '5.0' and PYTHON_VERSION_MAYOR_MINOR >= '3.2':
23            with self.assertWarns(yaml.YAMLLoadWarning):
24                data = yaml.load(StringIO(yml))
25        else:
26            data = yaml.load(StringIO(yml))
27        self.assertDictEqual(data, YAML1)
28
29
30class MultiLoadersTestCase(unittest.TestCase):
31
32    def setUp(self):
33        for loader_cls in YAML_LOADERS:
34            YamlIncludeConstructor.add_to_loader_class(loader_cls)
35
36    def tearDown(self):
37        for loader_class in YAML_LOADERS:
38            del loader_class.yaml_constructors[YamlIncludeConstructor.DEFAULT_TAG_NAME]
39
40    def test_include_one_in_mapping(self):
41        yml = '''
42file1: !include tests/data/include.d/1.yaml
43        '''
44        for loader_cls in YAML_LOADERS:
45            data = yaml.load(StringIO(yml), loader_cls)
46            self.assertDictEqual(data, {'file1': YAML1})
47
48    def test_include_two_in_mapping(self):
49        yml = '''
50file1: !include tests/data/include.d/1.yaml
51file2: !include tests/data/include.d/2.yaml
52        '''
53        for loader_cls in YAML_LOADERS:
54            data = yaml.load(StringIO(yml), loader_cls)
55            self.assertDictEqual(data, {
56                'file1': YAML1,
57                'file2': YAML2,
58            })
59
60    def test_include_one_in_sequence(self):
61        yml = '''
62file:
63    - !include tests/data/include.d/1.yaml
64        '''
65        for loader_cls in YAML_LOADERS:
66            data = yaml.load(StringIO(yml), loader_cls)
67            self.assertDictEqual(data, {'file': [YAML1]})
68
69    def test_include_two_in_sequence(self):
70        yml = '''
71- !include tests/data/include.d/1.yaml
72- !include tests/data/include.d/2.yaml
73        '''
74        for loader_cls in YAML_LOADERS:
75            data = yaml.load(StringIO(yml), loader_cls)
76            self.assertListEqual(data, [YAML1, YAML2])
77
78    def test_include_file_not_exists(self):
79        yml = '''
80file: !include tests/data/include.d/x.yaml
81            '''
82        if PYTHON_VERSION_MAYOR_MINOR >= '3.3':
83            err_cls = FileNotFoundError
84        else:
85            err_cls = IOError
86        for loader_cls in YAML_LOADERS:
87            with self.assertRaises(err_cls):
88                yaml.load(StringIO(yml), loader_cls)
89
90    def test_include_recursive(self):
91        yml = '''
92file: !include tests/data/0.yaml
93            '''
94        for loader_cls in YAML_LOADERS:
95            data = yaml.load(StringIO(yml), loader_cls)
96            self.assertDictEqual(data['file'], {
97                'files': [YAML1, YAML2],
98                'file1': YAML1,
99                'file2': YAML2,
100            })
101
102    def test_include_abs(self):
103        dirpath = os.path.abspath('')
104        yml = '''
105file: !include {0}/tests/data/include.d/1.yaml
106        '''.format(dirpath)
107        for loader_cls in YAML_LOADERS:
108            data = yaml.load(StringIO(yml), loader_cls)
109            self.assertDictEqual(data['file'], YAML1)
110
111    def test_include_wildcards(self):
112        ymllist = ['''
113files: !include tests/data/include.d/*.yaml
114''']
115        if PYTHON_VERSION_MAYOR_MINOR >= '3.5':
116            ymllist.extend(['''
117files: !include [tests/data/include.d/**/*.yaml, true]
118''', '''
119files: !include {pathname: tests/data/include.d/**/*.yaml, recursive: true}
120'''])
121        for loader_cls in YAML_LOADERS:
122            for yml in ymllist:
123                data = yaml.load(StringIO(yml), loader_cls)
124                self.assertListEqual(
125                    sorted(data['files'], key=lambda m: m['name']),
126                    [YAML1, YAML2]
127                )
128
129
130class JsonTestCase(unittest.TestCase):
131
132    def setUp(self):
133        for loader_cls in YAML_LOADERS:
134            YamlIncludeConstructor.add_to_loader_class(loader_cls)
135
136    def tearDown(self):
137        for loader_class in YAML_LOADERS:
138            del loader_class.yaml_constructors[YamlIncludeConstructor.DEFAULT_TAG_NAME]
139
140    def test_include_one_in_mapping(self):
141        yml = '''
142file1: !include tests/data/include.d/1.json
143        '''
144        for loader_cls in YAML_LOADERS:
145            data = yaml.load(StringIO(yml), loader_cls)
146            self.assertDictEqual(data, {'file1': YAML1})
147
148    def test_include_two_in_mapping(self):
149        yml = '''
150file1: !include tests/data/include.d/1.json
151file2: !include tests/data/include.d/2.json
152        '''
153        for loader_cls in YAML_LOADERS:
154            data = yaml.load(StringIO(yml), loader_cls)
155            self.assertDictEqual(data, {
156                'file1': YAML1,
157                'file2': YAML2,
158            })
159
160    def test_include_one_in_sequence(self):
161        yml = '''
162file:
163    - !include tests/data/include.d/1.json
164        '''
165        for loader_cls in YAML_LOADERS:
166            data = yaml.load(StringIO(yml), loader_cls)
167            self.assertDictEqual(data, {'file': [YAML1]})
168
169    def test_include_two_in_sequence(self):
170        yml = '''
171- !include tests/data/include.d/1.json
172- !include tests/data/include.d/2.json
173        '''
174        for loader_cls in YAML_LOADERS:
175            data = yaml.load(StringIO(yml), loader_cls)
176            self.assertListEqual(data, [YAML1, YAML2])
177
178    def test_include_file_not_exists(self):
179        yml = '''
180file: !include tests/data/include.d/x.json
181            '''
182        if PYTHON_VERSION_MAYOR_MINOR >= '3.3':
183            err_cls = FileNotFoundError
184        else:
185            err_cls = IOError
186        for loader_cls in YAML_LOADERS:
187            with self.assertRaises(err_cls):
188                yaml.load(StringIO(yml), loader_cls)
189
190    def test_include_abs(self):
191        dirpath = os.path.abspath('')
192        yml = '''
193file: !include {0}/tests/data/include.d/1.json
194        '''.format(dirpath)
195        for loader_cls in YAML_LOADERS:
196            data = yaml.load(StringIO(yml), loader_cls)
197            self.assertDictEqual(data['file'], YAML1)
198
199    def test_include_wildcards(self):
200        ymllist = ['''
201files: !include tests/data/include.d/*.json
202''']
203        if PYTHON_VERSION_MAYOR_MINOR >= '3.5':
204            ymllist.extend(['''
205files: !include [tests/data/include.d/**/*.json, true]
206''', '''
207files: !include {pathname: tests/data/include.d/**/*.yaml, recursive: true}
208'''])
209        for loader_cls in YAML_LOADERS:
210            for yml in ymllist:
211                data = yaml.load(StringIO(yml), loader_cls)
212                self.assertListEqual(
213                    sorted(data['files'], key=lambda m: m['name']),
214                    [YAML1, YAML2]
215                )
216
217
218
219class TomlTestCase(unittest.TestCase):
220
221    def setUp(self):
222        for loader_cls in YAML_LOADERS:
223            YamlIncludeConstructor.add_to_loader_class(loader_cls)
224
225    def tearDown(self):
226        for loader_class in YAML_LOADERS:
227            del loader_class.yaml_constructors[YamlIncludeConstructor.DEFAULT_TAG_NAME]
228
229    def test_include_one_in_mapping(self):
230        yml = '''
231file1: !include tests/data/include.d/1.toml
232        '''
233        for loader_cls in YAML_LOADERS:
234            data = yaml.load(StringIO(yml), loader_cls)
235            self.assertDictEqual(data, {'file1': YAML1})
236
237    def test_include_two_in_mapping(self):
238        yml = '''
239file1: !include tests/data/include.d/1.toml
240file2: !include tests/data/include.d/2.toml
241        '''
242        for loader_cls in YAML_LOADERS:
243            data = yaml.load(StringIO(yml), loader_cls)
244            self.assertDictEqual(data, {
245                'file1': YAML1,
246                'file2': YAML2,
247            })
248
249    def test_include_one_in_sequence(self):
250        yml = '''
251file:
252    - !include tests/data/include.d/1.toml
253        '''
254        for loader_cls in YAML_LOADERS:
255            data = yaml.load(StringIO(yml), loader_cls)
256            self.assertDictEqual(data, {'file': [YAML1]})
257
258    def test_include_two_in_sequence(self):
259        yml = '''
260- !include tests/data/include.d/1.toml
261- !include tests/data/include.d/2.toml
262        '''
263        for loader_cls in YAML_LOADERS:
264            data = yaml.load(StringIO(yml), loader_cls)
265            self.assertListEqual(data, [YAML1, YAML2])
266
267    def test_include_file_not_exists(self):
268        yml = '''
269file: !include tests/data/include.d/x.toml
270            '''
271        if PYTHON_VERSION_MAYOR_MINOR >= '3.3':
272            err_cls = FileNotFoundError
273        else:
274            err_cls = IOError
275        for loader_cls in YAML_LOADERS:
276            with self.assertRaises(err_cls):
277                yaml.load(StringIO(yml), loader_cls)
278
279    def test_include_abs(self):
280        dirpath = os.path.abspath('')
281        yml = '''
282file: !include {0}/tests/data/include.d/1.toml
283        '''.format(dirpath)
284        for loader_cls in YAML_LOADERS:
285            data = yaml.load(StringIO(yml), loader_cls)
286            self.assertDictEqual(data['file'], YAML1)
287
288    def test_include_wildcards(self):
289        ymllist = ['''
290files: !include tests/data/include.d/*.toml
291''']
292        if PYTHON_VERSION_MAYOR_MINOR >= '3.5':
293            ymllist.extend(['''
294files: !include [tests/data/include.d/**/*.toml, true]
295''', '''
296files: !include {pathname: tests/data/include.d/**/*.yaml, recursive: true}
297'''])
298        for loader_cls in YAML_LOADERS:
299            for yml in ymllist:
300                data = yaml.load(StringIO(yml), loader_cls)
301                self.assertListEqual(
302                    sorted(data['files'], key=lambda m: m['name']),
303                    [YAML1, YAML2]
304                )
305
306
307class PlainTextTestCase(unittest.TestCase):
308
309    def setUp(self):
310        YamlIncludeConstructor.add_to_loader_class()
311
312    def test_txt(self):
313        yml = 'text: !include tests/data/include.d/1.txt'
314        if yaml.__version__ >= '5.0' and PYTHON_VERSION_MAYOR_MINOR >= '3.2':
315            with self.assertWarns(yaml.YAMLLoadWarning):
316                data = yaml.load(StringIO(yml))
317        else:
318            data = yaml.load(StringIO(yml))
319        with open('tests/data/include.d/1.txt') as fp:
320            s = fp.read()
321        self.assertDictEqual(data, {'text': s})
322
323class ReaderTestCase(unittest.TestCase):
324
325    def setUp(self):
326        YamlIncludeConstructor.add_to_loader_class()
327
328    def test_txt(self):
329        yml = 'text: !include {pathname: tests/data/include.d/1.json, reader: txt}'
330        if yaml.__version__ >= '5.0' and PYTHON_VERSION_MAYOR_MINOR >= '3.2':
331            with self.assertWarns(yaml.YAMLLoadWarning):
332                data = yaml.load(StringIO(yml))
333        else:
334            data = yaml.load(StringIO(yml))
335        with open('tests/data/include.d/1.json') as fp:
336            s = fp.read()
337        self.assertDictEqual(data, {'text': s})
338
339
340if __name__ == '__main__':
341    unittest.main()
342