diff --git a/goblin/driver/graph.py b/goblin/driver/graph.py index 135de07782d4408ca7bdddc29694f5bbb6732719..40299e520f47403a145108966b08de4193550b9e 100644 --- a/goblin/driver/graph.py +++ b/goblin/driver/graph.py @@ -94,7 +94,6 @@ class AsyncRemoteGraph(AsyncGraph): class RemoteElement(metaclass=abc.ABCMeta): - @abc.abstractmethod def __init__(self, id, label, properties=None, **attrs): self._id = id self._label = label @@ -140,10 +139,15 @@ class RemoteVertex(RemoteElement): def __init__(self, id, label, properties=None, **attrs): properties = properties or dict() - props = dict() - for key, value_list in properties.items(): - props[key] = [item['value'] for item in value_list] - super().__init__(id, label, props, **attrs) + for key in properties: + property_list = list() + for prop in properties[key]: + metaproperties = prop.pop('properties', None) + property_id = prop.pop('id') + property_list.append( + RemoteVertexProperty(property_id, label, metaproperties, key=key, element=self, **prop)) + properties[key] = property_list + super().__init__(id, label, properties, **attrs) def property(self, key): props = self.properties(key) @@ -154,33 +158,31 @@ class RemoteVertex(RemoteElement): return props[0] def value(self, key): - props = self.properties(key) - if not props: - raise AttributeError('No property on this object with key: {}'.format(key)) - if len(props) > 1: - raise ValueError(self._value_error_msg.format(key, method="values")) - key, val = props[0] - return val + prop = self.property(key) + if prop is None: + raise KeyError(key) + + return prop.value() def values(self, *keys): - return [v for k, v in self.properties(keys)] + return [prop.value() for prop in self.properties(keys)] def properties(self, *keys): - if keys: - keys = (key for key in keys if key in self._properties) + if len(keys) > 0: + props = list() + for key in keys: + if key in self._properties: + props.extend(self._properties[key]) + return props else: - keys = self._properties.keys() - - props = list() - for key in keys: - for val in self._properties[key]: - props.append((key, val)) - - return props + return list(self._properties.values()) class RemoteEdge(RemoteElement): def __init__(self, id, label, properties=None, **attrs): + properties = properties or dict() + for key in properties: + properties[key] = RemoteProperty(key, properties[key], self) super().__init__(id, label, properties, **attrs) def property(self, key): @@ -190,7 +192,63 @@ class RemoteEdge(RemoteElement): return prop[0] def value(self, key): - return self._properties.get(key) + prop = self.property(key) + if prop is None: + raise KeyError(key) + + return prop.value() + + def values(self, *keys): + return [p.value() for p in self.properties(keys)] + + def properties(self, *keys): + if len(keys) > 0: + props = (self._properties[key] for key in keys if key in self._properties) + else: + props = self._properties.values() + return list(props) + + +class RemoteProperty: + def __init__(self, key, value, element): + self._key = key + self._value = value + self._element = element + + def element(self): + return self._element + + def key(self): + return self._key + + def value(self): + return self._value + + +class RemoteVertexProperty(RemoteElement): + def __init__(self, id, label, properties=None, **attrs): + self._key = attrs.pop('key') + self._value = attrs.pop('value') + self._element = attrs.pop('element') + properties = properties or dict() + for key in properties: + properties[key] = RemoteProperty(key, properties[key], self) + super().__init__(id, label, properties, **attrs) + + def property(self, key): + prop = self.properties(key) + if not prop: + return None + return prop[0] + + def key(self): + return self._key + + def value(self, key=None): + if key is not None: + return self._properties.get(key) + else: + return self._value def values(self, *keys): return [v for k, v in self.properties(keys)] @@ -201,3 +259,6 @@ class RemoteEdge(RemoteElement): else: props = self._properties.items() return list(props) + + def element(self): + return self._element