import py import pytest from py._iniconfig import IniConfig, ParseError, __all__ as ALL from py._iniconfig import iscommentline from textwrap import dedent def pytest_generate_tests(metafunc): if 'input' in metafunc.funcargnames: for name, (input, expected) in check_tokens.items(): metafunc.addcall(id=name, funcargs={ 'input': input, 'expected': expected, }) elif hasattr(metafunc.function, 'multi'): kwargs = metafunc.function.multi.kwargs names, values = zip(*kwargs.items()) values = cartesian_product(*values) for p in values: metafunc.addcall(funcargs=dict(zip(names, p))) def cartesian_product(L,*lists): # copied from http://bit.ly/cyIXjn if not lists: for x in L: yield (x,) else: for x in L: for y in cartesian_product(lists[0],*lists[1:]): yield (x,)+y check_tokens = { 'section': ( '[section]', [(0, 'section', None, None)] ), 'value': ( 'value = 1', [(0, None, 'value', '1')] ), 'value in section': ( '[section]\nvalue=1', [(0, 'section', None, None), (1, 'section', 'value', '1')] ), 'value with continuation': ( 'names =\n Alice\n Bob', [(0, None, 'names', 'Alice\nBob')] ), 'value with aligned continuation': ( 'names = Alice\n' ' Bob', [(0, None, 'names', 'Alice\nBob')] ), 'blank line':( '[section]\n\nvalue=1', [(0, 'section', None, None), (2, 'section', 'value', '1')] ), 'comment': ( '# comment', [] ), 'comment on value': ( 'value = 1', [(0, None, 'value', '1')] ), 'comment on section': ( '[section] #comment', [(0, 'section', None, None)] ), 'comment2': ( '; comment', [] ), 'comment2 on section': ( '[section] ;comment', [(0, 'section', None, None)] ), 'pseudo section syntax in value': ( 'name = value []', [(0, None, 'name', 'value []')] ), 'assignment in value': ( 'value = x = 3', [(0, None, 'value', 'x = 3')] ), 'use of colon for name-values': ( 'name: y', [(0, None, 'name', 'y')] ), 'use of colon without space': ( 'value:y=5', [(0, None, 'value', 'y=5')] ), 'equality gets precedence': ( 'value=xyz:5', [(0, None, 'value', 'xyz:5')] ), } def parse(input): # only for testing purposes - _parse() does not use state except path ini = object.__new__(IniConfig) ini.path = "sample" return ini._parse(input.splitlines(True)) def parse_a_error(input): return py.test.raises(ParseError, parse, input) def test_tokenize(input, expected): parsed = parse(input) assert parsed == expected def test_parse_empty(): parsed = parse("") assert not parsed ini = IniConfig("sample", "") assert not ini.sections def test_ParseError(): e = ParseError("filename", 0, "hello") assert str(e) == "filename:1: hello" def test_continuation_needs_perceeding_token(): excinfo = parse_a_error(' Foo') assert excinfo.value.lineno == 0 def test_continuation_cant_be_after_section(): excinfo = parse_a_error('[section]\n Foo') assert excinfo.value.lineno == 1 def test_section_cant_be_empty(): excinfo = parse_a_error('[]') @py.test.mark.multi(line=[ '!!', ]) def test_error_on_weird_lines(line): parse_a_error(line) def test_iniconfig_from_file(tmpdir): path = tmpdir/'test.txt' path.write('[metadata]\nname=1') config = IniConfig(path=path) assert list(config.sections) == ['metadata'] config = IniConfig(path, "[diff]") assert list(config.sections) == ['diff'] py.test.raises(TypeError, "IniConfig(data=path.read())") def test_iniconfig_section_first(tmpdir): excinfo = py.test.raises(ParseError, """ IniConfig("x", data='name=1') """) assert excinfo.value.msg == "no section header defined" def test_iniconig_section_duplicate_fails(): excinfo = py.test.raises(ParseError, r""" IniConfig("x", data='[section]\n[section]') """) assert 'duplicate section' in str(excinfo.value) def test_iniconfig_duplicate_key_fails(): excinfo = py.test.raises(ParseError, r""" IniConfig("x", data='[section]\nname = Alice\nname = bob') """) assert 'duplicate name' in str(excinfo.value) def test_iniconfig_lineof(): config = IniConfig("x.ini", data= '[section]\n' 'value = 1\n' '[section2]\n' '# comment\n' 'value =2' ) assert config.lineof('missing') is None assert config.lineof('section') == 1 assert config.lineof('section2') == 3 assert config.lineof('section', 'value') == 2 assert config.lineof('section2','value') == 5 assert config['section'].lineof('value') == 2 assert config['section2'].lineof('value') == 5 def test_iniconfig_get_convert(): config= IniConfig("x", data='[section]\nint = 1\nfloat = 1.1') assert config.get('section', 'int') == '1' assert config.get('section', 'int', convert=int) == 1 def test_iniconfig_get_missing(): config= IniConfig("x", data='[section]\nint = 1\nfloat = 1.1') assert config.get('section', 'missing', default=1) == 1 assert config.get('section', 'missing') is None def test_section_get(): config = IniConfig("x", data='[section]\nvalue=1') section = config['section'] assert section.get('value', convert=int) == 1 assert section.get('value', 1) == "1" assert section.get('missing', 2) == 2 def test_missing_section(): config = IniConfig("x", data='[section]\nvalue=1') py.test.raises(KeyError,'config["other"]') def test_section_getitem(): config = IniConfig("x", data='[section]\nvalue=1') assert config['section']['value'] == '1' assert config['section']['value'] == '1' def test_section_iter(): config = IniConfig("x", data='[section]\nvalue=1') names = list(config['section']) assert names == ['value'] items = list(config['section'].items()) assert items==[('value', '1')] def test_config_iter(): config = IniConfig("x.ini", data=dedent(''' [section1] value=1 [section2] value=2 ''')) l = list(config) assert len(l) == 2 assert l[0].name == 'section1' assert l[0]['value'] == '1' assert l[1].name == 'section2' assert l[1]['value'] == '2' def test_config_contains(): config = IniConfig("x.ini", data=dedent(''' [section1] value=1 [section2] value=2 ''')) assert 'xyz' not in config assert 'section1' in config assert 'section2' in config def test_iter_file_order(): config = IniConfig("x.ini", data=""" [section2] #cpython dict ordered before section value = 1 value2 = 2 # dict ordered before value [section] a = 1 b = 2 """) l = list(config) secnames = [x.name for x in l] assert secnames == ['section2', 'section'] assert list(config['section2']) == ['value', 'value2'] assert list(config['section']) == ['a', 'b'] def test_example_pypirc(): config = IniConfig("pypirc", data=dedent(''' [distutils] index-servers = pypi other [pypi] repository: username: password: [other] repository: http://example.com/pypi username: password: ''')) distutils, pypi, other = list(config) assert distutils["index-servers"] == "pypi\nother" assert pypi['repository'] == '' assert pypi['username'] == '' assert pypi['password'] == '' assert ['repository', 'username', 'password'] == list(other) def test_api_import(): assert ALL == ['IniConfig', 'ParseError'] @pytest.mark.parametrize("line", [ "#qwe", " #qwe", ";qwe", " ;qwe", ]) def test_iscommentline_true(line): assert iscommentline(line)