def add(self, from_object_class_name: str, from_object_uuid: str,
            from_property_name: str, to_object_uuid: str) -> None:
        """
        Add one Weaviate-object reference to this batch. Does NOT validate the consistency of the
        reference against the class schema. Checks the arguments' type and UUIDs' format.

        Parameters
        ----------
        from_object_class_name : str
            The name of the class that should reference another object.
        from_object_uuid : str
            The UUID or URL of the object that should reference another object.
        from_property_name : str
            The name of the property that contains the reference.
        to_object_uuid : str
            The UUID or URL of the object that is actually referenced.

        Raises
        ------
        TypeError
            If arguments are not of type str.
        ValueError
            If 'uuid' is not valid or cannot be extracted.
        """

        if (not isinstance(from_object_class_name, str)
                or not isinstance(from_object_uuid, str)
                or not isinstance(from_property_name, str)
                or not isinstance(to_object_uuid, str)):
            raise TypeError('All arguments must be of type string')

        from_object_uuid = get_valid_uuid(from_object_uuid)
        to_object_uuid = get_valid_uuid(to_object_uuid)

        self._items.append({
            'from':
            'weaviate://localhost/' + from_object_class_name + '/' +
            from_object_uuid + '/' + from_property_name,
            'to':
            'weaviate://localhost/' + to_object_uuid,
        })
    def delete(self, uuid: Union[str, uuid_lib.UUID]) -> None:
        """
        Delete an existing object from weaviate.

        Parameters
        ----------
        uuid : str or uuid.UUID
            The ID of the object that should be deleted.

        Examples
        --------
        >>> client.data_object.get("d842a0f4-ad8c-40eb-80b4-bfefc7b1b530")
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617112817487,
            "id": "d842a0f4-ad8c-40eb-80b4-bfefc7b1b530",
            "lastUpdateTimeUnix": 1617112817487,
            "properties": {
                "age": 46,
                "name": "H.P. Lovecraft"
            },
            "vectorWeights": null
        }
        >>> client.data_object.delete("d842a0f4-ad8c-40eb-80b4-bfefc7b1b530")
        >>> client.data_object.get("d842a0f4-ad8c-40eb-80b4-bfefc7b1b530")
        None

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        TypeError
            If parameter has the wrong type.
        ValueError
            If uuid is not properly formed.
        """

        uuid = get_valid_uuid(uuid)

        try:
            response = self._connection.delete(
                path="/objects/" + uuid,
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Object could not be deleted.') from conn_err
        if response.status_code == 204:
            # Successfully deleted
            return
        raise UnexpectedStatusCodeException("Delete object", response)
    def add(self,
            data_object: dict,
            class_name: str,
            uuid: str = None,
            vector: Sequence = None) -> None:
        """
        Add one object to this batch. Does NOT validate the consistency of the object against
        the client's schema. Checks the arguments' type and UUIDs' format.

        Parameters
        ----------
        class_name : str
            The name of the class this object belongs to.
        data_object : dict
            Object to be added as a dict datatype.
        uuid : str, optional
            UUID of the object as a string, by default None
        vector: Sequence, optional
            The embedding of the object that should be created. Used only class objects that do not
            have a vectorization module. Supported types are `list`, 'numpy.ndarray`,
            `torch.Tensor` and `tf.Tensor`,
            by default None.

        Raises
        ------
        TypeError
            If an argument passed is not of an appropriate type.
        ValueError
            If 'uuid' is not of a propper form.
        """

        if not isinstance(data_object, dict):
            raise TypeError("Object must be of type dict")
        if not isinstance(class_name, str):
            raise TypeError("Class name must be of type str")

        batch_item = {
            "class": class_name,
            "properties": copy.deepcopy(data_object)
        }
        if uuid is not None:
            batch_item["id"] = get_valid_uuid(uuid)

        if vector is not None:
            batch_item["vector"] = get_vector(vector)

        self._items.append(batch_item)
    def _get_response(self,
            uuid: Union[str, uuid_lib.UUID],
            additional_properties: List[str],
            with_vector: bool
        ) -> Response:
        """
        Gets object from weaviate as a requests.Response type. If 'uuid' is None, all objects are
        returned. If 'uuid' is specified the result is the same as for `get_by_uuid` method.

        Parameters
        ----------
        uuid : str
            The identifier of the object that should be retrieved.
        additional_properties : list of str
            list of additional properties that should be included in the request.
        with_vector: bool
            If True the `vector` property will be returned too.

        Returns
        -------
        requests.Response
            Response of the GET REST request.

        Raises
        ------
        TypeError
            If argument is of wrong type.
        ValueError
            If argument contains an invalid value.
        """

        params = _get_params(additional_properties, with_vector)

        if uuid is not None:
            path = "/objects/" + get_valid_uuid(uuid)
        else:
            path = "/objects"

        return self._connection.get(
            path=path,
            params=params
        )
Esempio n. 5
0
    def get(self, classification_uuid: str) -> dict:
        """
        Polls the current state of the given classification.

        Parameters
        ----------
        classification_uuid : str
            Identifier of the classification.

        Returns
        -------
        dict
            A dict containing the Weaviate answer.

        Raises
        ------
        ValueError
            If not a proper uuid.
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        """

        classification_uuid = get_valid_uuid(classification_uuid)

        try:
            response = self._connection.get(
                path='/classifications/' + classification_uuid,
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Classification status could not be retrieved.')\
                from conn_err
        if response.status_code == 200:
            return response.json()
        raise UnexpectedStatusCodeException("Get classification status", response)
    def validate(self,
            data_object: Union[dict, str],
            class_name: str,
            uuid: Union[str, uuid_lib.UUID, None]=None,
            vector: Sequence=None
        ) -> dict:
        """
        Validate an object against weaviate.

        Parameters
        ----------
        data_object : dict or str
            Object to be validated.
            If type is str it should be either an URL or a file.
        class_name : str
            Name of the class of the object that should be validated.
        uuid : str, uuid.UUID or None, optional
            The UUID of the object that should be validated against weaviate.
            by default None.
        vector: Sequence, optional
            The embedding of the object that should be validated. Used only class objects that
            do not have a vectorization module. Supported types are `list`, 'numpy.ndarray`,
            `torch.Tensor` and `tf.Tensor`,
            by default None.

        Examples
        --------
        Assume we have a Author class only 'name' property, NO 'age'.

        >>> client1.data_object.validate(
        ...     data_object = {'name': 'H. Lovecraft'},
        ...     class_name = 'Author'
        ... )
        {'error': None, 'valid': True}
        >>> client1.data_object.validate(
        ...     data_object = {'name': 'H. Lovecraft', 'age': 46},
        ...     class_name = 'Author'
        ... )
        {
            "error": [
                {
                "message": "invalid object: no such prop with name 'age' found in class 'Author'
                    in the schema. Check your schema files for which properties in this class are
                    available"
                }
            ],
            "valid": false
        }

        Returns
        -------
        dict
            Validation result. E.g. {"valid": bool, "error": None or list}

        Raises
        ------
        TypeError
            If argument is of wrong type.
        ValueError
            If argument contains an invalid value.
        weaviate.UnexpectedStatusCodeException
            If validating the object against Weaviate failed with a different reason.
        requests.ConnectionError
            If the network connection to weaviate fails.
        """

        loaded_data_object = _get_dict_from_object(data_object)
        if not isinstance(class_name, str):
            raise TypeError(f"Expected class_name of type `str` but was: {type(class_name)}")

        weaviate_obj = {
            "class": _capitalize_first_letter(class_name),
            "properties": loaded_data_object
        }

        if uuid is not None:
            weaviate_obj['id'] = get_valid_uuid(uuid)

        if vector is not None:
            weaviate_obj['vector'] = get_vector(vector)

        path = "/objects/validate"
        try:
            response = self._connection.post(
                path=path,
                weaviate_object=weaviate_obj
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Object was not validated against weaviate.')\
                from conn_err

        result: dict = {
            "error": None
        }

        if response.status_code == 200:
            result["valid"] = True
            return result
        if response.status_code == 422:
            result["valid"] = False
            result["error"] = response.json()["error"]
            return result
        raise UnexpectedStatusCodeException("Validate object", response)
    def replace(self,
            data_object: Union[dict, str],
            class_name: str,
            uuid: Union[str, uuid_lib.UUID],
            vector: Sequence=None
        ) -> None:
        """
        Replace an already existing object with the given data object.
        This method replaces the whole object.

        Parameters
        ----------
        data_object : dict or str
            Describes the new values. It may be an URL or path to a json
            or a python dict describing the new values.
        class_name : str
            Name of the class of the object that should be updated.
        uuid : str or uuid.UUID
            The UUID of the object that should be changed.
        vector: Sequence, optional
            The embedding of the object that should be replaced. Used only class objects that do not
            have a vectorization module. Supported types are `list`, 'numpy.ndarray`,
            `torch.Tensor` and `tf.Tensor`,
            by default None.

        Examples
        --------
        >>> author_id = client.data_object.create(
        ...     data_object = {'name': 'H. Lovecraft', 'age': 46},
        ...     class_name = 'Author'
        ... )
        >>> client.data_object.get(author_id)
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617112817487,
            "id": "d842a0f4-ad8c-40eb-80b4-bfefc7b1b530",
            "lastUpdateTimeUnix": 1617112817487,
            "properties": {
                "age": 46,
                "name": "H. Lovecraft"
            },
            "vectorWeights": null
        }
        >>> client.data_object.replace(
        ...     data_object = {'name': 'H.P. Lovecraft'},
        ...     class_name = 'Author',
        ...     uuid = author_id
        ... )
        >>> client.data_object.get(author_id)
        {
            "additional": {},
            "class": "Author",
            "id": "d842a0f4-ad8c-40eb-80b4-bfefc7b1b530",
            "lastUpdateTimeUnix": 1617112838668,
            "properties": {
                "name": "H.P. Lovecraft"
            },
            "vectorWeights": null
        }

        Raises
        ------
        TypeError
            If argument is of wrong type.
        ValueError
            If argument contains an invalid value.
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        """

        parsed_object = _get_dict_from_object(data_object)
        uuid = get_valid_uuid(uuid)

        weaviate_obj = {
            "id": uuid,
            "class": _capitalize_first_letter(class_name),
            "properties": parsed_object
        }

        if vector is not None:
            weaviate_obj['vector'] = get_vector(vector)

        path = f"/objects/{uuid}"
        try:
            response = self._connection.put(
                path=path,
                weaviate_object=weaviate_obj
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Object was not replaced.') from conn_err
        if response.status_code == 200:
            # Successful update
            return
        raise UnexpectedStatusCodeException("Replace object", response)
    def create(self,
            data_object: Union[dict, str],
            class_name: str,
            uuid: Union[str, uuid_lib.UUID, None]=None,
            vector: Sequence=None
        ) -> str:
        """
        Takes a dict describing the object and adds it to weaviate.

        Parameters
        ----------
        data_object : dict or str
            Object to be added.
            If type is str it should be either an URL or a file.
        class_name : str
            Class name associated with the object given.
        uuid : str, uuid.UUID or None, optional
            Object will be created under this uuid if it is provided.
            Otherwise weaviate will generate a uuid for this object,
            by default None.
        vector: Sequence, optional
            The embedding of the object that should be created. Used only class objects that do not
            have a vectorization module. Supported types are `list`, 'numpy.ndarray`,
            `torch.Tensor` and `tf.Tensor`,
            by default None.

        Examples
        --------
        Schema contains a class Author with only 'name' and 'age' primitive property.

        >>> client.data_object.create(
        ...     data_object = {'name': 'Neil Gaiman', 'age': 60},
        ...     class_name = 'Author',
        ... )
        '46091506-e3a0-41a4-9597-10e3064d8e2d'
        >>> client.data_object.create(
        ...     data_object = {'name': 'Andrzej Sapkowski', 'age': 72},
        ...     class_name = 'Author',
        ...     uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab'
        ... )
        'e067f671-1202-42c6-848b-ff4d1eb804ab'

        Returns
        -------
        str
            Returns the UUID of the created object if successful.

        Raises
        ------
        TypeError
            If argument is of wrong type.
        ValueError
            If argument contains an invalid value.
        weaviate.ObjectAlreadyExistsException
            If an object with the given uuid already exists within weaviate.
        weaviate.UnexpectedStatusCodeException
            If creating the object in Weaviate failed for a different reason,
            more information is given in the exception.
        requests.ConnectionError
            If the network connection to weaviate fails.
        """

        if not isinstance(class_name, str):
            raise TypeError("Expected class_name of type str but was: "\
                            + str(type(class_name)))
        loaded_data_object = _get_dict_from_object(data_object)

        weaviate_obj = {
            "class": _capitalize_first_letter(class_name),
            "properties": loaded_data_object
        }
        if uuid is not None:
            weaviate_obj["id"] = get_valid_uuid(uuid)

        if vector is not None:
            weaviate_obj["vector"] = get_vector(vector)

        path = "/objects"
        try:
            response = self._connection.post(
                path=path,
                weaviate_object=weaviate_obj
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Object was not added to Weaviate.') from conn_err
        if response.status_code == 200:
            return str(response.json()["id"])

        object_does_already_exist = False
        try:
            if 'already exists' in response.json()['error'][0]['message']:
                object_does_already_exist = True
        except KeyError:
            pass
        if object_does_already_exist:
            raise ObjectAlreadyExistsException(str(uuid))
        raise UnexpectedStatusCodeException("Creating object", response)
    def update(self,
            data_object: Union[dict, str],
            class_name: str,
            uuid: Union[str, uuid_lib.UUID],
            vector: Sequence=None
        ) -> None:
        """
        Update the given object with the already existing object in weaviate.
        Overwrites only the specified fields, the unspecified ones remain unchanged.

        Parameters
        ----------
        data_object : dict or str
            The object states the fields that should be updated.
            Fields not specified by in the 'data_object' remain unchanged.
            Fields that are None will not be changed.
            If type is str it should be either an URL or a file.
        class_name : str
            The class name of the object.
        uuid : str or uuid.UUID
            The ID of the object that should be changed.
        vector: Sequence, optional
            The embedding of the object that should be updated. Used only class objects that do not
            have a vectorization module. Supported types are `list`, 'numpy.ndarray`,
            `torch.Tensor` and `tf.Tensor`,
            by default None.

        Examples
        --------
        >>> author_id = client.data_object.create(
        ...     data_object = {'name': 'Philip Pullman', 'age': 64},
        ...     class_name = 'Author'
        ... )
        >>> client.data_object.get(author_id)
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617111215172,
            "id": "bec2bca7-264f-452a-a5bb-427eb4add068",
            "lastUpdateTimeUnix": 1617111215172,
            "properties": {
                "age": 64,
                "name": "Philip Pullman"
            },
            "vectorWeights": null
        }
        >>> client.data_object.update(
        ...     data_object = {'age': 74},
        ...     class_name = 'Author',
        ...     uuid = author_id
        ... )
        >>> client.data_object.get(author_id)
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617111215172,
            "id": "bec2bca7-264f-452a-a5bb-427eb4add068",
            "lastUpdateTimeUnix": 1617111215172,
            "properties": {
                "age": 74,
                "name": "Philip Pullman"
            },
            "vectorWeights": null
        }

        Raises
        ------
        TypeError
            If argument is of wrong type.
        ValueError
            If argument contains an invalid value.
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none successful status.
        """

        if not isinstance(class_name, str):
            raise TypeError("Class must be type str")

        uuid = get_valid_uuid(uuid)

        object_dict = _get_dict_from_object(data_object)

        weaviate_obj = {
            "id": uuid,
            "class": _capitalize_first_letter(class_name),
            "properties": object_dict
        }

        if vector is not None:
            weaviate_obj['vector'] = get_vector(vector)

        path = f"/objects/{uuid}"

        try:
            response = self._connection.patch(
                path=path,
                weaviate_object=weaviate_obj
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Object was not updated.') from conn_err
        if response.status_code == 204:
            # Successful merge
            return
        raise UnexpectedStatusCodeException("Update of the object not successful", response)
Esempio n. 10
0
    def add(self,
            from_uuid: str,
            from_property_name: str,
            to_uuid: str
        ) -> None:
        """
        Allows to link an object to an object unidirectionally.

        Parameters
        ----------
        from_uuid : str
            The ID of the object that should have the reference as part
            of its properties. Should be a plane UUID or an URL.
            E.g.
            'http://localhost:8080/v1/objects/fc7eb129-f138-457f-b727-1b29db191a67'
            or
            'fc7eb129-f138-457f-b727-1b29db191a67'
        from_property_name : str
            The name of the property within the object.
        to_uuid : str
            The UUID of the object that should be referenced.
            Should be a plane UUID or an URL.
            E.g.
            'http://localhost:8080/v1/objects/fc7eb129-f138-457f-b727-1b29db191a67'
            or
            'fc7eb129-f138-457f-b727-1b29db191a67'

        Examples
        --------
        Assume we have two classes, Author and Book.

        >>> # Create the objects first
        >>> client.data_object.create(
        ...     data_object = {'name': 'Ray Bradbury'},
        ...     class_name = 'Author',
        ...     uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab'
        ... )
        >>> client.data_object.create(
        ...     data_object = {'title': 'The Martian Chronicles'},
        ...     class_name = 'Book',
        ...     uuid = 'a9c1b714-4f8a-4b01-a930-38b046d69d2d'
        ... )
        >>> # Add the cross references
        >>> ## Author -> Book
        >>> client.data_object.reference.add(
        ...     from_uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab', # Author UUID
        ...     from_property_name = 'wroteBooks',
        ...     to_uuid = 'a9c1b714-4f8a-4b01-a930-38b046d69d2d' # Book UUID
        ... )
        >>> client.data_object.get('e067f671-1202-42c6-848b-ff4d1eb804ab') # Author UUID
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617177700595,
            "id": "e067f671-1202-42c6-848b-ff4d1eb804ab",
            "lastUpdateTimeUnix": 1617177700595,
            "properties": {
                "name": "Ray Bradbury",
                "wroteBooks": [
                {
                    "beacon": "weaviate://localhost/a9c1b714-4f8a-4b01-a930-38b046d69d2d",
                    "href": "/v1/objects/a9c1b714-4f8a-4b01-a930-38b046d69d2d"
                }
                ]
            },
            "vectorWeights": null
        }

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        TypeError
            If the parameters are of the wrong type.
        ValueError
            If the parameters are of the wrong value.
        """

        # Validate and create Beacon
        from_uuid = get_valid_uuid(from_uuid)
        to_uuid = get_valid_uuid(to_uuid)
        _validate_property_name(from_property_name)
        beacons = _get_beacon(to_uuid)

        path = f"/objects/{from_uuid}/references/{from_property_name}"
        try:
            response = self._connection.post(
                path=path,
                weaviate_object=beacons
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Reference was not added.') from conn_err
        if response.status_code == 200:
            return
        raise UnexpectedStatusCodeException("Add property reference to object", response)
Esempio n. 11
0
    def delete(self,
            from_uuid: str,
            from_property_name: str,
            to_uuid: str
        ) -> None:
        """
        Remove a reference to another object. Equal to removing one
        direction of an edge from the graph.

        Parameters
        ----------
        from_uuid : str
            The ID of the object that references another object.
        from_property_name : str
            The property from which the reference should be deleted.
        to_uuid : str
            The UUID of the referenced object.

        Examples
        --------
        Assume we have two classes, Author and Book.

        >>> # Create the objects first
        >>> client.data_object.create(
        ...     data_object = {'name': 'Ray Bradbury'},
        ...     class_name = 'Author',
        ...     uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab'
        ... )
        >>> client.data_object.create(
        ...     data_object = {'title': 'The Martian Chronicles'},
        ...     class_name = 'Book',
        ...     uuid = 'a9c1b714-4f8a-4b01-a930-38b046d69d2d'
        ... )
        >>> # Add the cross references
        >>> ## Author -> Book
        >>> client.data_object.reference.add(
        ...     from_uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab', # Author UUID
        ...     from_property_name = 'wroteBooks',
        ...     to_uuid = 'a9c1b714-4f8a-4b01-a930-38b046d69d2d' # Book UUID
        ... )
        >>> client.data_object.get('e067f671-1202-42c6-848b-ff4d1eb804ab') # Author UUID
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617177700595,
            "id": "e067f671-1202-42c6-848b-ff4d1eb804ab",
            "lastUpdateTimeUnix": 1617177700595,
            "properties": {
                "name": "Ray Bradbury",
                "wroteBooks": [
                {
                    "beacon": "weaviate://localhost/a9c1b714-4f8a-4b01-a930-38b046d69d2d",
                    "href": "/v1/objects/a9c1b714-4f8a-4b01-a930-38b046d69d2d"
                }
                ]
            },
            "vectorWeights": null
        }
        >>> # delete the reference
        >>> client.data_object.reference.delete(
        ...     from_uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab', # Author UUID
        ...     from_property_name = 'wroteBooks',
        ...     to_uuid = 'a9c1b714-4f8a-4b01-a930-38b046d69d2d' # Book UUID
        ... )
        >>> >>> client.data_object.get('e067f671-1202-42c6-848b-ff4d1eb804ab') # Author UUID
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617177700595,
            "id": "e067f671-1202-42c6-848b-ff4d1eb804ab",
            "lastUpdateTimeUnix": 1617177864970,
            "properties": {
                "name": "Ray Bradbury",
                "wroteBooks": []
            },
            "vectorWeights": null
        }

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        TypeError
            If parameter has the wrong type.
        ValueError
            If uuid is not properly formed.
        """


        # Validate arguments
        from_uuid = get_valid_uuid(from_uuid)
        to_uuid = get_valid_uuid(to_uuid)
        _validate_property_name(from_property_name)

        # Create the beacon
        beacon = _get_beacon(to_uuid)

        path = f"/objects/{from_uuid}/references/{from_property_name}"
        try:
            response = self._connection.delete(
                path=path,
                weaviate_object=beacon
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Reference was not deleted.') from conn_err
        if response.status_code == 204:
            return
        raise UnexpectedStatusCodeException("Delete property reference to object", response)
Esempio n. 12
0
    def update(self,
            from_uuid: str,
            from_property_name: str,
            to_uuids: Union[list, str]
        ) -> None:
        """
        Allows to update all references in that property with a new set of references.
        All old references will be deleted.

        Parameters
        ----------
        from_uuid : str
            The object that should have the reference as part of its properties.
            Should be in the form of an UUID or in form of an URL.
            E.g.
            'http://localhost:8080/v1/objects/fc7eb129-f138-457f-b727-1b29db191a67'
            or
            'fc7eb129-f138-457f-b727-1b29db191a67'
        from_property_name : str
            The name of the property within the object.
        to_uuids : list or str
            The UUIDs of the objects that should be referenced.
            Should be a list of str in the form of an UUID or str in form of an URL.
            E.g.
            ['http://localhost:8080/v1/objects/fc7eb129-f138-457f-b727-1b29db191a67', ...]
            or
            ['fc7eb129-f138-457f-b727-1b29db191a67', ...]
            If `str` it is converted internally into a list of str.

        Examples
        --------
        You have data object 1 with reference property `wroteBooks` and currently has one reference
        to data object 7. Now you say, I want to update the references of data object 1.wroteBooks
        to this list 3,4,9. After the update, the data object 1.wroteBooks is now 3,4,9, but no
        longer contains 7.

        >>> client.data_object.get('e067f671-1202-42c6-848b-ff4d1eb804ab') # Author UUID
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617177700595,
            "id": "e067f671-1202-42c6-848b-ff4d1eb804ab",
            "lastUpdateTimeUnix": 1617177700595,
            "properties": {
                "name": "Ray Bradbury",
                "wroteBooks": [
                {
                    "beacon": "weaviate://localhost/a9c1b714-4f8a-4b01-a930-38b046d69d2d",
                    "href": "/v1/objects/a9c1b714-4f8a-4b01-a930-38b046d69d2d"
                }
                ]
            },
            "vectorWeights": null
        }
        Currently there is only one `Book` reference.
        Update all the references of the Author for property name `wroteBooks`.
        >>> client.data_object.reference.update(
        ...     from_uuid = 'e067f671-1202-42c6-848b-ff4d1eb804ab', # Author UUID
        ...     from_property_name = 'wroteBooks',
        ...     to_uuids = [
        ...         '8429f68f-860a-49ea-a50b-1f8789515882',
        ...         '3e2e6795-298b-47e9-a2cb-3d8a77a24d8a'
        ...     ]
        ... )
        >>> client.data_object.get('e067f671-1202-42c6-848b-ff4d1eb804ab') # Author UUID
        {
            "additional": {},
            "class": "Author",
            "creationTimeUnix": 1617181292677,
            "id": "e067f671-1202-42c6-848b-ff4d1eb804ab",
            "lastUpdateTimeUnix": 1617181409405,
            "properties": {
                "name": "Ray Bradbury",
                "wroteBooks": [
                {
                    "beacon": "weaviate://localhost/8429f68f-860a-49ea-a50b-1f8789515882",
                    "href": "/v1/objects/8429f68f-860a-49ea-a50b-1f8789515882"
                },
                {
                    "beacon": "weaviate://localhost/3e2e6795-298b-47e9-a2cb-3d8a77a24d8a",
                    "href": "/v1/objects/3e2e6795-298b-47e9-a2cb-3d8a77a24d8a"
                }
                ]
            },
            "vectorWeights": null
        }
        All the previous references were removed and now we have only those specified in the
        `update` method.

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        TypeError
            If the parameters are of the wrong type.
        ValueError
            If the parameters are of the wrong value.
        """

        if not isinstance(to_uuids, list):
            to_uuids = [to_uuids]

        # Validate and create Beacon
        from_uuid = get_valid_uuid(from_uuid)
        _validate_property_name(from_property_name)
        beacons = []
        for to_uuid in to_uuids:
            to_uuid = get_valid_uuid(to_uuid)
            beacons.append(_get_beacon(to_uuid))

        path = f"/objects/{from_uuid}/references/{from_property_name}"
        try:
            response = self._connection.put(
                path=path,
                weaviate_object=beacons
            )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Reference was not updated.') from conn_err
        if response.status_code == 200:
            return
        raise UnexpectedStatusCodeException("Update property reference to object", response)
    def test_get_valid_uuid(self):
        """
        Test the `get_valid_uuid` function.
        """

        # valid calls
        result = get_valid_uuid("weaviate://localhost/28f3f61b-b524-45e0-9bbe-2c1550bf73d2")
        self.assertEqual(result, "28f3f61b-b524-45e0-9bbe-2c1550bf73d2")

        result = get_valid_uuid("weaviate://otherhost.com/28f3f61b-b524-45e0-9bbe-2c1550bf73d2")
        self.assertEqual(result, "28f3f61b-b524-45e0-9bbe-2c1550bf73d2")

        result = get_valid_uuid("http://localhost:8080/v1/objects/1c9cd584-88fe-5010-83d0-017cb3fcb446")
        self.assertEqual(result, "1c9cd584-88fe-5010-83d0-017cb3fcb446")

        result = get_valid_uuid("http://otherhost_2:8080/v1/objects/1c9cd584-88fe-5010-83d0-017cb3fcb446")
        self.assertEqual(result, "1c9cd584-88fe-5010-83d0-017cb3fcb446")

        result = get_valid_uuid("http://otherhost_2:8080/v1/objects/1c9cd58488fe501083d0017cb3fcb446")
        self.assertEqual(result, "1c9cd584-88fe-5010-83d0-017cb3fcb446")

        result = get_valid_uuid("1c9cd584-88fe-5010-83d0-017cb3fcb446")
        self.assertEqual(result, "1c9cd584-88fe-5010-83d0-017cb3fcb446")

        result = get_valid_uuid("1c9cd58488fe501083d0017cb3fcb446")
        self.assertEqual(result, "1c9cd584-88fe-5010-83d0-017cb3fcb446")

        result = get_valid_uuid(uuid_lib.UUID("1c9cd58488fe501083d0017cb3fcb446"))
        self.assertEqual(result, "1c9cd584-88fe-5010-83d0-017cb3fcb446")

        # invalid formats
        type_error_message = "'uuid' must be of type str or uuid.UUID, but was: "
        value_error_message = "Not valid 'uuid' or 'uuid' can not be extracted from value"
        ## neither an object URL nor a weaviate object URL
        with self.assertRaises(ValueError) as error:
            get_valid_uuid("http://localhost:8080/v1/1c9cd584-88fe-5010-83d0-017cb3fcb")
        check_error_message(self, error, value_error_message)

        # wrong UUID format
        with self.assertRaises(ValueError) as error:
            get_valid_uuid("http://localhost:8080/v1/objects/some-UUID")
        check_error_message(self, error, value_error_message)

        ## wrong '/v2', shoudl be '/v1'
        with self.assertRaises(ValueError) as error:
            get_valid_uuid("http://localhost:8080/v2/objects/1c9cd584-88fe-5010-83d0-017cb3fcb")
        check_error_message(self, error, value_error_message)

        ## wrong URL
        with self.assertRaises(ValueError) as error:
            get_valid_uuid("weaviate://INVALID_URL//1c9cd584-88fe-5010-83d0-017cb3fcb")
        check_error_message(self, error, value_error_message)

        ## wrong UUID data type
        with self.assertRaises(TypeError) as error:
            get_valid_uuid(12)
        check_error_message(self, error, type_error_message + str(int))