def testApplication(self): """Test function application across states.""" self.assertEqual( superposition.superposition(2, 4), superposition.state_apply(superposition.superposition(1, 2), lambda x: x * 2)) # As everything working on states, this should also work on scalars. applied = superposition.state_apply(5, lambda x: x * 2) self.assertTrue(superposition.state_eq(10, applied))
def testApplication(self): """Test function application across states.""" self.assertEqual( superposition.superposition(2, 4), superposition.state_apply( superposition.superposition(1, 2), lambda x: x * 2)) # As everything working on states, this should also work on scalars. applied = superposition.state_apply(5, lambda x: x * 2) self.assertTrue(superposition.state_eq(10, applied))
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
def coerce(self, value): if value == None: return None decoder = lambda s: str(s).decode("utf-8", "ignore") return superposition.state_apply(value, decoder)
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