import os, tempfile from nose.tools import * from mercurial import ( config, error, pycompat, ) import pytest from tortoisehg.util import wconfig import helpers def setup_module(): global _tempdir _tempdir = helpers.mktmpdir(__name__) def newrconfig(vals=None): if vals is None: vals = {} c = config.config() for k, v in isinstance(vals, dict) and vals.items() or vals: sec, it = k.split('.', 1) c.set(sec, it, v) return c def newwconfig(vals=None): if vals is None: vals = {} return wconfig.config(newrconfig(vals)) def written(c): dest = pycompat.bytesio() c.write(dest) return dest.getvalue() def writetempfile(s): fd, path = tempfile.mkstemp(dir=_tempdir) os.write(fd, s) os.close(fd) return path def with_rconfig(f): f.__test__ = True return pytest.mark.usefixtures('rconfig')(f) def with_wconfig(f): f.__test__ = True return pytest.mark.usefixtures('wconfig')(f) def with_both(f): f.__test__ = True return pytest.mark.usefixtures('both')(f) @pytest.fixture(name='wconfig') def fixture_wconfig(): if wconfig._hasiniparse: yield else: pytest.skip() @pytest.fixture(name='rconfig') def fixture_rconfig(): orighasiniparse = wconfig._hasiniparse wconfig._hasiniparse = False try: yield finally: wconfig._hasiniparse = orighasiniparse @pytest.fixture(name='both', params=['wconfig', 'rconfig']) def fixture_both(request): request.getfixturevalue(request.param) @with_both def check_copy(): c = newwconfig({'foo.bar': 'baz'}) assert_equals(c.__class__, c.copy().__class__) assert_equals('baz', c.copy().get('foo', 'bar')) @with_both def check_contains(): c = newwconfig({'foo.bar': 'baz'}) assert 'foo' in c, c assert 'bar' not in c, c @with_both def check_getitem(): c = newwconfig({'foo.bar': 'x', 'foo.baz': 'y'}) assert_equals({'bar': 'x', 'baz': 'y'}, dict(c['foo'])) assert_equals({}, dict(c['unknown'])) @with_both def check_getitem_empty_then_set_no_effect(): c = newwconfig() c['unknown']['bar'] = 'baz' assert not c.get('unknown', 'bar'), c.get('unknown', 'bar') @with_both def check_set_followed_by_getitem_empty(): c = newwconfig() c['unknown'] c.set('unknown', 'foo', 'bar') assert_equals('bar', c.get('unknown', 'foo')) assert_equals('bar', c['unknown']['foo']) @with_both def check_dict_contains(): c = newwconfig({'foo.bar': 'x'}) assert 'bar' in c['foo'], c['foo'] assert 'baz' not in c['foo'], c['foo'] @with_both def check_dict_getitem(): c = newwconfig({'foo.bar': 'x'}) assert_equals('x', c['foo']['bar']) assert_raises(KeyError, lambda: c['foo']['baz']) @with_both def check_dict_setitem(): c = newwconfig({'foo.bar': 'x'}) c['foo']['bar'] = 'y' c['foo']['baz'] = 'z' assert_equals('y', c['foo']['bar']) assert_equals('z', c['foo']['baz']) @with_wconfig # original config doesn't preserve the order def check_dict_setitem_preserve_order(): c = newwconfig([('foo.bar', 'x'), ('foo.baz', 'y')]) assert_equals(['bar', 'baz'], list(c['foo'])) c['foo']['bar'] = 'z' assert_equals(['bar', 'baz'], list(c['foo'])) @with_both def check_dict_iter(): c = newwconfig({'foo.bar': 'x', 'foo.baz': 'y'}) assert_equals({'bar', 'baz'}, set(c['foo'])) @with_both def check_dict_len(): c = newwconfig({'foo.bar': 'x'}) assert_equals(1, len(c['foo'])) @with_both def check_dict_update(): c = newwconfig({'foo.bar': 'x', 'foo.baz': 'y'}) c['foo'].update(newwconfig({'foo.bar': 'z', 'foo.baz': 'w'})['foo']) assert_equals('z', c['foo']['bar']) assert_equals('w', c['foo']['baz']) @with_both def check_dict_delitem(): c = newwconfig({'foo.bar': 'x'}) del c['foo']['bar'] assert 'bar' not in c['foo'], c['foo'] @with_both def check_iter(): c = newwconfig({'foo.bar': 'x', 'baz.bax': 'y'}) assert_equals({'foo', 'baz'}, set(c)) @with_both def check_update(): c0 = newwconfig({'foo.bar': 'x', 'foo.blah': 'w'}) c1 = newwconfig({'foo.bar': 'y', 'baz.bax': 'z'}) c0.update(c1) assert_equals('y', c0.get('foo', 'bar')) assert_equals('z', c0.get('baz', 'bax')) assert_equals('w', c0.get('foo', 'blah')) @with_both def check_get(): c = newwconfig({'foo.bar': 'baz'}) assert_equals('baz', c.get('foo', 'bar')) assert_equals(None, c.get('foo', 'baz')) assert_equals('x', c.get('foo', 'baz', 'x')) @with_both def check_source(): c = newwconfig() c.set('foo', 'bar', 'baz', source='blah') assert_equals('blah', c.source('foo', 'bar')) @with_both def check_sections(): c = newwconfig({'foo.bar': 'x', 'baz.bax': 'y'}) assert_equals(['baz', 'foo'], c.sections()) @with_both def check_items(): c = newwconfig({'foo.bar': 'x', 'foo.baz': 'y'}) assert_equals({'bar': 'x', 'baz': 'y'}, dict(c.items('foo'))) @with_both def check_set(): c = newwconfig({'foo.bar': 'x'}) c.set('foo', 'baz', 'y') c.set('foo', 'bar', 'w') c.set('newsection', 'bax', 'z') assert_equals('y', c.get('foo', 'baz')) assert_equals('w', c.get('foo', 'bar')) assert_equals('z', c.get('newsection', 'bax')) @with_wconfig # original config doesn't preserve the order def check_set_preserve_order(): c = newwconfig([('foo.bar', 'x'), ('foo.baz', 'y')]) assert_equals(['bar', 'baz'], list(c['foo'])) c.set('foo', 'bar', 'z') assert_equals(['bar', 'baz'], list(c['foo'])) # TODO: test_parse # TODO: test_read @with_wconfig def check_write_after_set(): c = newwconfig() c.set('foo', 'bar', 'baz') assert_equals('[foo]\nbar = baz', written(c).rstrip()) @with_wconfig def check_write_empty(): c = newwconfig() assert_equals('', written(c).rstrip()) @with_wconfig def check_write_after_update(): c = newwconfig() c.update(newwconfig({'foo.bar': 'baz'})) assert_equals('[foo]\nbar = baz', written(c).rstrip()) @with_wconfig def check_read_write(): c = newwconfig() s = '[foo]\nbar = baz' c.read(path='foo', fp=pycompat.bytesio(s)) assert_equals(s, written(c).rstrip()) @with_wconfig @raises(error.ParseError) def check_read_write_missing_section_header_error(): c = newwconfig() s = 'bar = baz' # missing header c.read(path='foo', fp=pycompat.bytesio(s)) c.write(pycompat.bytesio()) @with_wconfig @raises(error.ParseError) def check_read_write_parsing_error(): c = newwconfig() s = '[foo]\n:bar = baz' # Mercurial can parse it but INIConfig can't c.read(path='foo', fp=pycompat.bytesio(s)) c.write(pycompat.bytesio()) @with_wconfig def check_write_after_dict_setitem(): c = newwconfig({'foo.bar': 'x'}) c['foo']['bar'] = 'y' assert_equals('[foo]\nbar = y', written(c).rstrip()) @with_wconfig def check_write_after_dict_update(): c = newwconfig({'foo.bar': 'x'}) c['foo'].update({'bar': 'y'}) assert_equals('[foo]\nbar = y', written(c).rstrip()) @with_wconfig def check_write_after_dict_delitem(): c = newwconfig({'foo.bar': 'x', 'foo.baz': 'y'}) del c['foo']['bar'] assert_equals('[foo]\nbaz = y', written(c).rstrip()) @with_wconfig def check_read_write_rem(): c = newwconfig() s = '[foo]\nrem = x' c.read(path='foo', fp=pycompat.bytesio(s)) c.set('foo', 'rem', 'y') assert_equals('[foo]\nrem = y', written(c).rstrip()) @with_wconfig def check_read_write_suboption(): c = newwconfig() s = '[foo]\nbar:baz = x' c.read(path='foo', fp=pycompat.bytesio(s)) c.set('foo', 'bar:baz', 'y') assert_equals('[foo]\nbar:baz = y', written(c).rstrip()) @with_wconfig def check_read_write_suboption_removal(): c = newwconfig() s = '[foo]\nbar:baz = x\nbar = y' c.read(path='foo', fp=pycompat.bytesio(s)) del c['foo']['bar:baz'] assert_equals('[foo]\nbar = y', written(c).rstrip()) @with_wconfig def check_write_conflict_set_set(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = wconfig.readfile(fname) c1.set('foo', 'bar', 'y') wconfig.writefile(c1, fname) c0.set('foo', 'bar', 'z') wconfig.writefile(c0, fname) cr = wconfig.readfile(fname) assert_equals('z', cr.get('foo', 'bar')) @with_wconfig def check_write_conflict_del_set(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = wconfig.readfile(fname) del c1['foo']['bar'] wconfig.writefile(c1, fname) c0.set('foo', 'bar', 'z') wconfig.writefile(c0, fname) cr = wconfig.readfile(fname) assert_equals('z', cr.get('foo', 'bar')) @with_wconfig def check_write_conflict_set_del(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = wconfig.readfile(fname) c1.set('foo', 'bar', 'y') wconfig.writefile(c1, fname) del c0['foo']['bar'] wconfig.writefile(c0, fname) cr = wconfig.readfile(fname) assert not cr.get('foo', 'bar'), cr.get('foo', 'bar') @with_wconfig def check_write_conflict_del_del(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = wconfig.readfile(fname) del c1['foo']['bar'] wconfig.writefile(c1, fname) del c0['foo']['bar'] wconfig.writefile(c0, fname) # shouldn't raise KeyError cr = wconfig.readfile(fname) assert not cr.get('foo', 'bar'), cr.get('foo', 'bar') @with_wconfig def check_write_noconflict_set_set(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = wconfig.readfile(fname) c1.set('foo', 'baz', 'y') wconfig.writefile(c1, fname) c0.set('foo', 'bar', 'z') wconfig.writefile(c0, fname) # should not override foo.baz = y cr = wconfig.readfile(fname) assert_equals('z', cr.get('foo', 'bar')) assert_equals('y', cr.get('foo', 'baz')) # don't reload c1's change implicitly assert not c0.get('foo', 'baz'), c0.get('foo', 'baz') @with_wconfig def check_write_noconflict_del(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = wconfig.readfile(fname) del c1['foo']['bar'] wconfig.writefile(c1, fname) wconfig.writefile(c0, fname) # shouldn't override del foo.bar cr = wconfig.readfile(fname) assert not cr.get('foo', 'bar'), cr.get('foo', 'bar') # don't reload c1's change implicitly assert c0.get('foo', 'bar'), c0.get('foo', 'bar') @with_wconfig def check_write_copied(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = c0.copy() c1.set('foo', 'baz', 'y') wconfig.writefile(c1, fname) cr = wconfig.readfile(fname) assert_equals('x', cr.get('foo', 'bar')) assert_equals('y', cr.get('foo', 'baz')) @with_wconfig def check_write_copied_conflict(): fname = writetempfile('[foo]\nbar = x') c0 = wconfig.readfile(fname) c1 = c0.copy() c0.set('foo', 'bar', 'y') wconfig.writefile(c0, fname) wconfig.writefile(c1, fname) # shouldn't override foo.bar = y cr = wconfig.readfile(fname) assert_equals('y', cr.get('foo', 'bar')) @with_wconfig def check_write_copied_rconfig(): c0 = newrconfig({'foo.bar': 'x'}) c1 = wconfig.config(c0) assert_equals('[foo]\nbar = x', written(c1).rstrip()) @with_both def check_readfile(): fname = writetempfile('[foo]\nbar = baz') c = wconfig.readfile(fname) assert_equals('baz', c.get('foo', 'bar')) @with_wconfig def check_writefile(): c = newwconfig({'foo.bar': 'baz'}) fname = writetempfile('') wconfig.writefile(c, fname) assert_equals('[foo]\nbar = baz', open(fname).read().rstrip())