Пример #1
0
    def test_rename_unchanged(self):
        test_files = [
            (
                'template.txt',
                '''\
{# Delete template.txt #}
{% template_specialize_rename "template.txt" %}

{# Rename the file and the sub-directory #}
{% template_specialize_rename "subdir/subtemplate.txt", "subtemplate.txt" %}
{% template_specialize_rename "subdir", "subdir" %}
'''
            ),
            (('subdir', 'subtemplate.txt'), 'agree, "{{foo}}" is the value of "foo"')
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:

                # Destination directory exists and is non-empty
                os.mkdir(os.path.join(output_dir, 'newdir'))
                os.mkdir(os.path.join(output_dir, 'newdir', 'newsubdir'))

                main([input_dir, output_dir, '--key', 'foo', 'bar'])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            self.assertFalse(os.path.exists(os.path.join(output_dir, 'template.txt')))
            self.assertTrue(os.path.exists(os.path.join(output_dir, 'subdir')))
            with open(os.path.join(output_dir, 'subdir', 'subtemplate.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(f_output.read(), 'agree, "bar" is the value of "foo"')
Пример #2
0
    def test_unknown_environment(self):
        test_files = [
            (
                'config.config',
                '''\
env:
  values:
    a:
      a: foo
'''
            )
        ]
        with self.create_test_files(test_files) as input_dir:
            config_path = os.path.join(input_dir, 'config.config')
            for argv in [
                    ['-c', config_path, '-e', 'unknown', 'src.txt', 'dst.txt'],
                    ['-e', 'unknown', 'src.txt', 'dst.txt']
            ]:
                with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                     unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                    with self.assertRaises(SystemExit) as cm_exc:
                        main(argv)

                self.assertEqual(cm_exc.exception.code, 2)
                self.assertEqual(stdout.getvalue(), '')
                self.assertEqual(
                    stderr.getvalue(),
                    '''\
unknown environment 'unknown'
'''
                )
Пример #3
0
    def test_aws_parameter_store_error(self):
        test_files = [
            (
                'template.txt',
                '''\
{% aws_parameter_store 'some/string' %}
'''
            )
        ]

        with self.create_test_files(test_files) as input_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr, \
                 unittest_mock.patch('botocore.session') as mock_session:
                mock_session.get_session.return_value.create_client.return_value.get_parameter.side_effect = \
                    botocore.exceptions.ClientError({'Error': {'Code': 'SomeError'}}, 'GetParameter')

                with self.assertRaises(SystemExit) as cm_exc:
                    main([input_path])

            self.assertEqual(cm_exc.exception.code, 2)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(
                stderr.getvalue(),
                '''\
Failed to retrieve value "some/string" from parameter store with error: SomeError
'''
            )
Пример #4
0
    def test_keys_only(self):
        test_files = [
            (
                'template.txt',
                '''\
a.a = {{a.a}}
a.b = {{a.b}}
a.c = {{a.c}}
'''
            )
        ]
        with self.create_test_files(test_files) as input_dir, \
             self.create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main([
                    '--key', 'a', '--value', '{a: foo}',
                    '--key', 'a', '--value', '{b: bar}',
                    '--key', 'a', '--value', '{c: [3]}',
                    input_path,
                    output_path
                ])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            with open(os.path.join(output_dir, 'other.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(
                    f_output.read(),
                    '''\
a.a = foo
a.b = bar
a.c = [3]'''
                )
Пример #5
0
    def test_stdin_to_stdout(self):
        with unittest_mock.patch('sys.stdin', new=StringIO('the value of "foo" is "{{foo}}"')), \
             unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
             unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
            main(['--key', 'foo', '--value', 'bar'])

        self.assertEqual(stdout.getvalue(), 'the value of "foo" is "bar"')
        self.assertEqual(stderr.getvalue(), '')
Пример #6
0
    def test_environment_only(self):
        test_files = [
            (
                'test.config',
                '''\
env1:
  values:
    a:
      a: "foo"
      c: [1, 2]

env2:
  values:
    b:
      a: "nope"
'''
            ),
            (
                'test2.config',
                '''\
env3:
  parents: [env1]
  values:
    a:
      b: "bar"
      c: [4, 5, 3]
'''
            ),
            (
                'template.txt', '''\
a.a = {{a.a}}
a.b = {{a.b}}
a.c = {{a.c}}
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            test_path = os.path.join(input_dir, 'test.config')
            test2_path = os.path.join(input_dir, 'test2.config')
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main(['-c', test_path, '-c', test2_path, '-e', 'env3', input_path, output_path])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            with open(os.path.join(output_dir, 'other.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(
                    f_output.read(),
                    '''\
a.a = foo
a.b = bar
a.c = [4, 5, 3]
'''
                )
Пример #7
0
    def test_stdin_to_file(self):
        with self.create_test_files([]) as output_dir:
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdin', new=StringIO('the value of "foo" is "{{foo}}"')), \
                 unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main(['-', output_path, '--key', 'foo', '--value', 'bar'])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            with open(output_path, 'r', encoding='utf-8') as f_output:
                self.assertEqual(f_output.read(), 'the value of "foo" is "bar"')
Пример #8
0
    def test_file_to_stdout(self):
        test_files = [
            ('template.txt', 'the value of "foo" is "{{foo}}"')
        ]
        with self.create_test_files(test_files) as input_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main([input_path, '--key', 'foo', '--value', 'bar'])

            self.assertEqual(stdout.getvalue(), 'the value of "foo" is "bar"')
            self.assertEqual(stderr.getvalue(), '')
Пример #9
0
    def test_environment_and_keys(self):
        test_files = [
            (
                'config.config',
                '''\
env:
  values:
    a:
      a: foo
      b: bar
      c: [1]
'''
            ),
            (
                'template.txt',
                '''\
a.a = {{a.a}}
a.b = {{a.b}}
a.c = {{a.c}}
'''
            )
        ]
        with self.create_test_files(test_files) as input_dir, \
             self.create_test_files([]) as output_dir:
            config_path = os.path.join(input_dir, 'config.config')
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main([
                    '-c', config_path,
                    '-e', 'env',
                    '--key', 'a',
                    '--value', '{b: bonk}',
                    '--key', 'a',
                    '--value', '{c: [10]}',
                    '--key', 'a',
                    '--value', '{c: [12, 11]}',
                    input_path,
                    output_path
                ])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            with open(os.path.join(output_dir, 'other.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(
                    f_output.read(),
                    '''\
a.a = foo
a.b = bonk
a.c = [12, 11]'''
                )
Пример #10
0
    def test_version(self):
        for argv in [
                ['-v'],
                ['--version']
        ]:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main(argv)

            self.assertEqual(cm_exc.exception.code, 0)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), str(__version__) + '\n')
Пример #11
0
    def test_file_not_exist(self):
        with self.create_test_files([]) as input_dir, \
             self.create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main([input_path, output_path, '--key', 'foo', '--value', 'bar'])

            self.assertEqual(cm_exc.exception.code, 2)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), "[Errno 2] No such file or directory: '{0}'\n".format(input_path))
            self.assertFalse(os.path.exists(input_path))
            self.assertFalse(os.path.exists(output_path))
Пример #12
0
    def test_file_to_file(self):
        test_files = [
            ('template.txt', 'the value of "foo" is "{{foo}}"')
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main([input_path, output_path, '--key', 'foo', 'bar'])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            with open(os.path.join(output_dir, 'other.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(f_output.read(), 'the value of "foo" is "bar"')
Пример #13
0
    def test_aws_parameter_store(self):
        test_files = [
            (
                'template.txt',
                '''\
{% filter tojson %}{% aws_parameter_store 'some/string' %}{% endfilter %}
{% aws_parameter_store 'some/string' %}
{% aws_parameter_store foo %}
'''
            )
        ]

        def get_parameter(**kwargs):
            return {
                'Parameter': {
                    'Value': f'{kwargs["Name"]}-{{value}}'
                }
            }

        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr, \
                 unittest_mock.patch('botocore.session') as mock_session:
                mock_session.get_session.return_value.create_client.return_value.get_parameter.side_effect = get_parameter
                main([input_path, output_path, '--key', 'foo', 'a"[bar}'])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')

            with open(output_path, 'r', encoding='utf-8') as f_output:
                self.assertEqual(
                    f_output.read(),
                    '''\
"some/string-{value}"
some/string-{value}
a"[bar}-{value}
'''
                )

            # get_parameter results should be cached between blocks.
            mock_session.get_session.return_value.create_client.return_value.assert_has_calls([
                unittest_mock.call.get_parameter(Name='some/string', WithDecryption=True),
                unittest_mock.call.get_parameter(Name='a"[bar}', WithDecryption=True)
            ])
Пример #14
0
    def test_invalid_keys_values(self):
        with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
             unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
            with self.assertRaises(SystemExit) as cm_exc:
                main(['--key', 'a', '--value', 'a: b: c'])

        self.assertEqual(cm_exc.exception.code, 2)
        self.assertEqual(stdout.getvalue(), '')
        self.assertEqual(
            stderr.getvalue(),
            '''\
mapping values are not allowed here
  in "<unicode string>", line 1, column 5:
    a: b: c
        ^
'''
        )
Пример #15
0
    def test_dir_to_dir(self):
        test_files = [
            ('template.txt', 'the value of "foo" is "{{foo}}"'),
            (('subdir', 'subtemplate.txt'), 'agree, "{{foo}}" is the value of "foo"')
        ]
        with self.create_test_files(test_files) as input_dir, \
             self.create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main([input_dir, output_dir, '--key', 'foo', '--value', 'bar'])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            with open(os.path.join(output_dir, 'template.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(f_output.read(), 'the value of "foo" is "bar"')
            with open(os.path.join(output_dir, 'subdir', 'subtemplate.txt'), 'r', encoding='utf-8') as f_output:
                self.assertEqual(f_output.read(), 'agree, "bar" is the value of "foo"')
Пример #16
0
    def test_dir_to_file(self):
        test_files = [
            (('subdir', 'template.txt'), 'the value of "foo" is "{{foo}}"'),
            ('other.txt', 'hello')
        ]
        with self.create_test_files(test_files) as input_dir:
            input_path = os.path.join(input_dir, 'subdir')
            output_path = os.path.join(input_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main([input_path, output_path, '--key', 'foo', '--value', 'bar'])

            self.assertEqual(cm_exc.exception.code, 2)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), "[Errno 17] File exists: '{0}'\n".format(output_path))
            self.assertTrue(os.path.isdir(input_path))
            self.assertTrue(os.path.isfile(output_path))
Пример #17
0
    def test_file_to_dir(self):
        test_files = [
            ('template.txt', 'the value of "foo" is "{{foo}}"')
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, '')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main([input_path, output_path, '--key', 'foo', 'bar'])

            self.assertEqual(cm_exc.exception.code, 2)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), f"{input_path}: error: [Errno 21] Is a directory: '{output_path}'\n")
            self.assertTrue(os.path.isfile(input_path))
            self.assertTrue(os.path.isdir(output_path))
Пример #18
0
    def test_rename_error_no_args(self):
        test_files = [
            (
                'template.txt',
                '''\
{% template_specialize_rename %}
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit):
                    main([input_dir, output_dir])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), f"{os.path.join(input_dir, 'template.txt')}:1: unexpected 'end of statement block'\n")
Пример #19
0
    def test_rename_error_path_invalid(self):
        test_files = [
            (
                'template.txt',
                '''\
{% template_specialize_rename '../bar.txt', 'foo.txt' %}
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit):
                    main([input_dir, output_dir])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '''\
template_specialize_rename invalid path '../bar.txt\'''')
Пример #20
0
    def test_dump(self):
        test_files = [
            (
                'config.config',
                '''\
env:
  values:
    a:
      a: foo
      b: bar
      c: [1]
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            config_path = os.path.join(input_dir, 'config.config')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main([
                        input_path,
                        output_path,
                        '-c', config_path,
                        '-e', 'env',
                        '--key', 'a', '{b: bonk}',
                        '--key', 'a', '{c: [12, 11]}',
                        '--dump'
                    ])

            self.assertEqual(cm_exc.exception.code, 0)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '''\
a:
  a: foo
  b: bonk
  c:
  - 12
  - 11
''')
Пример #21
0
    def test_invalid_keys_values(self):
        with create_test_files([]) as input_dir, \
             create_test_files([]) as output_dir:
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main([input_path, output_path, '--key', 'a', 'a: b: c'])

        self.assertEqual(cm_exc.exception.code, 2)
        self.assertEqual(stdout.getvalue(), '')
        self.assertEqual(
            stderr.getvalue(),
            '''\
mapping values are not allowed here
  in "<unicode string>", line 1, column 5:
    a: b: c
        ^
'''
        )
Пример #22
0
    def test_rename_error_name_dirname(self):
        test_files = [
            (
                'template.txt',
                '''\
{% template_specialize_rename "template.txt", '  /foo.txt' %}
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit):
                    main([input_dir, output_dir])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(
                stderr.getvalue(),
                f"{os.path.join(input_dir, 'template.txt')}: error: template_specialize_rename - invalid destination name '  /foo.txt'\n"
            )
Пример #23
0
    def test_mismatched_keys_values(self):
        for argv in [
                ['--key', 'a', 'src.txt', 'dst.txt'],
                ['--key', 'a', '--value', 'foo', '--key', 'b', 'src.txt', 'dst.txt']
        ]:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main(argv)

            self.assertEqual(cm_exc.exception.code, 2)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(
                stderr.getvalue(),
                '''\
usage: template-specialize [-h] [-c FILE] [-e ENV] [--key KEY] [--value VALUE]
                           [--dump] [-v]
                           [SRC] [DST]
template-specialize: error: mismatched keys/values
'''
            )
Пример #24
0
    def test_rename_error_dst_undefined(self):
        test_files = [
            (
                'template.txt',
                '''\
{% template_specialize_rename "template.txt", foobar %}
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit):
                    main([input_dir, output_dir])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(
                stderr.getvalue(),
                f"{os.path.join(input_dir, 'template.txt')}: error: 'foobar' is undefined\n"
            )
Пример #25
0
    def test_rename_error_not_found(self):
        test_files = [
            (
                'template.txt',
                '''\
{% template_specialize_rename 'missing.txt', 'bar.txt' %}
'''
            )
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            output_missing = os.path.join(output_dir, 'missing.txt')
            output_bar = os.path.join(output_dir, 'bar.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit):
                    main([input_dir, output_dir])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(
                stderr.getvalue(),
                f"template_specialize_rename error: [Errno 2] No such file or directory: '{output_missing}' -> '{output_bar}'"
            )
Пример #26
0
    def test_delete_directory(self):
        test_files = [
            (
                'template.txt',
                '''\
{# Delete template.txt #}
{% template_specialize_rename "template.txt" %}

{# Delete the sub-directory #}
{% template_specialize_rename "subdir" %}
'''
            ),
            (('subdir', 'subtemplate.txt'), 'agree, "{{foo}}" is the value of "foo"')
        ]
        with create_test_files(test_files) as input_dir, \
             create_test_files([]) as output_dir:
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                main([input_dir, output_dir, '--key', 'foo', 'bar'])

            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(stderr.getvalue(), '')
            self.assertFalse(os.path.exists(os.path.join(output_dir, 'template.txt')))
            self.assertFalse(os.path.exists(os.path.join(output_dir, 'subdir')))
Пример #27
0
    def test_config_errors(self):
        test_files = [
            (
                'test.config',
                '''\
env1:
  values:
    a:
      a: "env1 a.a"
    b:
      a: "env1 b.a"
    asdf1

env2:
  values:
    a: ["env2 a.0"]
    asdf2
'''
            ),
            (
                'test2.config',
                '''\
env3:
    parents: [env1, env2]
'''
            ),
            (
                'template.txt',
                '''\
a.a = {{a.a}}
b.a = {{b.a}}
'''
            )
        ]
        with self.create_test_files(test_files) as input_dir, \
             self.create_test_files([]) as output_dir:
            test_path = os.path.join(input_dir, 'test.config')
            test2_path = os.path.join(input_dir, 'test2.config')
            input_path = os.path.join(input_dir, 'template.txt')
            output_path = os.path.join(output_dir, 'other.txt')
            with unittest_mock.patch('sys.stdout', new=StringIO()) as stdout, \
                 unittest_mock.patch('sys.stderr', new=StringIO()) as stderr:
                with self.assertRaises(SystemExit) as cm_exc:
                    main([
                        '-c', test_path,
                        '-c', test2_path,
                        '-e', 'env3',
                        '--key', 'b', '--value', '[b0]',
                        input_path,
                        output_path
                    ])

            self.assertEqual(cm_exc.exception.code, 2)
            self.assertEqual(stdout.getvalue(), '')
            self.assertEqual(
                re.sub('^.+?test', 'test', stderr.getvalue(), flags=re.MULTILINE),
                '''\
while scanning a simple key
test.config", line 7, column 5
could not find expected ':'
test.config", line 9, column 1
'''
            )
            self.assertFalse(os.path.exists(output_path))