def setDataForPath(data, path: PathType, value, *, undefined=ImmutableDict()): if not path: if value is Undefined: return undefined else: return sanitize(value) p, path = path[0], path[1:] if type(p) is str: if data is Undefined: data = ImmutableDict() elif type(data) is not ImmutableDict: raise PathElementTypeMismatch(p, data) if value is Undefined and not path: return data.discard(p) elif type(p) is int: if data is Undefined: data = ImmutableList() elif type(data) is not ImmutableList: raise PathElementTypeMismatch(p, data) if value is Undefined and not path: if 0 <= p < len(data): return data[0:p] + data[p + 1:] else: return data if p < 0 or p > len(data): raise IndexError if p == len(data): return data.append(setDataForPath(Undefined, path, value)) else: raise InvalidPathElement(p) return data.set(p, setDataForPath(data.get(p, Undefined), path, value))
def test_mixed(self): ch = ImmutableChecker(self) keys = ( "", "a", "foobar", "baz", "0", "123", "xxx", None, False, unittest, ) values = keys + ( 123, 0, -1, 12.34, 567.76, True, [], {}, [1, 2], { "a": 1 }, ) idicts = set() for k1 in keys: for v1 in values: i = ImmutableDict().set(k1, v1) idicts.add(i) ch.add(i) for k2 in keys: for v2 in values: i = i.set(k2, v2) idicts.add(i) ch.add(i) for i in set(idicts): for k in keys: i = i.discard(k) idicts.add(i) ch.add(i) ilists = set() for k1 in keys: i = ImmutableList().append(k1) ilists.add(i) ch.add(i) for k1 in keys: i = i.append(k2) ilists.add(i) ch.add(i) idicts = list(idicts) ilists = list(ilists) for n in range(100_000): d1 = idicts[n * 104_651 % len(idicts)] l1 = ilists[n * 104_659 % len(ilists)] k1 = keys[n * 104_677 % len(keys)] k2 = keys[n * 104_681 % len(keys)] d2 = idicts[n * 104_683 % len(idicts)] l2 = ilists[n * 104_693 % len(ilists)] nl = l1.append(d1) ilists.append(nl) ch.add(nl) nd = d1.set(k1, l1) idicts.append(nd) ch.add(nd) if k2 in d1: nd2 = d1.discard(k2) idicts.append(nd2) ch.add(nd2) nl = l2.append(l1) ilists.append(nl) ch.add(nl) nd = d2.set(k2, d1) idicts.append(nd) ch.add(nd)