This instance will be upgraded to Heptapod 0.21.0rc2 on 2021-04-16 at 11:00 UTC+2 (a few minutes of down time)

wconfig_test.py 11.4 KB
Newer Older
1
import os, tempfile
2
from nose.tools import *
3 4 5 6 7
from mercurial import (
    config,
    error,
    pycompat,
)
8
import pytest
9

10 11
from tortoisehg.util import wconfig

12 13
import helpers

14
def setup_module():
15
    global _tempdir
16
    _tempdir = helpers.mktmpdir(__name__)
17 18


19 20 21
def newrconfig(vals=None):
    if vals is None:
        vals = {}
22
    c = config.config()
23
    for k, v in isinstance(vals, dict) and vals.items() or vals:
24 25 26 27
        sec, it = k.split('.', 1)
        c.set(sec, it, v)
    return c

28 29 30
def newwconfig(vals=None):
    if vals is None:
        vals = {}
31 32 33
    return wconfig.config(newrconfig(vals))

def written(c):
34
    dest = pycompat.bytesio()
35 36 37 38 39 40 41 42 43 44
    c.write(dest)
    return dest.getvalue()

def writetempfile(s):
    fd, path = tempfile.mkstemp(dir=_tempdir)
    os.write(fd, s)
    os.close(fd)
    return path


45 46 47
def with_rconfig(f):
    f.__test__ = True
    return pytest.mark.usefixtures('rconfig')(f)
48

49 50 51
def with_wconfig(f):
    f.__test__ = True
    return pytest.mark.usefixtures('wconfig')(f)
52

53 54 55
def with_both(f):
    f.__test__ = True
    return pytest.mark.usefixtures('both')(f)
56

57 58 59 60 61 62 63 64 65 66

@pytest.fixture(name='wconfig')
def fixture_wconfig():
    if wconfig._hasiniparse:
        yield
    else:
        pytest.skip()

@pytest.fixture(name='rconfig')
def fixture_rconfig():
67 68 69
    orighasiniparse = wconfig._hasiniparse
    wconfig._hasiniparse = False
    try:
70
        yield
71 72 73
    finally:
        wconfig._hasiniparse = orighasiniparse

74 75 76 77
@pytest.fixture(name='both', params=['wconfig', 'rconfig'])
def fixture_both(request):
    request.getfixturevalue(request.param)

78 79 80 81 82 83 84 85 86 87

@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'})
88 89
    assert 'foo' in c, c
    assert 'bar' not in c, c
90 91 92 93 94 95 96 97 98 99 100

@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'
101
    assert not c.get('unknown', 'bar'), c.get('unknown', 'bar')
102

103 104 105 106 107 108 109 110
@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'])

111 112 113
@with_both
def check_dict_contains():
    c = newwconfig({'foo.bar': 'x'})
114 115
    assert 'bar' in c['foo'], c['foo']
    assert 'baz' not in c['foo'], c['foo']
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

@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'})
141
    assert_equals({'bar', 'baz'}, set(c['foo']))
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

@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']
159
    assert 'bar' not in c['foo'], c['foo']
160 161 162 163

@with_both
def check_iter():
    c = newwconfig({'foo.bar': 'x', 'baz.bax': 'y'})
164
    assert_equals({'foo', 'baz'}, set(c))
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

@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'
239
    c.read(path='foo', fp=pycompat.bytesio(s))
240 241
    assert_equals(s, written(c).rstrip())

242 243
@with_wconfig
@raises(error.ParseError)
244
def check_read_write_missing_section_header_error():
245 246
    c = newwconfig()
    s = 'bar = baz'  # missing header
247 248
    c.read(path='foo', fp=pycompat.bytesio(s))
    c.write(pycompat.bytesio())
249

250 251 252 253 254
@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
255 256
    c.read(path='foo', fp=pycompat.bytesio(s))
    c.write(pycompat.bytesio())
257

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
@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'
280
    c.read(path='foo', fp=pycompat.bytesio(s))
281 282 283
    c.set('foo', 'rem', 'y')
    assert_equals('[foo]\nrem = y', written(c).rstrip())

284 285 286 287
@with_wconfig
def check_read_write_suboption():
    c = newwconfig()
    s = '[foo]\nbar:baz = x'
288
    c.read(path='foo', fp=pycompat.bytesio(s))
289 290 291 292 293 294 295
    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'
296
    c.read(path='foo', fp=pycompat.bytesio(s))
297 298 299
    del c['foo']['bar:baz']
    assert_equals('[foo]\nbar = y', written(c).rstrip())

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

@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)
338
    assert not cr.get('foo', 'bar'), cr.get('foo', 'bar')
339 340 341 342 343 344 345 346 347 348 349 350

@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)
351
    assert not cr.get('foo', 'bar'), cr.get('foo', 'bar')
352 353 354 355 356 357 358 359 360 361 362 363 364 365

@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'))
366 367
    # don't reload c1's change implicitly
    assert not c0.get('foo', 'baz'), c0.get('foo', 'baz')
368 369 370 371 372 373 374 375 376 377 378

@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)
379 380 381
    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')
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408


@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
409
def check_write_copied_rconfig():
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
    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())