Exemplo n.º 1
0
    def save(self, *args, **kwargs):
        """
        Save this edge to the graph database.
        """
        super(Edge, self).save()
        future = connection.get_future(kwargs)
        future_result = self._save_edge(self._outV,
                                        self._inV,
                                        self.get_label(),
                                        self.as_save_params(),
                                        exclusive=self.__exclusive__,
                                        **kwargs)

        def on_read(f2):
            try:
                result = f2.result()[0]
            except Exception as e:
                future.set_exception(e)
            else:
                future.set_result(result)

        def on_save(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_save)

        return future
Exemplo n.º 2
0
    def delete(self, **kwargs):
        """
        Delete the current edge from the graph.
        """
        if self.__abstract__:  # pragma: no cover
            raise GoblinQueryError('cant delete abstract elements')
        if self._id is None:
            return self

        future = connection.get_future(kwargs)
        future_result = self._delete_edge()

        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future.set_result(result)

        def on_delete(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_delete)

        return future
Exemplo n.º 3
0
    def _reload_values(self, *args, **kwargs):
        """
        Method for reloading the current vertex by reading its current values
        from the database.

        """
        reloaded_values = {}
        future = connection.get_future(kwargs)
        future_result = connection.execute_query(
            'g.V(vid)', {'vid': self._id}, **kwargs)

        def on_read(f2):
            try:
                result = f2.result()
                result = result.data[0]
            except Exception as e:
                future.set_exception(e)
            else:
                # del result['type']  # don't think I need this
                reloaded_values['id'] = result['id']
                for name, value in result.get('properties', {}).items():
                    # This is a hack until decide how to deal with props
                    reloaded_values[name] = value[0]['value']
                future.set_result(reloaded_values)

        def on_reload_values(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)
        future_result.add_done_callback(on_reload_values)
        return future
    def _get_simple(self, deserialize, **kwargs):
        script = "g.V(vid)"
        future_results = self._get_stream(script, deserialize, **kwargs)
        future = connection.get_future(kwargs)

        def on_read(f):
            try:
                result = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                if not result:
                    future.set_exception(GoblinQueryError("Does not exist"))
                future.set_result(result[0])

        def on_stream(f2):
            try:
                stream = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_results.add_done_callback(on_stream)
        return future
Exemplo n.º 5
0
    def save(self, *args, **kwargs):
        """
        Save this edge to the graph database.
        """
        super(Edge, self).save()
        future = connection.get_future(kwargs)
        future_result = self._save_edge(self._outV,
                                        self._inV,
                                        self.get_label(),
                                        self.as_save_params(),
                                        exclusive=self.__exclusive__,
                                        **kwargs)

        def on_read(f2):
            try:
                result = f2.result()[0]
            except Exception as e:
                future.set_exception(e)
            else:
                future.set_result(result)

        def on_save(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_save)

        return future
Exemplo n.º 6
0
    def delete(self, **kwargs):
        """
        Delete the current edge from the graph.
        """
        if self.__abstract__:  # pragma: no cover
            raise GoblinQueryError('cant delete abstract elements')
        if self._id is None:
            return self

        future = connection.get_future(kwargs)
        future_result = self._delete_edge()

        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future.set_result(result)

        def on_delete(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_delete)

        return future
Exemplo n.º 7
0
    def outV(self, *args, **kwargs):
        """
        Return the vertex that this edge goes into.

        :rtype: Vertex

        """
        from goblin.models.vertex import Vertex
        future = connection.get_future(kwargs)
        if self._inV is None:
            future_results = self._simple_traversal('outV', **kwargs)

            def on_traversal(f):
                try:
                    result = f.result()
                except Exception as e:
                    future.set_exception(e)
                else:
                    self._outV = result[0]
                    if isinstance(self._outV, string_types + integer_types):
                        future_results = Vertex.get(self._outV, **kwargs)

                        def on_get(f2):
                            try:
                                result = f2.result()
                            except Exception as e:
                                future.set_exception(e)
                            else:
                                self._outV = result

                        future_results.add_done_callback(on_get)
                    future.set_result(self._outV)
                future_results.add_done_callback(on_traversal)

        elif isinstance(self._outV, string_types + integer_types):
            future_results = Vertex.get(self._outV, **kwargs)

            def on_get(f2):
                try:
                    result = f2.result()
                except Exception as e:
                    future.set_exception(e)
                else:
                    self._outV = result
                    future.set_result(self._outV)

            future_results.add_done_callback(on_get)
        else:
            future.set_result(self._outV)
        return future
Exemplo n.º 8
0
    def outV(self, *args, **kwargs):
        """
        Return the vertex that this edge goes into.

        :rtype: Vertex

        """
        from goblin.models.vertex import Vertex
        future = connection.get_future(kwargs)
        if self._inV is None:
            future_results = self._simple_traversal('outV', **kwargs)

            def on_traversal(f):
                try:
                    result = f.result()
                except Exception as e:
                    future.set_exception(e)
                else:
                    self._outV = result[0]
                    if isinstance(self._outV, string_types + integer_types):
                        future_results = Vertex.get(self._outV, **kwargs)

                        def on_get(f2):
                            try:
                                result = f2.result()
                            except Exception as e:
                                future.set_exception(e)
                            else:
                                self._outV = result

                        future_results.add_done_callback(on_get)
                    future.set_result(self._outV)
                future_results.add_done_callback(on_traversal)

        elif isinstance(self._outV, string_types + integer_types):
            future_results = Vertex.get(self._outV, **kwargs)

            def on_get(f2):
                try:
                    result = f2.result()
                except Exception as e:
                    future.set_exception(e)
                else:
                    self._outV = result
                    future.set_result(self._outV)

            future_results.add_done_callback(on_get)
        else:
            future.set_result(self._outV)
        return future
Exemplo n.º 9
0
    def get(cls, id, *args, **kwargs):
        """
        Look up edge by titan assigned ID. Raises a DoesNotExist exception if
        an edge with the given edge id was not found. Raises a
        MultipleObjectsReturned exception if the edge_id corresponds to more
        than one edge in the graph.

        :param id: The titan assigned ID
        :type id: str | basestring
        :rtype: goblin.models.Edge
        """
        if not id:
            raise cls.DoesNotExist
        future = connection.get_future(kwargs)
        future_result = cls.all([id], **kwargs)

        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                if len(result) > 1:  # pragma: no cover
                    # This requires titan to be broken.
                    e = cls.MultipleObjectsReturned
                    future.set_exception(e)
                else:
                    result = result[0]
                    if not isinstance(result, cls):
                        e = cls.WrongElementType(
                            '%s is not an instance or subclass of %s' % (
                                result.__class__.__name__, cls.__name__))
                        future.set_exception(e)
                    else:
                        future.set_result(result)

        def on_get(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_get)

        return future
Exemplo n.º 10
0
    def _simple_deletion(self, operation, labels, **kwargs):
        """
        Perform simple bulk graph deletion operation.

        :param operation: The operation to be performed
        :type operation: str
        :param labels: The edge label to be used
        :type labels: str or Edge

        """
        from goblin.models.edge import Edge

        label_strings = []
        for label in labels:
            if inspect.isclass(label) and issubclass(label, Edge):
                label_string = label.get_label()
            elif isinstance(label, Edge):
                label_string = label.get_label()
            elif isinstance(label, string_types):
                label_string = label
            else:
                raise GoblinException("traversal labels must be edge " +
                                      "classes, instances, or strings")
            label_strings.append(label_string)

        future = connection.get_future(kwargs)
        future_result = self._delete_related(operation, label_strings)

        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future.set_result(result)

        def on_save(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_save)

        return future
Exemplo n.º 11
0
    def get(cls, id, *args, **kwargs):
        """
        Look up edge by titan assigned ID. Raises a DoesNotExist exception if
        an edge with the given edge id was not found. Raises a
        MultipleObjectsReturned exception if the edge_id corresponds to more
        than one edge in the graph.

        :param id: The titan assigned ID
        :type id: str | basestring
        :rtype: goblin.models.Edge
        """
        if not id:
            raise cls.DoesNotExist
        future = connection.get_future(kwargs)
        future_result = cls.all([id], **kwargs)

        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                if len(result) > 1:  # pragma: no cover
                    # This requires titan to be broken.
                    e = cls.MultipleObjectsReturned
                    future.set_exception(e)
                else:
                    result = result[0]
                    if not isinstance(result, cls):
                        e = cls.WrongElementType(
                            '%s is not an instance or subclass of %s' %
                            (result.__class__.__name__, cls.__name__))
                        future.set_exception(e)
                    else:
                        future.set_result(result)

        def on_get(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_get)

        return future
Exemplo n.º 12
0
    def find_by_value(cls, field, value, as_dict=False, **kwargs):
        """
        Returns edges that match the given field/value pair.

        :param field: The field to search
        :type field: str
        :param value: The value of the field
        :type value: str
        :param as_dict: Return results as a dictionary
        :type as_dict: boolean
        :rtype: [goblin.models.Edge]
        """
        _field = cls.get_property_by_name(field)
        _label = cls.get_label()

        value_type = False
        if isinstance(value, integer_types + float_types):
            value_type = True

        future = connection.get_future(kwargs)
        future_results = cls._find_edge_by_value(
            value_type=value_type,
            elabel=_label,
            field=_field,
            val=value
        )

        def by_value_handler(data):
            if data is None:
                data = []
            if as_dict:  # pragma: no cover
                data = {v._id: v for v in data}
            return data

        def on_find_by_value(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                stream.add_handler(by_value_handler)
                future.set_result(stream)

        future_results.add_done_callback(on_find_by_value)

        return future
Exemplo n.º 13
0
 def __call__(self, instance, *args, **kwargs):
     future_results = super(GremlinMethod, self).__call__(
         instance, *args, **kwargs)
     deserialize = kwargs.get('deserialize', True)
     if deserialize:
         future = connection.get_future(kwargs)
         def on_call(f):
             try:
                 stream = f.result()
             except Exception as e:
                 future.set_exception(e)
             else:
                 stream.add_handler(GremlinMethod._deserialize)
                 future.set_result(stream)
         future_results.add_done_callback(on_call)
         return future
     return future_results
Exemplo n.º 14
0
    def find_by_value(cls, field, value, as_dict=False, **kwargs):
        """
        Returns edges that match the given field/value pair.

        :param field: The field to search
        :type field: str
        :param value: The value of the field
        :type value: str
        :param as_dict: Return results as a dictionary
        :type as_dict: boolean
        :rtype: [goblin.models.Edge]
        """
        _field = cls.get_property_by_name(field)
        _label = cls.get_label()

        value_type = False
        if isinstance(value, integer_types + float_types):
            value_type = True

        future = connection.get_future(kwargs)
        future_results = cls._find_edge_by_value(value_type=value_type,
                                                 elabel=_label,
                                                 field=_field,
                                                 val=value)

        def by_value_handler(data):
            if data is None:
                data = []
            if as_dict:  # pragma: no cover
                data = {v._id: v for v in data}
            return data

        def on_find_by_value(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                stream.add_handler(by_value_handler)
                future.set_result(stream)

        future_results.add_done_callback(on_find_by_value)

        return future
Exemplo n.º 15
0
    def __call__(self, instance, *args, **kwargs):
        future = connection.get_future(kwargs)
        future_result = super(GremlinValue, self).__call__(instance, *args,
                                                           **kwargs)

        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                from goblin.models.element import Element
                if result is None:  # pragma: no cover
                    future.set_result(None)
                # we have to make a special case for dictionaries, python
                # len returns number of keys, even though it is one
                # object. Don't do the same for lists or tuples, since
                # they arevGremlin Methods not GremlinValues.
                elif isinstance(result, dict):
                    future.set_result(result)
                elif isinstance(result,
                                integer_types + float_types + string_types):
                    future.set_result(result)
                elif isinstance(result, Element):
                    future.set_result(result)
                elif len(result) != 1:
                    e = GoblinGremlinException(
                        '''GremlinValue requires a single value is
                           returned (%s returned)''' % len(result))
                    future.set_exception(e)
                else:
                    future.set_result(result[0])

        def on_call(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_call)
        return future
Exemplo n.º 16
0
    def save(self, *args, **kwargs):
        """
        Save the current vertex using the configured save strategy, the default
        save strategy is to re-save all fields every time the object is saved.
        """
        super(Vertex, self).save()
        params = self.as_save_params()
        label = self.get_label()
        # params['element_type'] = self.get_element_type()  don't think we need
        # Here this is a future, have to set handler in callback
        future = connection.get_future(kwargs)
        future_result = self._save_vertex(label, params, **kwargs)
        deserialize = kwargs.pop('deserialize', True)
        def on_read(f2):
            try:
                result = f2.result()
            except Exception as e:
                future.set_exception(e)
            else:
                if deserialize:
                    result = result[0]
                    self._id = result._id
                    for k, v in self._values.items():
                        v.previous_value = result._values[k].previous_value
                else:
                    result = result.data
                future.set_result(result)

        def on_save(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_save)

        return future
Exemplo n.º 17
0
def _property_handler(script, graph_name, **kwargs):
    future = connection.get_future(kwargs)
    future_response = connection.execute_query(script, graph_name=graph_name)

    def on_read(f2):
        try:
            result = f2.result()
        except Exception as e:
            future.set_exception(e)
        else:
            future.set_result(result)

    def on_key(f):
        try:
            stream = f.result()
        except Exception as e:
            future.set_exception(e)
        else:
            future_read = stream.read()
            future_read.add_done_callback(on_read)

    future_response.add_done_callback(on_key)
    return future
Exemplo n.º 18
0
    def _reload_values(self, *args, **kwargs):
        """ Re-read the values for this edge from the graph database. """
        reloaded_values = {}
        future = connection.get_future(kwargs)
        future_result = connection.execute_query(
            'g.E(eid)', {'eid': self._id}, **kwargs)

        def on_read(f2):
            try:
                result = f2.result()
                result = result.data[0]
            except Exception as e:
                future.set_exception(e)
            else:
                if result:
                    # del result['type']
                    reloaded_values['id'] = result['id']
                    for name, value in result.get('properties', {}).items():
                        reloaded_values[name] = value
                    if result['id']:
                        setattr(self, 'id', result['id'])
                    future.set_result(reloaded_values)
                else:
                    future.set_result({})

        def on_reload(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_reload)

        return future
Exemplo n.º 19
0
    def _reload_values(self, *args, **kwargs):
        """ Re-read the values for this edge from the graph database. """
        reloaded_values = {}
        future = connection.get_future(kwargs)
        future_result = connection.execute_query('g.E(eid)', {'eid': self._id},
                                                 **kwargs)

        def on_read(f2):
            try:
                result = f2.result()
                result = result.data[0]
            except Exception as e:
                future.set_exception(e)
            else:
                if result:
                    # del result['type']
                    reloaded_values['id'] = result['id']
                    for name, value in result.get('properties', {}).items():
                        reloaded_values[name] = value
                    if result['id']:
                        setattr(self, 'id', result['id'])
                    future.set_result(reloaded_values)
                else:
                    future.set_result({})

        def on_reload(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                future_read = stream.read()
                future_read.add_done_callback(on_read)

        future_result.add_done_callback(on_reload)

        return future
Exemplo n.º 20
0
    def reload(self, *args, **kwargs):
        """
        Reload the given element from the database.

        """
        future = connection.get_future(kwargs)
        future_values = self._reload_values(**kwargs)

        def on_reload(f):
            try:
                values = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                for name, prop in self._properties.items():
                    value = values.get(prop.db_field_name, None)
                    if value is not None:
                        value = prop.to_python(value)
                    setattr(self, name, value)
                future.set_result(self)

        future_values.add_done_callback(on_reload)

        return future
Exemplo n.º 21
0
    def all(cls, ids=[], as_dict=False, match_length=True, *args, **kwargs):
        """
        Load all vertices with the given ids from the graph. By default this
        will return a list of vertices but if as_dict is True then it will
        return a dictionary containing ids as keys and vertices found as
        values.

        :param ids: A list of titan ids
        :type ids: list
        :param as_dict: Toggle whether to return a dictionary or list
        :type as_dict: boolean
        :rtype: dict | list

        """
        if not isinstance(ids, array_types):
            raise GoblinQueryError("ids must be of type list or tuple")

        deserialize = kwargs.pop('deserialize', True)
        handlers = []
        future = connection.get_future(kwargs)
        if len(ids) == 0:
            future_results = connection.execute_query(
                'g.V.hasLabel(x)', bindings={"x": cls.get_label()}, **kwargs)

        else:
            strids = [str(i) for i in ids]
            # Need to test sending complex bindings with client
            vids = ", ".join(strids)
            future_results = connection.execute_query(
                'g.V(%s)' % vids, **kwargs)

            def id_handler(results):
                try:
                    results = list(filter(None, results))
                except TypeError:
                    raise cls.DoesNotExist
                if len(results) != len(ids) and match_length:
                    raise GoblinQueryError(
                        "the number of results don't match the number of " +
                        "ids requested")
                return results

            handlers.append(id_handler)

        def result_handler(results):
            objects = []
            for r in results:
                if deserialize:
                    try:
                        objects += [Element.deserialize(r)]
                    except KeyError:  # pragma: no cover
                        raise GoblinQueryError(
                            'Vertex type "%s" is unknown' % r.get('label', ''))
                else:
                    objects = results

            if as_dict:  # pragma: no cover
                return {v._id: v for v in objects}

            return objects

        handlers.append(result_handler)

        def on_all(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                [stream.add_handler(h) for h in handlers]
                future.set_result(stream)

        future_results.add_done_callback(on_all)

        return future
Exemplo n.º 22
0
    def _simple_traversal(self,
                          operation,
                          labels,
                          limit=None,
                          offset=None,
                          types=None,
                          **kwargs):
        """
        Perform simple graph database traversals with ubiquitous pagination.

        :param operation: The operation to be performed
        :type operation: str
        :param labels: The edge labels to be used
        :type labels: list of Edges or strings
        :param start: The starting offset
        :type start: int
        :param max_results: The maximum number of results to return
        :type max_results: int
        :param types: The list of allowed result elements
        :type types: list

        """
        from goblin.models.edge import Edge
        label_strings = []
        for label in labels:
            if inspect.isclass(label) and issubclass(label, Edge):
                label_string = label.get_label()
            elif isinstance(label, Edge):
                label_string = label.get_label()
            elif isinstance(label, string_types):
                label_string = label
            else:
                raise GoblinException("traversal labels must be edge " +
                                      "classes, instances, or strings")
            label_strings.append(label_string)

        allowed_elts = None
        if types is not None:
            allowed_elts = []
            for e in types:
                if issubclass(e, Vertex):
                    allowed_elts += [e.get_label()]
                elif issubclass(e, Edge):
                    allowed_elts += [e.get_label()]

        if limit is not None and offset is not None:
            start = offset
            end = offset + limit
        else:
            start = end = None
        future = connection.get_future(kwargs)
        future_result = self._traversal(operation,
                                        label_strings,
                                        start,
                                        end,
                                        allowed_elts)

        def traversal_handler(data):
            if data is None:
                data = []
            return data

        def on_traversal(f):
            try:
                stream = f.result()
            except Exception as e:
                future.set_exception(e)
            else:
                stream.add_handler(traversal_handler)
                future.set_result(stream)

        future_result.add_done_callback(on_traversal)
        return future