Example #1
0
    def test_dict(self):
        data = ImmutableDict(a=123)
        self.assertEqual(data.meta, {})

        data.meta["been here"] = True

        self.assertTrue(ImmutableDict(a=123).meta["been here"])
Example #2
0
def example_immutable_data():
    return ImmutableDict(
        foo=1,
        bar=ImmutableDict(baz=99),
        xxx=ImmutableList((None, True, ImmutableList())),
        yyy=ImmutableDict(),
        zzz=None,
    )
Example #3
0
 def test_getset(self):
     d = ImmutableDict()
     with self.assertRaises(KeyError):
         d["foo"]
     self.assertEqual(d.get("foo"), None)
     e = d.set("foo", "bar")
     with self.assertRaises(KeyError):
         d["foo"]
     self.assertEqual(e.get("foo"), "bar")
Example #4
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)
Example #5
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))
Example #6
0
 def clear(self):
     for rc in self.__registeredCommands.values():
         rc.disabled = True
         rc.unregister()
     self.__registeredCommands = {}
     self.__state = ImmutableDict()
     self.__reportedState = Undefined
     self.__parentSet(self.__path, Undefined)
Example #7
0
    def test_dict_weakref(self):
        # Create one ImmutableDict
        self.assertEqual(ImmutableDict._get_instance_count(), 0)
        d = ImmutableDict(foo=1, bar=2)
        self.assertEqual(ImmutableDict._get_instance_count(), 1)

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

        # Release the only reference to the ImmutableDict
        d = None
        self.assertEqual(ImmutableDict._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 ImmutableDict, check that it not magically appears in
        # wkd
        d = ImmutableDict(foo=1, bar=2)
        self.assertEqual(ImmutableDict._get_instance_count(), 1)
        self.assertEqual(len(wvd), 0)
        with self.assertRaises(KeyError):
            wvd[1]
Example #8
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)
    def test_tuple(self):
        key1 = ("x" * 10000,)
        key2 = (("x" * 9999 + "x"),)
        self.assertTrue(type(key1) is tuple)
        self.assertTrue(type(key2) is tuple)
        self.assertEqual(key1, key2)

        if key1 is key2:
            self.skipTest(
                "failed to construct two different tuple objects "
                "with same value"
            )

        d = ImmutableDict({key1: 123})
        self.assertEqual(d.get(key1), 123)
        self.assertEqual(d.get(key2), 123)
        self.assertTrue(key1 in d)
        self.assertTrue(key2 in d)
Example #10
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])]))
Example #11
0
    def test_bytes(self):
        key1 = b"x" * 10000
        key2 = b"x" * 9999 + b"x"
        self.assertTrue(type(key1) is bytes)
        self.assertTrue(type(key2) is bytes)
        self.assertEqual(key1, key2)

        if key1 is key2:
            self.skipTest(
                "failed to construct two different bytes objects "
                "with same value"
            )

        d = ImmutableDict({key1: 123})
        self.assertEqual(d.get(key1), 123)
        self.assertEqual(d.get(key2), 123)
        self.assertTrue(key1 in d)
        self.assertTrue(key2 in d)
        self.assertFalse(key1.decode("ascii") in d)
Example #12
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()))
Example #13
0
 def __init__(
     self,
     path,
     *,
     parent_set,
     parent_register_command,
     immediate_updates=True
 ):
     self.__path = path
     self.__parentSet = parent_set
     self.__parentRegisterCommand = parent_register_command
     self.__state = ImmutableDict()
     self.__reportedState = Undefined
     self.__registeredCommands = {}
     self.__immediate_updates = immediate_updates
     self.__deactivated = False
     self.__hidden = False
Example #14
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")
Example #15
0
    def __newPlugin(self, path, config):
        plugin_info = PluginInfo(path=path, configuration=config)

        try:
            plugin_identifier = config["__plugin__"]
            module, class_ = plugin_identifier.rsplit(".", 1)

            sys.modules.pop(module, None)
            mod = importlib.import_module(module)

            PluginType = getattr(mod, class_)
            plugin_info.plugin_object = PluginType(
                path=path,
                get=lambda path: self.get(path),
                subscribe=lambda callback, *paths, initial=True: (
                    self.subscribe(
                        plugin_info, paths, callback, initial=initial
                    )
                ),
                command=self.command,
                set_state=functools.partial(
                    self.__setPluginState, plugin_info
                ),
                register_command=functools.partial(
                    self.registerCommand, plugin_info
                ),
            )
            plugin_info.plugin_object.init(config)
        except Exception as ex:
            traceback.print_exc()
            plugin_info.state = ImmutableDict(
                exception=str(ex), traceback=traceback.format_exc()
            )
            plugin_info.plugin_object = None

        return plugin_info
Example #16
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)
Example #17
0
def _symlinkInfoDict(data):
    return ImmutableDict((pathToString(k), pathToString(v)) for k, v in data)
Example #18
0
import unittest

from pyimmutable import ImmutableDict, ImmutableList

from pykzee.core import AttachedInfo
from pykzee.core.common import sanitize

# Instantiante an empty ImmutableDict, since pykzee modules may or may not do
# that anyway. This way we know what instance counts to expect in the tests
# below.
empty_immutable_dict = ImmutableDict()


class TestResolved(unittest.TestCase):
    def test_basic(self):
        self.assertEqual(immutables_count(), 1)
        data = sanitize({
            "foo": "bar",
            "x1": [0, 1, 2, {
                "__symlink__": "x2"
            }, 4],
            "x2": {
                "y1": 123,
                "y2": {
                    "__symlink__": "foo"
                },
                "y3": {
                    "__symlink__": "/x1/[3]/y1"
                },
                "y4": {
                    "__symlink__": ["x2", "y2"]
Example #19
0
 def test_constructFromDict(self):
     pydict = {"a": 1, "b": None, "c": True, False: 5.678}
     d = ImmutableDict(pydict)
     self.assertEqual(set(d.items()), set(pydict.items()))
Example #20
0
 def test_convertToDict(self):
     pydict = {"a": 1, "b": None, "c": True, False: 5.678}
     d = ImmutableDict()
     for key, val in pydict.items():
         d = d.set(key, val)
     self.assertEqual(dict(d), pydict)
Example #21
0
 def test_len(self):
     self.assertEqual(len(ImmutableDict()), 0)
     self.assertEqual(len(ImmutableDict().set("foo", 1)), 1)
     self.assertEqual(len(ImmutableDict().set("foo", 1).set("bar", 2)), 2)
     self.assertEqual(
         len(ImmutableDict().set("foo", 1).set("bar", 2).set("foo", 99)), 2)
Example #22
0
 def test_iter(self):
     d = ImmutableDict().set("foo", 1).set("bar", 2)
     self.assertEqual(set(d), {"foo", "bar"})
     self.assertEqual(set(d.keys()), {"foo", "bar"})
     self.assertEqual(set(d.values()), {1, 2})
     self.assertEqual(set(d.items()), {("foo", 1), ("bar", 2)})
Example #23
0
 def test_equal(self):
     d = ImmutableDict().set("foo", 1).set("bar", 2)
     e = ImmutableDict().set("bar", 2).set("foo", 1)
     self.assertEqual(d, e)
     self.assertTrue(d is e)
Example #24
0
def immutables_count():
    return (ImmutableDict._get_instance_count() +
            ImmutableList._get_instance_count())
Example #25
0
    def test_stress(self):
        r = random.Random(123)

        class X:
            pass

        x = X()

        objects = [
            x,
            x,
            True,
            False,
            None,
            "\uf111",
            -4.5,
            -4.501,
            -4.502,
            4.5,
        ]
        objects.extend(range(-50, 50))
        objects.extend(str(r.random()) for i in range(100))
        objects.append(unittest)

        dicts = list((ImmutableDict(), {}) for i in range(10))

        for i in range(1_000_000):
            # Mutate actions
            idx = random.randrange(0, len(dicts))
            idict, pydict = dicts[idx]

            action = random.randint(0, 2)
            if action == 0:
                key, value = random.choice(objects), random.choice(objects)
                idict = idict.set(key, value)
                pydict[key] = value
            elif action == 1:
                key = random.choice(objects)
                idict = idict.discard(key)
                pydict.pop(key, None)
            elif action == 2:
                update = {
                    random.choice(objects): random.choice(objects)
                    for i in range(random.randint(0, 5))
                }
                idict = idict.update(update)
                pydict.update(update)

            dicts[idx] = idict, pydict

            # Verify actions
            idict, pydict = random.choice(dicts)
            action = random.randint(0, 13)
            if action < 5:
                key = random.choice(objects)
                self.assertEqual(idict.get(key, -999), pydict.get(key, -999))
            elif action < 10:
                key = random.choice(objects)
                try:
                    value = idict[key]
                except KeyError:
                    value = KeyError
                self.assertEqual(value, pydict.get(key, KeyError))
            elif action == 10:
                self.assertTrue(compareUnsortedUniqueSequences(idict, pydict))
            elif action == 11:
                self.assertTrue(
                    compareUnsortedUniqueSequences(idict.keys(), pydict)
                )
            elif action == 12:
                self.assertTrue(
                    compareUnsortedSequences(idict.values(), pydict.values())
                )
            elif action == 13:
                self.assertTrue(
                    compareUnsortedUniqueSequences(
                        idict.items(), pydict.items()
                    )
                )
Example #26
0
    def test_dict(self):
        ch = ImmutableChecker(self)

        ch.addImmutable(ImmutableDict())
        ch.addImmutable(ImmutableDict({"a": 1}))
        ch.addImmutable(ImmutableDict({"a": 1, "b": 2}))
        ch.addImmutable(ImmutableDict({"a": 1, "b": "foo"}))
        ch.addImmutable(ImmutableDict({"a": 1, "b": None}))
        ch.addImmutable(ImmutableDict({"a": 1, "b": True}))
        ch.addImmutable(ImmutableDict({"a": 1, "b": 9.876}))
        ch.addNonImmutable(ImmutableDict({"a": 1, "b": 2, "c": Exception()}))
        ch.addImmutable(
            ImmutableDict({
                "a": 1,
                "b": 2,
                "c": Exception()
            }).discard("c"))
        ch.addImmutable(
            ImmutableDict({
                "a": 99,
                "b": 2,
                "c": Exception()
            }).discard("c"))
        ch.addNonImmutable(ImmutableDict({"a": 1, "b": 2, True: 123}))
        ch.addImmutable(
            ImmutableDict({
                "a": 1,
                "b": 2,
                True: 123
            }).discard(True))
        ch.addImmutable(
            ImmutableDict({
                "a": 1,
                "b": 2,
                "c": 3,
                "d": 4
            }).set("e", 5).set("d", 7))
        ch.addNonImmutable(
            ImmutableDict({
                "a": 1,
                "b": 2,
                "c": 3,
                "d": 4
            }).set("d", Exception()).set("e", 5))
        ch.addImmutable(
            ImmutableDict({
                "a": 1,
                "b": 2,
                "c": 3
            }).update(b=2, c=4))

        ch.check_all()