Ejemplo n.º 1
0
    def test_list(self):
        data = ImmutableList((1, 2, 3))
        self.assertEqual(data.meta, {})

        data.meta["been here"] = True

        self.assertTrue(ImmutableList((1, 2, 3)).meta["been here"])
Ejemplo n.º 2
0
    def test_iter(self):
        il = ImmutableList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

        self.assertEqual([x for x in il], list(range(10)))
        self.assertEqual([x for x in iter(il)], list(range(10)))
        self.assertEqual([x for x in il.__iter__()], list(range(10)))
        self.assertFalse([x for x in ImmutableList()])
Ejemplo n.º 3
0
def example_immutable_data():
    return ImmutableDict(
        foo=1,
        bar=ImmutableDict(baz=99),
        xxx=ImmutableList((None, True, ImmutableList())),
        yyy=ImmutableDict(),
        zzz=None,
    )
Ejemplo n.º 4
0
    def test_pass_immutable(self):
        self.assertTrue(
            sanitize([[]]) is sanitize(ImmutableList([[]])) is sanitize(
                ImmutableList([ImmutableList()])) is ImmutableList(
                    [ImmutableList()]))

        self.assertTrue(
            sanitize({"a": {}}) is sanitize(ImmutableDict({"a": {}})) is
            sanitize(ImmutableDict(
                a={})) is sanitize(ImmutableDict(
                    a=ImmutableDict())) is ImmutableDict(a=ImmutableDict()))
Ejemplo n.º 5
0
    def test_index(self):
        with self.assertRaises(ValueError):
            ImmutableList().index(None)
        with self.assertRaises(ValueError):
            ImmutableList().index(1)
        with self.assertRaises(ValueError):
            ImmutableList([1, 2, 3]).index(4)

        self.assertEqual(ImmutableList([1, 2, 3, 4]).index(3), 2)
        with self.assertRaises(ValueError):
            ImmutableList([1, 2, 3, 4]).index(3.0)
Ejemplo n.º 6
0
    def test_simple(self):
        self.assertTrue(sanitize(ImmutableDict()) is ImmutableDict())
        self.assertTrue(sanitize({}) is ImmutableDict())
        self.assertTrue(sanitize(ImmutableList()) is ImmutableList())
        self.assertTrue(sanitize([]) is ImmutableList())

        self.assertTrue(sanitize(None) is None)
        self.assertTrue(sanitize(True) is True)
        self.assertTrue(sanitize(False) is False)
        self.assertEqual(sanitize("foobar"), "foobar")
        self.assertEqual(sanitize(1234), 1234)
        self.assertEqual(sanitize(1.234), 1.234)
Ejemplo n.º 7
0
    def test_list(self):
        ch = ImmutableChecker(self)

        ch.addImmutable(ImmutableList())
        ch.addImmutable(ImmutableList([1]))
        ch.addImmutable(ImmutableList([1, 2]))
        ch.addImmutable(ImmutableList([1, "foo"]))
        ch.addImmutable(ImmutableList([1, None]))
        ch.addImmutable(ImmutableList([1, True]))
        ch.addImmutable(ImmutableList([1, 9.876]))
        ch.addNonImmutable(ImmutableList([1, 2, Exception()]))
        ch.addImmutable(ImmutableList([1, 2, Exception()])[0:2])
        ch.addImmutable(ImmutableList([99, 2, Exception()])[0:2])

        ch.check_all()
Ejemplo n.º 8
0
    def test_hash(self):
        data1 = make_test_data()
        data2 = make_test_data()

        if all(x is y for x, y in zip(data1, data2)):
            # If the members of data1 and data2 are pairwise identical (they
            # are the same objects), then this test is not meaningful.
            # This means that constructing the same tuple or string twice
            # yields the same object. This was not the case with the Python
            # interpreter used during development.
            raise unittest.SkipTest("Test data sets contain identical objects")

        l1 = ImmutableList(data1)
        l2 = ImmutableList(data2)
        self.assertTrue(l1 is l2)
Ejemplo n.º 9
0
 def subscribe(
     self,
     plugin_info,
     paths,
     callback,
     *,
     initial=True,
     state_type=StateType.RESOLVED,
 ):
     if plugin_info.disabled:
         raise Exception("disabled plugin must not subscribe")
     slots = tuple(
         SubscriptionSlot(
             path,
             (
                 self.__rawSubscriptionRoot
                 if state_type == StateType.RAW
                 else self.__unresolvedSubscriptionRoot
                 if state_type == StateType.UNRESOLVED
                 else self.__resolvedSubscriptionRoot
             ).get(path),
             state_type,
         )
         for path in map(makePath, paths)
     )
     state = ImmutableList(slot.directory.state for slot in slots)
     sub = Subscription(plugin_info, slots, callback, state, initial)
     plugin_info.subscriptions.add(sub)
     for idx, slot in enumerate(slots):
         slot.directory.subscriptions.add((sub, idx))
     if initial:
         self.__updatedSubscriptions.add(sub)
         self.__stateUpdateEvent.set()
     return lambda: self.unsubscribe(sub)
Ejemplo n.º 10
0
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))
Ejemplo n.º 11
0
def plugins(data):
    if type(data) is ImmutableDict:
        if "__plugin__" in data:
            return ImmutableList([((), data)])

    gen = (
        sorted(data.items())
        if type(data) is ImmutableDict
        else enumerate(data)
    )
    return ImmutableList(
        ((key,) + path, plugin)
        for key, value in gen
        if type(value) in (ImmutableDict, ImmutableList)
        for path, plugin in plugins(value)
    )
Ejemplo n.º 12
0
def sanitize(data):
    t = type(data)
    if (t is ImmutableList or t is ImmutableDict) and data.isImmutableJson:
        return data
    if data is None or t is bool or t is str or t is int or t is float:
        return data
    elif isinstance(data, Sequence):
        data = ImmutableList(sanitize(x) for x in data if x is not Undefined)
        if data.isImmutableJson:
            return data
    elif isinstance(data, Mapping):
        data = ImmutableDict((enforceKeyType(key), sanitize(value))
                             for key, value in data.items()
                             if value is not Undefined)
        if data.isImmutableJson:
            return data
    raise TypeError("data cannot be sanitized to immutable json")
Ejemplo n.º 13
0
    def test_concat_extend(self):
        lists = [[], [0], ["foo", "bar"], [False, True, None, 0.123]]

        for l1 in lists:
            for l2 in lists:
                il1 = ImmutableList(l1)
                il2 = ImmutableList(l2)
                self.assertTrue(ImmutableList(l1 + l2) is il1 + il2)
                self.assertTrue(ImmutableList(l1 + l2) is il1.extend(il2))
                self.assertTrue(ImmutableList(l1 + l2) is il1.extend(l2))
Ejemplo n.º 14
0
    def test_list_weakref(self):
        # Create one ImmutableList
        self.assertEqual(ImmutableList._get_instance_count(), 0)
        d = ImmutableList([1, 2])
        self.assertEqual(ImmutableList._get_instance_count(), 1)

        # Store in a weakref.WeakValueListionary
        wvd = weakref.WeakValueDictionary()
        wvd[1] = d
        self.assertEqual(ImmutableList._get_instance_count(), 1)
        self.assertEqual(len(wvd), 1)
        self.assertTrue(wvd[1] is d)

        # Release the only reference to the ImmutableList
        d = None
        self.assertEqual(ImmutableList._get_instance_count(), 0)
        # Check that it is no longer in wkd
        self.assertEqual(len(wvd), 0)
        with self.assertRaises(KeyError):
            wvd[1]

        # Create a new ImmutableList, check that it not magically appears in
        # wkd
        d = ImmutableList([1, 2])
        self.assertEqual(ImmutableList._get_instance_count(), 1)
        self.assertEqual(len(wvd), 0)
        with self.assertRaises(KeyError):
            wvd[1]
Ejemplo n.º 15
0
def symlinks(data):
    sl = symlink(data)
    if sl is False:
        return ImmutableList()
    elif sl is not None:
        return ImmutableList([((), sl)])

    gen = (
        sorted(data.items())
        if type(data) is ImmutableDict
        else enumerate(data)
    )
    return ImmutableList(
        ((key,) + path, dest)
        for key, value in gen
        if type(value) in (ImmutableDict, ImmutableList)
        for path, dest in symlinks(value)
    )
Ejemplo n.º 16
0
def _realpaths(data):
    rp = functools.partial(_realpathImpl, dict(data))
    return ImmutableList(
        (location, real_destination)
        for location, real_destination in (
            (location, rp(destination)) for location, destination in data
        )
        if real_destination is not None
    )
Ejemplo n.º 17
0
 def test_append_get_set(self):
     l0 = ImmutableList()
     self.assertEqual(len(l0), 0)
     self.assertEqual(list(l0), [])
     l1 = l0.append(999)
     self.assertEqual(len(l1), 1)
     self.assertEqual(l1[0], 999)
     self.assertEqual(list(l1), [999])
     l2 = l1.append("foobar")
     self.assertEqual(len(l2), 2)
     self.assertEqual(l2[0], 999)
     self.assertEqual(l2[1], "foobar")
     self.assertEqual(list(l2), [999, "foobar"])
     l3 = l2.set(0, "baz")
     self.assertEqual(len(l3), 2)
     self.assertEqual(l3[0], "baz")
     self.assertEqual(l3[1], "foobar")
     self.assertEqual(list(l3), ["baz", "foobar"])
Ejemplo n.º 18
0
    def test_nested(self):
        self.assertTrue(
            sanitize({
                "a": 1,
                "b": None,
                "c": {
                    "x": True
                },
                "d": ImmutableDict(y=False),
            }) is ImmutableDict(
                a=1, b=None, c=ImmutableDict(x=True), d=ImmutableDict(
                    y=False)))

        self.assertTrue(
            sanitize([1, None, [True], ImmutableList([False])]) is
            ImmutableList(
                [1, None,
                 ImmutableList([True]),
                 ImmutableList([False])]))
Ejemplo n.º 19
0
 def test_count(self):
     il = ImmutableList([3, "two", 1, 3, "two", 3, 2])
     self.assertEqual(il.count(0), 0)
     self.assertEqual(il.count(1), 1)
     self.assertEqual(il.count("two"), 2)
     self.assertEqual(il.count(3), 3)
     self.assertEqual(il.count(3.0), 0)
Ejemplo n.º 20
0
def _resolveImpl(resolve_data):
    if len(resolve_data) == 3 and resolve_data[1] == ():
        return resolve_data[2]

    data = resolve_data[0]
    replacements = [
        (resolve_data[i], resolve_data[i + 1])
        for i in range(1, len(resolve_data), 2)
    ]

    if not replacements:
        return data

    try:
        keep_alive = data.meta["_resolveImpl-keep_alive"]
    except KeyError:
        keep_alive = data.meta["_resolveImpl-keep_alive"] = []

    keep_alive = []
    i = 0
    while i < len(replacements):
        first_elem = replacements[i][0][0]
        j = i + 1
        while j < len(replacements):
            if replacements[j][0][0] == first_elem:
                j += 1
            else:
                break

        if j - i == 1 and len(replacements[i][0]) == 1:
            data = _set_helper(data, first_elem, replacements[i][1])
        else:
            subreplacements = ImmutableList(
                [
                    _get_helper(data, first_elem),
                    *(
                        item
                        for k in range(i, j)
                        for item in (
                            replacements[k][0][1:],
                            replacements[k][1],
                        )
                    ),
                ]
            )
            keep_alive.append(subreplacements)
            data = _set_helper(data, first_elem, _resolveImpl(subreplacements))
        i = j

    return data
Ejemplo n.º 21
0
 def __init__(self):
     self.__rawState = self.__unresolvedState = ImmutableDict()
     self.__resolvedState = self.__nextState = ImmutableDict()
     self.__realpath = makePath
     self.__rawSubscriptionRoot = Directory(None, None)
     self.__unresolvedSubscriptionRoot = Directory(None, None)
     self.__resolvedSubscriptionRoot = Directory(None, None)
     self.__updatedSubscriptions = set()
     self.__pluginInfos = []
     self.__pluginList = ImmutableList()
     self.__coreState = ImmutableDict(commands=ImmutableDict())
     self.__corePluginPaths = []
     self.__commands = {}  # path -> {name: Command}
     self.__stateUpdateEvent = asyncio.Event()
     self.__stateUpdateTask = asyncio.create_task(
         self.__stateUpdateTaskImpl()
     )
     self.__stateUpdateTask.add_done_callback(print_exception_task_callback)
Ejemplo n.º 22
0
 def __init__(self, plugin, slots, callback, state, initial: bool):
     if (
         type(slots) != tuple
         or any(type(slot) is not SubscriptionSlot for slot in slots)
         or type(state) != ImmutableList
         or not len(slots) == len(state)
     ):
         logging.error(  # FIXME REMOVE
             "Subscription constructor called with invalid arguments: "
             f"slots={ slots !r} len(state)={ len(state) }"
         )
         raise Exception(
             "Subscription constructor called with invalid arguments: "
             f"slots={ slots !r} len(state)={ len(state) }"
         )
     self.plugin = plugin
     self.slots = slots
     self.callback = callback
     self.__currentState = state
     self.__reportedState = (
         ImmutableList(Undefined for _ in slots) if initial else state
     )
     self.disabled = False
Ejemplo n.º 23
0
    def test_strict_equality(self):
        """
        pyimmutable has stricter equality requirements than usual.
        """

        l1 = ImmutableList([1, 2, 3])
        l2 = ImmutableList([1, 2, 3.0])

        self.assertFalse(l1 is l2)
        self.assertNotEqual(l1, l2)

        self.assertEqual(l1.count(3), 1)
        self.assertEqual(l1.count(3.0), 0)
        self.assertEqual(l2.count(3), 0)
        self.assertEqual(l2.count(3.0), 1)

        self.assertEqual(l1.index(3), 2)
        self.assertEqual(l2.index(3.0), 2)

        with self.assertRaises(ValueError):
            l1.index(3.0)

        with self.assertRaises(ValueError):
            l2.index(3)
Ejemplo n.º 24
0
 def test_reversed(self):
     il = ImmutableList([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
     self.assertEqual([x for x in reversed(il)], list(range(10)))
     self.assertEqual([x for x in il.__reversed__()], list(range(10)))
     self.assertEqual([x for x in iter(il.__reversed__())], list(range(10)))
Ejemplo n.º 25
0
def immutables_count():
    return (ImmutableDict._get_instance_count() +
            ImmutableList._get_instance_count())
Ejemplo n.º 26
0
    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)