Exemple #1
0
    def union(self, other):
        if other is None:
            return self

        if not isinstance(other, type(self)):
            raise TypeError("Cannot merge %s with %s" % (type(self),
                                                         type(other)))

        merged_fields = []
        for i, x in enumerate(self._contents):
            y = other[i]
            merged_fields.append(superposition.meld(x, y))

        return type(self)(*merged_fields)
Exemple #2
0
    def testCreation(self):
        """Test that creation is reasonable."""
        # Providing the same object twice will still build a superposition.
        s = superposition.superposition("foo", "foo")
        # This object is a superposition type...
        self.assertIsInstance(s, superposition.ISuperposition)

        # ...but it is not IN superposition.
        self.assertFalse(superposition.insuperposition(s))

        # Using meld is sometimes more convenient for this.
        s = superposition.meld("foo", "foo")
        # This object is actually a string.
        self.assertIsInstance(s, six.string_types)
        # It can still be manipulated with the superposition-aware protocol,
        # as can any scalar.
        self.assertEqual(s, superposition.getstate(s))
    def testCreation(self):
        """Test that creation is reasonable."""

        # Providing the same object twice will still build a superposition.
        s = superposition.superposition("foo", "foo")
        # This object is a superposition type...
        self.assertIsInstance(s, superposition.ISuperposition)

        # ...but it is not IN superposition.
        self.assertFalse(superposition.insuperposition(s))

        # Using meld is sometimes more convenient for this.
        s = superposition.meld("foo", "foo")
        # This object is actually a string.
        self.assertIsInstance(s, basestring)
        # It can still be manipulated with the superposition-aware protocol,
        # as can any scalar.
        self.assertEqual(s, superposition.getstate(s))
Exemple #4
0
    def get(self, key, complete=False):
        """Returns value of the key, or a superposition thereof.

        Out of the get_ functions, this is almost always the one you want.

        Getting a basic value:
        ======================

        Use key in form of Component.attribute. For example, "Process/pid" or
        "User/username". Same as calling entity[key]:

        entity["Process/pid"]  # PID of the process.

        What if the value is an entity:
        ===============================

        This method automatically recognizes attributes that reference other
        entities, looks them up and returns them. For example:

        entity["Process/parent"]  # Returns the parent process entity.
        entity["Process/parent"]["Process/pid"]  # PID of the parent.

        What if I want all the child processes (Inverse Lookup):
        ========================================================

        You can call entity.get_referencing_entities if you want to be explicit.

        Alternatively, prepend the key with a '&' for inverse lookup of a N:1
        assocation.

        For example:

        entity["&Process/parent"]  # Returns processes of which this process is
                                   # (Child processes).

        entity["&Handle/process"]  # Returns all handles this process has open.

        In most cases, this is unnecessary and aliases can be used instead.

        For example:

        entity["&Handle/process"]  # Is already aliased in definitions as:
        entity["Process/handles"]

        entity["&Process/parent"]  # Is already aliased in definitions as:
        entity["Process/children"]

        When does this return more than one value:
        ==========================================

        1) When doing an inverse lookup.
        2) When the value we find is a superposition.

        In both cases, a superposition is returned. Remember that superpositions
        proxy the [] operator, returning more superpositions. For example:

        # To return the pids of all child processes:
        entity["&Process/parent"]["Process/pid"]

        You can request more than one key in a single call:
        ===================================================

        This is identical to the behavior of [] on python dictionaries:

        entity["Process/pid", "Process/command"]  # is the same as calling:
        (entity["Process/pid"], entity["Process/command"])

        You can also request a multi-level path into the object:
        ========================================================

        The path separator is '->' and is used as follows:

        entity["Process/handles"]["Handle/resource"]  # Is the same as:
        entity["Process/handles->Handle/resource]

        This is merely syntax sugar to make specifying rendering output easier.
        """
        # If we get called with [x, y] python will pass us the keys as a tuple
        # of (x, y). The following behaves identically to dict.
        if isinstance(key, tuple):
            return [self.get(_key, complete) for _key in key]

        # If we get called with a Component/attribute->Component/attribute
        # we treat -> as path separator and the whole key as path into the
        # object.
        if "->" in key:
            # This works recursively.
            key, rest = key.split("->", 1)
            subresult = self.get(key=key, complete=complete)
            if not subresult:
                return None

            return superposition.state_apply(
                subresult,
                lambda x: x.get(key=rest, complete=complete))

        # The & sigil denotes reverse lookup.
        if key.startswith("&"):
            entities = self.get_referencing_entities(key[1:],
                                                     complete=complete)
            return superposition.meld(*list(entities))

        # The raw result could be None, a superposition or just a scalar.
        value = self.get_raw(key)
        if value is None:
            return obj.NoneObject(
                "Entity '%s' has no results for key '%s'." % (self, key))

        # Redirection.
        if isinstance(value, entity_component.Alias):
            return self.get(value.alias, complete=complete)

        typedesc = self.reflect_type(key)
        if typedesc.type_name == "Entity":
            entities = self.manager.find_by_identity(value, complete=complete)
            return superposition.meld(*list(entities))

        return value
Exemple #5
0
    def get(self, key, complete=False):
        """Returns value of the key, or a superposition thereof.

        Out of the get_ functions, this is almost always the one you want.

        Getting a basic value:
        ======================

        Use key in form of Component.attribute. For example, "Process/pid" or
        "User/username". Same as calling entity[key]:

        entity["Process/pid"]  # PID of the process.

        What if the value is an entity:
        ===============================

        This method automatically recognizes attributes that reference other
        entities, looks them up and returns them. For example:

        entity["Process/parent"]  # Returns the parent process entity.
        entity["Process/parent"]["Process/pid"]  # PID of the parent.

        What if I want all the child processes (Inverse Lookup):
        ========================================================

        You can call entity.get_referencing_entities if you want to be explicit.

        Alternatively, prepend the key with a '&' for inverse lookup of a N:1
        assocation.

        For example:

        entity["&Process/parent"]  # Returns processes of which this process is
                                   # (Child processes).

        entity["&Handle/process"]  # Returns all handles this process has open.

        In most cases, this is unnecessary and aliases can be used instead.

        For example:

        entity["&Handle/process"]  # Is already aliased in definitions as:
        entity["Process/handles"]

        entity["&Process/parent"]  # Is already aliased in definitions as:
        entity["Process/children"]

        When does this return more than one value:
        ==========================================

        1) When doing an inverse lookup.
        2) When the value we find is a superposition.

        In both cases, a superposition is returned. Remember that superpositions
        proxy the [] operator, returning more superpositions. For example:

        # To return the pids of all child processes:
        entity["&Process/parent"]["Process/pid"]

        You can request more than one key in a single call:
        ===================================================

        This is identical to the behavior of [] on python dictionaries:

        entity["Process/pid", "Process/command"]  # is the same as calling:
        (entity["Process/pid"], entity["Process/command"])

        You can also request a multi-level path into the object:
        ========================================================

        The path separator is '->' and is used as follows:

        entity["Process/handles"]["Handle/resource"]  # Is the same as:
        entity["Process/handles->Handle/resource]

        This is merely syntax sugar to make specifying rendering output easier.
        """
        # If we get called with [x, y] python will pass us the keys as a tuple
        # of (x, y). The following behaves identically to dict.
        if isinstance(key, tuple):
            return [self.get(_key, complete) for _key in key]

        # If we get called with a Component/attribute->Component/attribute
        # we treat -> as path separator and the whole key as path into the
        # object.
        if "->" in key:
            # This works recursively.
            key, rest = key.split("->", 1)
            subresult = self.get(key=key, complete=complete)
            if not subresult:
                return None

            return superposition.state_apply(
                subresult, lambda x: x.get(key=rest, complete=complete))

        # The & sigil denotes reverse lookup.
        if key.startswith("&"):
            entities = self.get_referencing_entities(key[1:],
                                                     complete=complete)
            return superposition.meld(*list(entities))

        # The raw result could be None, a superposition or just a scalar.
        value = self.get_raw(key)
        if value is None:
            return obj.NoneObject("Entity '%s' has no results for key '%s'." %
                                  (self, key))

        # Redirection.
        if isinstance(value, entity_component.Alias):
            return self.get(value.alias, complete=complete)

        if isinstance(value, entity_component.Component):
            return CurriedComponent(self, value)

        typedesc = self.reflect_type(key)
        if typedesc.type_name == "Entity":
            entities = self.manager.find_by_identity(value, complete=complete)
            return superposition.meld(*list(entities))

        return value