예제 #1
0
    def test_nested_working(self):
        config1 = Config(dict(x=1, y=[2, 3], z=dict(a=4, b=5)))
        config2 = Config(dict(w=6, y=[7], z=dict(b=8, c=9)))
        config1.merge(config2)

        compare(config1.data,
                expected=dict(x=1, w=6, y=[2, 3, 7], z=dict(a=4, b=8, c=9)))
예제 #2
0
 def test_other_to_dict(self):
     config1 = Config(1)
     config2 = Config(1)
     with ShouldRaise(type_error(
         "Cannot merge <class 'int'> with <class 'int'>"
     )):
         config1.merge(config2)
예제 #3
0
 def test_type_returns_new_object(self):
     config1 = Config((1, 2))
     config2 = Config((3, 4))
     def concat(context, source, target):
         return target + source
     config1.merge(config2, mergers={tuple: concat})
     compare(config1.data, expected=(1, 2, 3, 4))
예제 #4
0
 def test_override_type_mapping(self):
     config1 = Config([1, 2])
     config2 = Config([3, 4])
     def zipper(context, source, target):
         return zip(target, source)
     config1.merge(config2, mergers={list: zipper})
     compare(config1.data, expected=[(1, 3), (2, 4)])
예제 #5
0
 def test_supplement_type_mapping(self):
     config1 = Config({'x': (1, 2)})
     config2 = Config({'x': (3, 4)})
     def concat(context, source, target):
         return target + source
     config1.merge(config2, mergers=default_mergers+{tuple: concat})
     compare(config1.data, expected={'x': (1, 2, 3, 4)})
예제 #6
0
 def test_blank_type_mapping(self):
     config1 = Config({'foo': 'bar'})
     config2 = Config({'baz': 'bob'})
     with ShouldRaise(type_error(
         "Cannot merge <class 'dict'> with <class 'dict'>"
     )):
         config2.merge(config1, mergers={})
예제 #7
0
 def test_mapping_strings(self):
     config = Config({'x': 'old'})
     data = {'foo': 'bar'}
     config.merge(data, mapping={
         'foo': 'x'
     })
     compare(config.data, expected={'x': 'bar'})
예제 #8
0
    def test_overlay(self):
        path1 = self.dir.write('etc/myapp.yml', '''
        base: 1
        user: bad
        file: bad
        ''')

        path2 = self.dir.write('home/.myapp.yml', '''
        user: 2
        file: bad-user
        ''')

        path3 = self.dir.write('app.yml', '''
        file: 3
        ''')

        config = Config.from_file(path1)
        config.merge(Config.from_file(path2))
        config.merge(Config.from_file(path3))

        config.validate(Schema({str: int}))

        compare(config.base, expected=1)
        compare(config.user, expected=2)
        compare(config.file, expected=3)
예제 #9
0
 def test_mapping_type_conversion(self):
     config = Config({'x': 0})
     data = {'y': '1'}
     config.merge(data, mapping={
         convert(source['y'], int): target['x']
     })
     compare(config.data, expected={'x': 1})
예제 #10
0
 def test_mapping_dotted_strings(self):
     config = Config({'a': {'b': 'old'}})
     data = {'c': {'d': 'new'}}
     config.merge(data, mapping={
         'c.d': 'a.b'
     })
     compare(config.data, expected={'a': {'b': 'new'}})
예제 #11
0
 def test_mapping_with_top_level_merge(self):
     config = Config({'x': {'y': 1}})
     data = {'z': 2}
     config.merge(data, mapping={
         source: target.merge()
     })
     compare(config.data, expected={'x': {'y': 1}, 'z': 2})
예제 #12
0
 def test_list_to_dict(self):
     config1 = Config({'x': 1})
     config2 = Config([1, 2])
     with ShouldRaise(type_error(
         "Cannot merge <class 'list'> with <class 'dict'>"
     )):
         config1.merge(config2)
예제 #13
0
 def test_mapping_paths(self):
     config = Config({'x': 'old'})
     data = {'foo': 'bar'}
     config.merge(data, mapping={
         source['foo']: target['x']
     })
     compare(config.data, expected={'x': 'bar'})
예제 #14
0
    def test_mapping_extensive_conversation(self):
        config = Config({'a': 0})
        data = {'x': 2, 'y': -1}

        def best(possible):
            return max(possible.values())

        config.merge(data, mapping={
            convert(source, best): target['a']
        })

        compare(config.data, expected={'a': 2})
예제 #15
0
    def test_defaults_and_env(self):
        config = Config({'present': 'dp', 'absent': 'da'})

        environ = {'ENV_PRESENT': '1'}

        config.merge(environ, {
            convert('ENV_PRESENT', int): 'present',
            convert('ENV_ABSENT', int): 'absent',
        })

        compare(config.present, expected=1)
        compare(config.absent, expected='da')
예제 #16
0
    def test_templated(self):
        self.dir.write('etc/myapp.yml', '''
        {% set base = dict(one=1)%}
        base_template: {{ base.one }}
        base_env: {{ MYVAR }}
        file_template: bad
        file_env: bad
        ''')

        self.dir.write('app.yml', '''
        {% set local=2 %}
        file_template: {{ local }}
        file_env: {{ MYVAR }}
        ''')

        with Replace('os.environ.MYVAR', 'hello', strict=False) as r:
            env = Environment(loader=FileSystemLoader(self.dir.path))
            config = None
            context = dict(os.environ)
            for path in 'etc/myapp.yml', 'app.yml':
                text = env.get_template(path).render(context)
                layer = Config.from_text(text)
                if config is None:
                    config = layer
                else:
                    config.merge(layer)

        compare(config.base_template, expected=1)
        compare(config.base_env, expected='hello')
        compare(config.file_template, expected=2)
        compare(config.file_env, expected='hello')
예제 #17
0
 def test_stream_with_name_guess_parser(self):
     with NamedTemporaryFile(suffix='.json') as source:
         source.write(b'{"x": 1}')
         source.flush()
         source.seek(0)
         config = Config.from_stream(source)
     compare(config.x, expected=1)
예제 #18
0
    def test_explicit_extends(self):
        raise SkipTest('not yet')
        path1 = self.dir.write('base.yml', '''
        base: 1
        file: bad
        ''')

        path2 = self.dir.write('app.yml', '''
        extends: {}
        file: 2
        '''.format(path1))

        config = Config(path2)

        config.validate(Schema({
            'extends': config.merge(),
            'base': int,
            'file': int,
        }))

        compare(config.base, expected=1)
        compare(config.file, expected=2)
예제 #19
0
    def test_defaults_and_argparse(self):
        parser = ArgumentParser()
        parser.add_argument('--first-url')
        parser.add_argument('--attempts', type=int, default=2)
        parser.add_argument('--bool-a', action='store_true')
        parser.add_argument('--bool-b', action='store_false')

        args = parser.parse_args(['--first-url', 'override_url', '--bool-a'])
        compare(args.bool_b, expected=True)

        config = Config({'urls': ['default_url'], 'bool_b': False})

        config.merge(args, {
            'first_url': target['urls'].insert(0),
            'attempts': target['attempts'],
            'bool_a': target['bool_a'],
            'bool_b': target['bool_b'],
        })

        compare(config.urls, expected=['override_url', 'default_url'])
        compare(config.attempts, expected=2)
        compare(config.bool_a, expected=True)
        compare(config.bool_b, expected=True)
예제 #20
0
    def test_include_list(self):
        raise SkipTest('not yet')
        path1 = self.dir.write('other.yml', '''
        - 2
        - 3
        ''')

        path2 = self.dir.write('app.yml', '''
        root:
          - 1
          - include: {}
        '''.format(path1))

        config = Config(path2)

        config.validate(Schema({
            'include': config.merge(),
            'base': int,
            'file': int,
        }))

        compare(config.base, expected=1)
        compare(config.file, expected=2)
예제 #21
0
    def test_overlay(self, dir):
        pytest.importorskip("yaml")
        path1 = dir.write('etc/myapp.yml', '''
        base: 1
        user: bad
        file: bad
        ''')

        path2 = dir.write('home/.myapp.yml', '''
        user: 2
        file: bad-user
        ''')

        path3 = dir.write('app.yml', '''
        file: 3
        ''')

        config = Config.from_path(path1)
        config.merge(Config.from_path(path2))
        config.merge(Config.from_path(path3))

        compare(config.base, expected=1)
        compare(config.user, expected=2)
        compare(config.file, expected=3)
예제 #22
0
 def test_layered(self, dir):
     # defaults
     config = Config({
         'database': {'user': '******'},
         'special': False
     })
     # from system file:
     path = dir.write('etc/myapp.json', '{"special": true}')
     config.merge(Config.from_path(path))
     # from user file:
     path = dir.write('home/user/myapp.json', '{"database": {"password": "******"}}')
     config.merge(Config.from_path(path))
     # end result:
     compare(config.database.user, expected='foo')
     compare(config.database.password, expected='123')
     compare(config.special, expected=True)
예제 #23
0
 def test_path_with_encoding(self):
     with NamedTemporaryFile() as source:
         source.write(b'{"x": "\xa3"}')
         source.flush()
         config = Config.from_path(source.name, 'json', encoding='latin-1')
     compare(config.x, expected=u'\xa3')
예제 #24
0
 def test_path_explicit_string_parser(self):
     with NamedTemporaryFile() as source:
         source.write(b'{"x": 1}')
         source.flush()
         config = Config.from_path(source.name, 'json')
     compare(config.x, expected=1)
예제 #25
0
 def test_path_guess_parser_no_extension(self):
     with TempDirectory() as dir:
         path = dir.write('nope', b'{"x": 1}')
         with ShouldRaise(ParseError("No parser found for None")):
             Config.from_path(path)
예제 #26
0
 def test_text_missing_parser(self):
     with ShouldRaise(ParseError("No parser found for 'lolwut'")):
         Config.from_text("{'foo': 'bar'}", 'lolwut')
예제 #27
0
    source_path.rename(dest_path)


class IncomingEventHandler(FileSystemEventHandler):

    def __init__(self, dest: Path):
        self.dest = dest

    def on_created(self, event):
        source_path = Path(event.src_path)
        if source_path.name == FILENAME:
            move(source_path, self.dest)


if __name__ == "__main__":
    config = Config.from_path('config.yaml')
    source_dir = Path(config.directories.incoming).expanduser()
    dest = Path(config.directories.storage).expanduser()

    path = source_dir / FILENAME
    if path.exists():
        move(path, dest)

    event_handler = IncomingEventHandler(dest)
    observer = Observer()
    observer.schedule(event_handler, str(source_dir))
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
예제 #28
0
config = Config({
    'user': {
        'name': 'unsetname',
        'affiliation': 'unsetaffiliation',
        'style': 'double',
    },
    'reconfig': True,
    'compiler': 'none',
    'script': {
        'locations': {
            '~/.reportinator/scripts',
            '~/.config/reportinator/scripts',
            '~/AppData/Local/Programs/reportinator/scripts',
        },
    },
    'layout': {
        'locations': {
            '~/.reportinator/layouts',
            '~/.config/reportinator/layouts',
            '~/AppData/Local/Programs/reportinator/layouts',
        },
    },
    'locations': {
        '/etc/reportinator.yaml',
        '~/.reportinator/config.yaml',
        '~/.config/reportinator/config.yaml',
        '~/AppData/Local/Programs/reportinator/config.yaml',
    },
})
예제 #29
0
 def test_empty_config(self):
     config = Config()
     config.merge(Config())
     compare(config.data, expected={})
예제 #30
0
 def test_list(self):
     config = Config([1, 2])
     compare(config[0], expected=1)
     compare(config[1], expected=2)
     compare(list(config), expected=[1, 2])
예제 #31
0
 def test_list_to_list(self):
     config = Config([1, 2])
     config.merge([3, 4])
     compare(config.data, expected=[1, 2, 3, 4])
예제 #32
0
 def test_dict(self):
     config = Config(dict(x=1))
     compare(config.x, expected=1)
예제 #33
0
 def test_dict_to_dict(self):
     config = Config({'x': 1})
     config.merge({'y': 2})
     compare(config.data, expected={'x': 1, 'y': 2})
예제 #34
0
 def test_simple_type(self):
     config = Config()
     with ShouldRaise(type_error(
         "Cannot merge <class 'str'> with <class 'dict'>"
     )):
         config.merge('foo')
예제 #35
0
 def test_stream_no_name_no_parser(self):
     source = StringIO(u'{"x": 1}')
     with ShouldRaise(ParseError("No parser found for None")):
         Config.from_stream(source)
예제 #36
0
 def test_attr_access(self):
     config = Config({'foo': 'bar'})
     compare(config.foo, expected='bar')
예제 #37
0
config = Config({
    "user": {
        "name": "unsetname",
        "affiliation": "unsetaffiliation",
        "style": "double",
    },
    "reconfig": True,
    "compiler": "none",
    "script": {
        "location": cdir,
        "locations": {
            "~/.reportinator/scripts",
            "~/.config/reportinator/scripts",
            "~/AppData/Local/Programs/reportinator/scripts",
        },
    },
    "layout": {
        "location": cdir,
        "locations": {
            "~/.reportinator/layouts",
            "~/.config/reportinator/layouts",
            "~/AppData/Local/Programs/reportinator/layouts",
        },
    },
    "locations": {
        "/etc/reportinator.yaml",
        "~/.reportinator/config.yaml",
        "~/.config/reportinator/config.yaml",
        "~/AppData/Local/Programs/reportinator/config.yaml",
    },
    "location": "",
})
예제 #38
0
 def test_dict_access(self):
     config = Config({'foo': 'bar'})
     compare(config['foo'], expected='bar')
예제 #39
0
 def test_context_manager_push_deep(self):
     config = Config({'x': {'y': 'z'}})
     with config.push():
         config.data['x']['y'] = 'a'
         compare(config.x.y, expected='a')
     compare(config.x.y, expected='z')
예제 #40
0
 def test_empty(self):
     config = Config()
     compare(config.data, expected={})
예제 #41
0
 def test_text_callable_parser(self):
     config = Config.from_text("{'foo': 'bar'}", python_literal)
     compare(config.data, expected={'foo': 'bar'})
예제 #42
0
 def test_pop_without_push(self):
     config = Config({'x': 1, 'y': 2})
     with ShouldRaise(IndexError('pop from empty list')):
         config.pop()
예제 #43
0
 def test_path_guess_parser(self):
     with NamedTemporaryFile(suffix='.json') as source:
         source.write(b'{"x": 1}')
         source.flush()
         config = Config.from_path(source.name)
     compare(config.x, expected=1)
예제 #44
0
 def test_push_non_config(self):
     config = Config({'x': 1})
     compare(config.x, expected=1)
     config.push({'x': 2})
     compare(config.x, expected=2)
예제 #45
0
 def test_path_guess_parser_bad_extension(self):
     with NamedTemporaryFile(suffix='.nope') as source:
         with ShouldRaise(ParseError("No parser found for 'nope'")):
             Config.from_path(source.name)
예제 #46
0
 def test_stream_callable_parser(self):
     source = StringIO(u'{"x": 1}')
     config = Config.from_stream(source, python_literal)
     compare(config.x, expected=1)
예제 #47
0
 def test_path_explicit_callable_parser(self):
     with NamedTemporaryFile() as source:
         source.write(b'{"x": 1}')
         source.flush()
         config = Config.from_path(source.name, python_literal)
     compare(config.x, expected=1)
예제 #48
0
 def test_stream_string_parser(self):
     source = StringIO(u'{"x": 1}')
     config = Config.from_stream(source, 'json')
     compare(config.x, expected=1)
예제 #49
0
def test_fake_fs(fs):
    fs.create_file('/foo/bar.yml', contents='foo: 1\n')
    config = Config.from_path('/foo/bar.yml')
    compare(config.foo, expected=1)
예제 #50
0
 def test_non_empty_config(self):
     config = Config({'foo': 'bar'})
     config.merge(Config({'baz': 'bob'}))
     compare(config.data, {'foo': 'bar', 'baz': 'bob'})