Example #1
0
    def get_clusters(self) -> Optional[List[str]]:
        """
        Lists all weaviate clusters registered with the this account.

        Returns
        -------
        Optional[List[str]]
            A list of cluster names or None if no clusters.

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If getting the weaviate clusters failed for a different reason,
            more information is given in the exception.
        """

        try:
            response = self.get(
                path='/clusters/list',
                params={
                    'email':
                    self._auth_client_secret.get_credentials()['username']
                })
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError(
                'WCS clusters were not fetched.') from conn_err
        if response.status_code == 200:
            return response.json()['clusterIDs']
        raise UnexpectedStatusCodeException('Checking WCS instance', response)
Example #2
0
    def get_cluster_config(self, cluster_name: str) -> dict:
        """
        Get details of a cluster.

        Parameters
        ----------
        cluster_name : str
            The name of the weaviate server cluster.
            NOTE: Case insensitive. The WCS cluster's name is always lowercased.

        Returns
        -------
        dict
            Details in a JSON format. If no cluster with such name was found then an empty
            dictionary is returned.

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If getting the weaviate cluster failed for a different reason,
            more information is given in the exception.
        """

        try:
            response = self.get(path='/clusters/' + cluster_name.lower(), )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError(
                'WCS cluster info was not fetched.') from conn_err
        if response.status_code == 200:
            return response.json()
        if response.status_code == 404:
            return {}
        raise UnexpectedStatusCodeException('Checking WCS instance', response)
Example #3
0
    def test_get_cluster_config(self, mock_get):
        """
        Test the `get_cluster_config` method.
        """

        wcs = WCS(AuthClientPassword('test_secret_username', 'test_secret_password'))
        wcs._auth_bearer = 'test_bearer'

        # invalid calls

        ## error messages
        connection_error_message = 'WCS cluster info was not fetched.'
        unexpected_error_message = 'Checking WCS instance'

        ## connection error
        mock_get.side_effect = RequestsConnectionError('Test!')
        with self.assertRaises(RequestsConnectionError) as error:
            wcs.get_cluster_config('test_name')
        check_error_message(self, error, connection_error_message)
        mock_get.assert_called_with(
            path='/clusters/test_name',
        )

        ## unexpected error
        mock_get.side_effect = None
        mock_get.return_value = Mock(status_code=400)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            wcs.get_cluster_config('test_name')
        check_startswith_error_message(self, error, unexpected_error_message)
        mock_get.assert_called_with(
            path='/clusters/test_name',
        )

        # valid calls
        return_mock = Mock(status_code=200)
        return_mock.json.return_value = {'clusterIDs': 'test!'}
        mock_get.return_value = return_mock
        result = wcs.get_cluster_config('test_name')
        self.assertEqual(result, {'clusterIDs': 'test!'})
        mock_get.assert_called_with(
            path='/clusters/test_name',
        )

        return_mock = Mock(status_code=200)
        return_mock.json.return_value = {'clusterIDs': 'test!'}
        mock_get.return_value = return_mock
        result = wcs.get_cluster_config('Test_Name')
        self.assertEqual(result, {'clusterIDs': 'test!'})
        mock_get.assert_called_with(
            path='/clusters/test_name',
        )

        return_mock = Mock(status_code=404)
        return_mock.json.return_value = {'clusterIDs': 'test!'}
        mock_get.return_value = return_mock
        result = wcs.get_cluster_config('test_name')
        self.assertEqual(result, {})
        mock_get.assert_called_with(
            path='/clusters/test_name',
        )
    def test_get_concept_vector(self):
        """
        Test `get_concept_vector` method.
        """

        # test valid call
        connection_mock = mock_connection_method('get', return_json={"A": "B"})
        contextionary = Contextionary(connection_mock)
        self.assertEqual("B", contextionary.get_concept_vector("sauce")["A"])
        connection_mock.get.assert_called_with(
            path="/modules/text2vec-contextionary/concepts/sauce", )

        # test exceptions

        # error messages
        requests_error_message = 'text2vec-contextionary vector was not retrieved.'
        unexpected_exception_error_message = "text2vec-contextionary vector"

        ## test UnexpectedStatusCodeException
        contextionary = Contextionary(
            mock_connection_method('get', status_code=404))
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            contextionary.get_concept_vector("Palantir")
        check_startswith_error_message(self, error,
                                       unexpected_exception_error_message)

        ## test requests error
        contextionary = Contextionary(
            mock_connection_method(
                'get', side_effect=RequestsConnectionError("Test!")))
        with self.assertRaises(RequestsConnectionError) as error:
            contextionary.get_concept_vector("Palantir")
        check_error_message(self, error, requests_error_message)
Example #5
0
    def do(self) -> dict:
        """
        Builds and runs the query.

        Returns
        -------
        dict
            The response of the query.

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

        query = self.build()

        try:
            response = self._connection.post(path="/graphql",
                                             weaviate_object={"query": query})
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError(
                'Query was not successful.') from conn_err
        if response.status_code == 200:
            return response.json()  # success
        raise UnexpectedStatusCodeException("Query was not successful",
                                            response)
    def delete_class(self, class_name: str) -> None:
        """
        Delete a schema class from weaviate. This deletes all associated data.

        Parameters
        ----------
        class_name : str
            The class that should be deleted from weaviate.

        Examples
        --------
        >>> client.schema.delete_class('Author')

        Raises
        ------
        TypeError
            If 'class_name' argument not of type str.
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        """

        if not isinstance(class_name, str):
            raise TypeError(
                f"Class name was {type(class_name)} instead of str")

        path = f"/schema/{_capitalize_first_letter(class_name)}"
        try:
            response = self._connection.delete(path=path)
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Deletion of class.') from conn_err
        if response.status_code != 200:
            raise UnexpectedStatusCodeException("Delete class from schema",
                                                response)
    def update_config(self, class_name: str, config: dict) -> None:
        """
        Update a schema configuration for a specific class.

        Parameters
        ----------
        class_name : str
            The class for which to update the schema configuration.
        config : dict
            The configurations to update (MUST follow schema format).

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

        class_name = _capitalize_first_letter(class_name)
        class_schema = self.get(class_name)
        new_class_schema = _update_nested_dict(class_schema, config)
        check_class(new_class_schema)

        path = "/schema/" + class_name
        try:
            response = self._connection.put(path=path,
                                            weaviate_object=new_class_schema)
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Class schema configuration could not be updated.')\
                from conn_err
        if response.status_code != 200:
            raise UnexpectedStatusCodeException(
                "Update class schema configuration", response)
    def _start(self) -> dict:
        """
        Start the classification based on the configuration set.

        Returns
        -------
        dict
            Classification result.

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            Unexpected error.
        """

        try:
            response = self._connection.post(path='/classifications',
                                             weaviate_object=self._config)
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError(
                'Classification may not started.') from conn_err
        if response.status_code == 201:
            return response.json()
        raise UnexpectedStatusCodeException("Start classification", response)
Example #9
0
    def delete_cluster(self, cluster_name: str) -> None:
        """
        Delete the WCS Weaviate cluster instance.

        Parameters
        ----------
        cluster_name : str
            The name of the weaviate server cluster.
            NOTE: Case insensitive. The WCS cluster's name is always lowercased.

        Raises
        ------
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.UnexpectedStatusCodeException
            If deleting the weaviate cluster failed for a different reason,
            more information is given in the exception.
        """

        try:
            response = self.delete(path='/clusters/' + cluster_name.lower(), )
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError(
                'WCS cluster was not deleted.') from conn_err
        if response.status_code == 200 or response.status_code == 404:
            return
        raise UnexpectedStatusCodeException('Deleting WCS instance', response)
    def test_get(self, mock_get_params):
        """
        Test the `get` method.
        """

        # error messages
        requests_error_message = 'Could not get object/s.'
        unexpected_error_message = "Get object/s"

        # test exceptions

        data_object = DataObject(
            mock_connection_method('get', side_effect=RequestsConnectionError("Test!"))
        )
        with self.assertRaises(RequestsConnectionError) as error:
            data_object.get()
        check_error_message(self, error, requests_error_message)
        
        data_object = DataObject(
            mock_connection_method('get', status_code=204)
        )
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            data_object.get()
        check_startswith_error_message(self, error, unexpected_error_message)

        # test valid calls
        return_value_get = {"my_key": 12341}
        mock_get_params.return_value = {'include': "test1,test2"}
        connection_mock = mock_connection_method('get', return_json=return_value_get, status_code=200)
        data_object = DataObject(connection_mock)
        result = data_object.get()
        self.assertEqual(result, return_value_get)
        connection_mock.get.assert_called_with(
            path="/objects",
            params={'include': "test1,test2"}
        )

        return_value_get = {"my_key": '12341'}
        mock_get_params.return_value = {'include': "test1,test2"}
        connection_mock = mock_connection_method('get', return_json=return_value_get, status_code=200)
        data_object = DataObject(connection_mock)
        result = data_object.get(uuid="1d420c9c98cb11ec9db61e008a366d49")
        self.assertEqual(result, return_value_get)
        connection_mock.get.assert_called_with(
            path="/objects/1d420c9c-98cb-11ec-9db6-1e008a366d49",
            params={'include': "test1,test2"}
        )

        return_value_get = {"my_key": '12341'}
        mock_get_params.return_value = {'include': "test1,test2"}
        connection_mock = mock_connection_method('get', return_json=return_value_get, status_code=404)
        data_object = DataObject(connection_mock)
        result = data_object.get(uuid="1d420c9c-98cb-11ec-9db6-1e008a366d49")
        self.assertIsNone(result)
        connection_mock.get.assert_called_with(
            path="/objects/1d420c9c-98cb-11ec-9db6-1e008a366d49",
            params={'include': "test1,test2"}
        )
    def create(self, schema_class_name: str, schema_property: dict) -> None:
        """
        Create a class property.

        Parameters
        ----------
        schema_class_name : str
            The name of the class in the schema to which the property
            should be added.
        schema_property : dict
            The property that should be added.

        Examples
        --------
        >>> property_age = {
        ...     "dataType": [
        ...         "int"
        ...     ],
        ...     "description": "The Author's age",
        ...     "name": "age"
        ... }
        >>> client.schema.property.create('Author', property_age)

        Raises
        ------
        TypeError
            If 'schema_class_name' is of wrong type.
        weaviate.exceptions.UnexpectedStatusCodeException
            If weaviate reports a none OK status.
        requests.ConnectionError
            If the network connection to weaviate fails.
        weaviate.SchemaValidationException
            If the 'schema_property' is not valid.
        """

        if not isinstance(schema_class_name, str):
            raise TypeError(
                f"Class name must be of type str but is {type(schema_class_name)}"
            )

        loaded_schema_property = _get_dict_from_object(schema_property)

        # check if valid property
        check_property(loaded_schema_property)

        schema_class_name = _capitalize_first_letter(schema_class_name)

        path = f"/schema/{schema_class_name}/properties"
        try:
            response = self._connection.post(
                path=path, weaviate_object=loaded_schema_property)
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError(
                'Property was created properly.') from conn_err
        if response.status_code != 200:
            raise UnexpectedStatusCodeException("Add property to class",
                                                response)
    def _create_complex_properties_from_class(self,
                                              schema_class: dict) -> None:
        """
        Add crossreferences to already existing class.

        Parameters
        ----------
        schema_class : dict
            Description of the class that should be added.

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

        if "properties" not in schema_class:
            # Class has no properties nothing to do
            return
        for property_ in schema_class["properties"]:

            if _property_is_primitive(property_["dataType"]):
                continue

            # create the property object
            ## All complex dataTypes should be capitalized.
            schema_property = {
                "dataType": [
                    _capitalize_first_letter(dtype)
                    for dtype in property_["dataType"]
                ],
                "description":
                property_["description"],
                "name":
                property_["name"]
            }

            if "indexInverted" in property_:
                schema_property["indexInverted"] = property_["indexInverted"]

            if "moduleConfig" in property_:
                schema_property["moduleConfig"] = property_["moduleConfig"]

            path = "/schema/" + _capitalize_first_letter(
                schema_class["class"]) + "/properties"
            try:
                response = self._connection.post(
                    path=path, weaviate_object=schema_property)
            except RequestsConnectionError as conn_err:
                raise RequestsConnectionError('Property may not have been created properly.')\
                    from conn_err
            if response.status_code != 200:
                raise UnexpectedStatusCodeException(
                    "Add properties to classes", response)
    def _create_class_with_premitives(self, weaviate_class: dict) -> None:
        """
        Create class with only primitives.

        Parameters
        ----------
        weaviate_class : dict
            A single weaviate formated class

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

        # Create the class
        schema_class = {
            "class": _capitalize_first_letter(weaviate_class['class']),
            "properties": []
        }

        if "description" in weaviate_class:
            schema_class['description'] = weaviate_class['description']

        if "vectorIndexType" in weaviate_class:
            schema_class['vectorIndexType'] = weaviate_class['vectorIndexType']

        if "vectorIndexConfig" in weaviate_class:
            schema_class['vectorIndexConfig'] = weaviate_class[
                'vectorIndexConfig']

        if "vectorizer" in weaviate_class:
            schema_class['vectorizer'] = weaviate_class['vectorizer']

        if "moduleConfig" in weaviate_class:
            schema_class["moduleConfig"] = weaviate_class["moduleConfig"]

        if "shardingConfig" in weaviate_class:
            schema_class["shardingConfig"] = weaviate_class["shardingConfig"]

        if "properties" in weaviate_class:
            schema_class["properties"] = _get_primitive_properties(
                weaviate_class["properties"])

        # Add the item
        try:
            response = self._connection.post(path="/schema",
                                             weaviate_object=schema_class)
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Class may not have been created properly.')\
                from conn_err
        if response.status_code != 200:
            raise UnexpectedStatusCodeException("Create class", response)
    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)
Example #15
0
    def test_get_clusters(self, mock_get):
        """
        Test the `get_clusters` method.
        """


        wcs = WCS(AuthClientPassword('*****@*****.**', 'testPassoword'))
        wcs._auth_bearer = 'test_bearer'

        # invalid calls

        ## error messages
        connection_error_message = 'WCS clusters were not fetched.'
        unexpected_error_message = 'Checking WCS instance'

        # connection error
        mock_get.side_effect = RequestsConnectionError('Test!')
        with self.assertRaises(RequestsConnectionError) as error:
            wcs.get_clusters()
        check_error_message(self, error, connection_error_message)
        mock_get.assert_called_with(
            path='/clusters/list',
            params={
                'email': '*****@*****.**'
            }
        )

        # unexpected error
        mock_get.side_effect = None
        mock_get.return_value = Mock(status_code=400)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            wcs.get_clusters()
        check_startswith_error_message(self, error, unexpected_error_message)
        mock_get.assert_called_with(
            path='/clusters/list',
            params={
                'email': '*****@*****.**'
            }
        )

        # valid calls
        return_mock = Mock(status_code=200)
        return_mock.json.return_value = {'clusterIDs': 'test!'}
        mock_get.return_value = return_mock
        result = wcs.get_clusters()
        self.assertEqual(result, 'test!')
        mock_get.assert_called_with(
            path='/clusters/list',
            params={
                'email': '*****@*****.**'
            }
        )
Example #16
0
    def test_delete(self, mock_delete):
        """
        Test the `delete` method.
        """

        wcs = WCS(AuthClientPassword('test_secret_username', 'test_password'))
        wcs._auth_bearer = 'test_bearer'

        # invalid calls

        ## error messages
        connection_error_message = 'WCS cluster was not deleted.'
        unexpected_error_message = 'Deleting WCS instance'

        ## connection error
        mock_delete.side_effect = RequestsConnectionError('Test!')
        with self.assertRaises(RequestsConnectionError) as error:
            wcs.delete_cluster('test_name')
        check_error_message(self, error, connection_error_message)
        mock_delete.assert_called_with(
            path='/clusters/test_name',
        )

        ## unexpected error
        mock_delete.side_effect = None
        mock_delete.return_value = Mock(status_code=400)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            wcs.delete_cluster('test_name')
        check_startswith_error_message(self, error, unexpected_error_message)
        mock_delete.assert_called_with(
            path='/clusters/test_name',
        )

        # valid calls
        mock_delete.return_value = Mock(status_code=200)
        self.assertIsNone(wcs.delete_cluster('test_name'))
        mock_delete.assert_called_with(
            path='/clusters/test_name',
        )

        mock_delete.return_value = Mock(status_code=404)
        self.assertIsNone(wcs.delete_cluster('test_name'))
        mock_delete.assert_called_with(
            path='/clusters/test_name',
        )

        mock_delete.return_value = Mock(status_code=404)
        self.assertIsNone(wcs.delete_cluster('TesT_naMe'))
        mock_delete.assert_called_with(
            path='/clusters/test_name',
        )
    def test__check_status(self, mock_get):
        """
        Test the `_check_status` method.
        """

        mock_get.return_value = {'status': 'failed'}

        result = Classification(None)._check_status('uuid', 'running')
        self.assertFalse(result)

        result = Classification(None)._check_status('uuid', 'failed')
        self.assertTrue(result)

        mock_get.side_effect = RequestsConnectionError('Test!')
        result = Classification(None)._check_status('uuid', 'running')
        self.assertFalse(result)
    def get(self,
            uuid: Union[str, uuid_lib.UUID, None]=None,
            additional_properties: List[str]=None,
            with_vector: bool=False
        ) -> List[dict]:
        """
        Gets objects from weaviate, the maximum number of objects returned is 100.
        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, uuid.UUID or None, optional
            The identifier of the object that should be retrieved.
        additional_properties : list of str, optional
            list of additional properties that should be included in the request,
            by default None
        with_vector: bool
            If True the `vector` property will be returned too,
            by default False.

        Returns
        -------
        list of dicts
            A list of all objects. If no objects where found the list is empty.

        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.
        """

        try:
            response = self._get_response(uuid, additional_properties, with_vector)
        except RequestsConnectionError as conn_err:
            raise RequestsConnectionError('Could not get object/s.') from conn_err
        if response.status_code == 200:
            return response.json()
        if uuid is not None and response.status_code == 404:
            return None
        raise UnexpectedStatusCodeException("Get object/s", response)
    def test_delete(self):
        """
        Test the `delete` method.
        """

        data_object = DataObject(Mock())

        # error messages
        uuid_type_error_message = lambda dt: f"'uuid' must be of type str or uuid.UUID, but was: {dt}"
        uuid_value_error_message = "Not valid 'uuid' or 'uuid' can not be extracted from value"
        requests_error_message = 'Object could not be deleted.'
        unexpected_error_message = "Delete object"

        with self.assertRaises(TypeError) as error:
            data_object.delete(4)
        check_error_message(self, error, uuid_type_error_message(int))

        with self.assertRaises(ValueError) as error:
            data_object.delete("Hallo World")
        check_error_message(self, error, uuid_value_error_message)

        connection_mock = mock_connection_method('delete', side_effect=RequestsConnectionError('Test!'))
        data_object = DataObject(connection_mock)
        with self.assertRaises(RequestsConnectionError) as error:
            data_object.delete("b36268d4-a6b5-5274-985f-45f13ce0c642")
        check_error_message(self, error, requests_error_message)

        connection_mock = mock_connection_method('delete', status_code=404)
        data_object = DataObject(connection_mock)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            data_object.delete("b36268d4-a6b5-5274-985f-45f13ce0c642")
        check_startswith_error_message(self, error, unexpected_error_message)

        # 1. Successfully delete something
        connection_mock = mock_connection_method('delete', status_code=204)
        data_object = DataObject(connection_mock)

        object_id = "b36268d4-a6b5-5274-985f-45f13ce0c642"
        data_object.delete(object_id)
        connection_mock.delete.assert_called_with(
            path="/objects/" + object_id
        )
Example #20
0
    def test_get(self):
        """
        Test the `get` method.
        """

        # invalid calls
        requests_error_message = 'Schema could not be retrieved.'
        unexpected_error_msg = "Get schema"
        type_error_msg = lambda dt: f"'class_name' argument must be of type `str`! Given type: {dt}"

        mock_conn = mock_connection_method(
            'get', side_effect=RequestsConnectionError("Test!"))
        schema = Schema(mock_conn)
        with self.assertRaises(RequestsConnectionError) as error:
            schema.get()
        check_error_message(self, error, requests_error_message)

        mock_conn = mock_connection_method('get', status_code=404)
        schema = Schema(mock_conn)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            schema.get()
        check_startswith_error_message(self, error, unexpected_error_msg)

        connection_mock_file = mock_connection_method(
            'get', status_code=200, return_json={'Test': 'OK!'})
        schema = Schema(connection_mock_file)
        with self.assertRaises(TypeError) as error:
            schema.get(1234)
        check_error_message(self, error, type_error_msg(int))

        # valid calls

        self.assertEqual(schema.get(), {'Test': 'OK!'})
        connection_mock_file.get.assert_called_with(path="/schema", )

        self.assertEqual(schema.get("Artist"), {'Test': 'OK!'})
        connection_mock_file.get.assert_called_with(path="/schema/Artist")

        # with uncapitalized class_name
        self.assertEqual(schema.get("artist"), {'Test': 'OK!'})
        connection_mock_file.get.assert_called_with(path="/schema/Artist")
    def test_get(self):
        """
        Test the `get` method.
        """

        # error messages
        uuid_type_error = lambda dt: f"'uuid' must be of type str or uuid.UUID, but was: {dt}"
        value_error = "Not valid 'uuid' or 'uuid' can not be extracted from value"
        requests_error_message = 'Classification status could not be retrieved.'
        unexpected_error_message = "Get classification status"

        # invalid calls
        with self.assertRaises(TypeError) as error:
            Classification(None).get(123)
        check_error_message(self, error, uuid_type_error(int))

        with self.assertRaises(ValueError) as error:
            Classification(None).get('123')
        check_error_message(self, error, value_error)

        mock_conn = mock_connection_method(
            'get', side_effect=RequestsConnectionError('Test!'))
        with self.assertRaises(RequestsConnectionError) as error:
            Classification(mock_conn).get(
                "d087b7c6-a115-5c89-8cb2-f25bdeb9bf92")
        check_error_message(self, error, requests_error_message)

        mock_conn = mock_connection_method('get', status_code=404)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            Classification(mock_conn).get(
                "d087b7c6-a115-5c89-8cb2-f25bdeb9bf92")
        check_startswith_error_message(self, error, unexpected_error_message)

        # valid calls
        mock_conn = mock_connection_method('get',
                                           return_json='OK!',
                                           status_code=200)
        result = Classification(mock_conn).get(
            "d087b7c6-a115-5c89-8cb2-f25bdeb9bf92")
        self.assertEqual(result, 'OK!')
    def test__start(self):
        """
        Test the `_start` method.
        """

        # error messages
        requests_error_message = 'Classification may not started.'
        unexpected_error_message = "Start classification"

        # invalid calls
        mock_conn = mock_connection_method(
            'post', side_effect=RequestsConnectionError('Test!'))
        config = ConfigBuilder(mock_conn, None)
        with self.assertRaises(RequestsConnectionError) as error:
            config._start()
        check_error_message(self, error, requests_error_message)
        mock_conn.post.assert_called_with(path="/classifications",
                                          weaviate_object={})

        mock_conn = mock_connection_method('post', status_code=200)
        config = ConfigBuilder(mock_conn, None).with_class_name('Test!')
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            config._start()
        check_startswith_error_message(self, error, unexpected_error_message)
        mock_conn.post.assert_called_with(path="/classifications",
                                          weaviate_object={'class': 'Test!'})

        # valid calls
        mock_conn = mock_connection_method('post',
                                           status_code=201,
                                           return_json='OK!')
        config = ConfigBuilder(
            mock_conn, None).with_class_name('TestClass').with_type('TestType')
        self.assertEqual(config._start(), 'OK!')
        mock_conn.post.assert_called_with(path="/classifications",
                                          weaviate_object={
                                              'class': 'TestClass',
                                              'type': 'TestType'
                                          })
Example #23
0
    def test_do(self):
        """
        Test the `do` method.
        """

        # test exceptions
        requests_error_message = 'Query was not successful.'

        # requests.exceptions.ConnectionError
        mock_obj = mock_connection_method(
            'post', side_effect=RequestsConnectionError("Test"))
        self.aggregate._connection = mock_obj
        with self.assertRaises(RequestsConnectionError) as error:
            self.aggregate.do()
        check_error_message(self, error, requests_error_message)

        # weaviate.UnexpectedStatusCodeException
        mock_obj = mock_connection_method('post', status_code=204)
        self.aggregate._connection = mock_obj
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            self.aggregate.do()
        check_startswith_error_message(self, error, "Query was not successful")

        filter = {"path": ["name"], "operator": "Equal", "valueString": "B"}

        self.aggregate \
            .with_group_by_filter(["name"]) \
            .with_fields("groupedBy { value }") \
            .with_fields("name { count }") \
            .with_where(filter)
        expected_gql_clause = '{Aggregate{Object(where: {path: ["name"] operator: Equal valueString: "B"} groupBy: ["name"]){groupedBy { value }name { count }}}}'

        mock_obj = mock_connection_method('post',
                                          status_code=200,
                                          return_json={"status": "OK!"})
        self.aggregate._connection = mock_obj
        self.assertEqual(self.aggregate.do(), {"status": "OK!"})
        mock_obj.post.assert_called_with(
            path="/graphql", weaviate_object={'query': expected_gql_clause})
Example #24
0
    def test_delete_class_input(self):
        """
        Test the 'delete_class` method.
        """

        schema = Schema(Mock())

        # invalid calls
        type_error_message = lambda t: f"Class name was {t} instead of str"
        requests_error_message = 'Deletion of class.'

        with self.assertRaises(TypeError) as error:
            schema.delete_class(1)
        check_error_message(self, error, type_error_message(int))

        schema = Schema(
            mock_connection_method(
                'delete', side_effect=RequestsConnectionError('Test!')))
        with self.assertRaises(RequestsConnectionError) as error:
            schema.delete_class("uuid")
        check_error_message(self, error, requests_error_message)

        schema = Schema(mock_connection_method('delete', status_code=404))
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            schema.delete_class("uuid")
        check_startswith_error_message(self, error, "Delete class from schema")

        # valid calls
        mock_conn = mock_connection_method('delete', status_code=200)
        schema = Schema(mock_conn)
        schema.delete_class("Test")
        mock_conn.delete.assert_called_with(path="/schema/Test")

        # with uncapitalized class_name
        mock_conn = mock_connection_method('delete', status_code=200)
        schema = Schema(mock_conn)
        schema.delete_class("test")
        mock_conn.delete.assert_called_with(path="/schema/Test")
    def test_is_ready(self):
        """
        Test the `is_ready` method.
        """

        client = Client("http://localhost:8080")
        # Request to weaviate returns 200
        connection_mock = mock_connection_method('get')
        client._connection = connection_mock
        self.assertTrue(client.is_ready())  # Should be true
        connection_mock.get.assert_called_with(path="/.well-known/ready")

        # Request to weaviate returns 404
        connection_mock = mock_connection_method('get', status_code=404)
        client._connection = connection_mock
        self.assertFalse(client.is_ready())  # Should be false
        connection_mock.get.assert_called_with(path="/.well-known/ready")

        # Test exception in connect
        connection_mock = mock_connection_method(
            'get', side_effect=RequestsConnectionError("Test"))
        client._connection = connection_mock
        self.assertFalse(client.is_ready())
        connection_mock.get.assert_called_with(path="/.well-known/ready")
Example #26
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 test_raw(self):
        """
        Test the `raw` method.
        """

        # valid calls
        connection_mock = mock_connection_method('post')
        query = Query(connection_mock)

        gql_query = "{Get {Group {name Members {... on Person {name}}}}}"
        query.raw(gql_query)

        connection_mock.post.assert_called_with(
            path="/graphql", weaviate_object={"query": gql_query})

        # invalid calls

        type_error_message = "Query is expected to be a string"
        requests_error_message = 'Query not executed.'
        query_error_message = "GQL query failed"

        with self.assertRaises(TypeError) as error:
            query.raw(["TestQuery"])
        check_error_message(self, error, type_error_message)

        query = Query(
            mock_connection_method(
                'post', side_effect=RequestsConnectionError("Test!")))
        with self.assertRaises(RequestsConnectionError) as error:
            query.raw("TestQuery")
        check_error_message(self, error, requests_error_message)

        query = Query(mock_connection_method('post', status_code=404))
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            query.raw("TestQuery")
        check_startswith_error_message(self, error, query_error_message)
    def test_update(self):
        """
        Test the `update` method.
        """

        reference = Reference(Mock())

        # error messages
        unexpected_error_msg = 'Update property reference to object'
        connection_error_msg = 'Reference was not updated.'

        # test exceptions
        with self.assertRaises(TypeError) as error:
            reference.update(1, "prop", [self.uuid_1])
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(TypeError) as error:
            reference.update(self.uuid_1, 1, [self.uuid_2])
        check_error_message(self, error, self.name_error_message(int))

        with self.assertRaises(TypeError) as error:
            reference.update(self.uuid_1, "prop", 1)
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(TypeError) as error:
            reference.update(self.uuid_1, "prop", [1])
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.update("my UUID", "prop", self.uuid_2)
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.update(self.uuid_1, "prop", "my uuid")
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.update(self.uuid_1, "prop", ["my uuid"])
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.update(f"http://localhost:8080/v1/objects/{self.uuid_1}", "prop",
                "http://localhost:8080/v1/objects/MY_UUID")
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.update("http://localhost:8080/v1/objects/My-UUID", "prop",
                f"http://localhost:8080/v1/objects/{self.uuid_2}")
        check_error_message(self, error, self.valid_uuid_error_message)
        
        mock_obj = mock_connection_method('put', status_code=204)
        reference = Reference(mock_obj)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            reference.update(self.uuid_1, "myProperty", self.uuid_2)
        check_startswith_error_message(self, error, unexpected_error_msg)

  
        mock_obj = mock_connection_method('put', side_effect=RequestsConnectionError("Test!"))
        reference = Reference(mock_obj)
        with self.assertRaises(RequestsConnectionError) as error:
            reference.update(self.uuid_1, "myProperty", self.uuid_2)
        check_error_message(self, error, connection_error_msg)

        # test valid calls
        connection_mock = mock_connection_method('put')
        reference = Reference(connection_mock)

        reference.update(
            "de998e81-fa66-440e-a1de-2a2013667e77",
            "hasAwards",
            "fc041624-4ddf-4b76-8e09-a5b0b9f9f832"
        )
        connection_mock.put.assert_called_with(
            path="/objects/de998e81-fa66-440e-a1de-2a2013667e77/references/hasAwards",
            weaviate_object=[{'beacon': 'weaviate://localhost/fc041624-4ddf-4b76-8e09-a5b0b9f9f832'}],
        )

        reference.update(
            "4e44db9b-7f9c-4cf4-a3a0-b57024eefed0",
            "hasAwards",
            [
                "17ee17bd-a09a-49ff-adeb-d242f25f390d",
                "f8c25386-707c-40c0-b7b9-26cc0e9b2bd1",
                "d671dc52-dce4-46e7-8731-b722f19420c8"
            ]
        )
        connection_mock.put.assert_called_with(
            path="/objects/4e44db9b-7f9c-4cf4-a3a0-b57024eefed0/references/hasAwards",
            weaviate_object=[
                {'beacon': 'weaviate://localhost/17ee17bd-a09a-49ff-adeb-d242f25f390d'},
                {'beacon': 'weaviate://localhost/f8c25386-707c-40c0-b7b9-26cc0e9b2bd1'},
                {'beacon': 'weaviate://localhost/d671dc52-dce4-46e7-8731-b722f19420c8'}
            ],
        )     
    def test_add(self):
        """
        Test the `add` method.
        """
        reference = Reference(Mock())

        # error messages
        unexpected_error_msg = 'Add property reference to object'
        connection_error_msg = 'Reference was not added.'
        
        # test exceptions
        with self.assertRaises(TypeError) as error:
            reference.add(1, "prop", self.uuid_1)
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(TypeError) as error:
            reference.add(self.uuid_1, 1, self.uuid_2)
        check_error_message(self, error, self.name_error_message(int))

        with self.assertRaises(TypeError) as error:
            reference.add(self.uuid_1, "prop", 1)
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.add("my UUID", "prop", self.uuid_2)
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.add(self.uuid_1, "prop", "my uuid")
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.add(f"http://localhost:8080/v1/objects/{self.uuid_1}", "prop",
                                        "http://localhost:8080/v1/objects/MY_UUID")
        check_error_message(self, error, self.valid_uuid_error_message)
    
        with self.assertRaises(ValueError) as error:
            reference.add("http://localhost:8080/v1/objects/My-UUID", "prop",
                                        f"http://localhost:8080/v1/objects/{self.uuid_2}")
        check_error_message(self, error, self.valid_uuid_error_message)

        mock_obj = mock_connection_method('post', status_code=204)
        reference = Reference(mock_obj)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            reference.add(self.uuid_1, "myProperty", self.uuid_2)
        check_startswith_error_message(self, error, unexpected_error_msg)

        mock_obj = mock_connection_method('post', side_effect=RequestsConnectionError("Test!"))
        reference = Reference(mock_obj)
        with self.assertRaises(RequestsConnectionError) as error:
            reference.add(self.uuid_1, "myProperty", self.uuid_2)
        check_error_message(self, error, connection_error_msg)

        # test valid calls
        connection_mock = mock_connection_method('post')
        reference = Reference(connection_mock)

        # 1. Plain
        reference.add(
            "3250b0b8-eaf7-499b-ac68-9084c9c82d0f",
            "hasItem",
            "99725f35-f12a-4f36-a2e2-0d41501f4e0e"
        )
        connection_mock.post.assert_called_with(
            path="/objects/3250b0b8-eaf7-499b-ac68-9084c9c82d0f/references/hasItem",
            weaviate_object={'beacon': 'weaviate://localhost/99725f35-f12a-4f36-a2e2-0d41501f4e0e'},
        )

        # 2. using url
        reference.add(
            "http://localhost:8080/v1/objects/7591be77-5959-4386-9828-423fc5096e87",
            "hasItem",
            "http://localhost:8080/v1/objects/1cd80c11-29f0-453f-823c-21547b1511f0"
        )
        connection_mock.post.assert_called_with(
            path="/objects/7591be77-5959-4386-9828-423fc5096e87/references/hasItem",
            weaviate_object={'beacon': 'weaviate://localhost/1cd80c11-29f0-453f-823c-21547b1511f0'},
        )

        # 3. using weaviate url
        reference.add(
            "weaviate://localhost/f8def983-87e7-4e21-bf10-e32e2de3efcf",
            "hasItem",
            "weaviate://localhost/e40aaef5-d3e5-44f1-8ec4-3eafc8475078"
        )
        connection_mock.post.assert_called_with(
            path="/objects/f8def983-87e7-4e21-bf10-e32e2de3efcf/references/hasItem",
            weaviate_object={'beacon': 'weaviate://localhost/e40aaef5-d3e5-44f1-8ec4-3eafc8475078'},
        )
    def test_delete(self):
        """
        Test `delete` method`.
        """

        reference = Reference(Mock())

        # error messages
        unexpected_error_msg = 'Delete property reference to object'
        connection_error_msg = 'Reference was not deleted.'
    
        # invalid calls

        with self.assertRaises(TypeError) as error:
            reference.delete(1, "myProperty", self.uuid_2)
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(TypeError) as error:
            reference.delete(self.uuid_1, "myProperty", 2)
        check_error_message(self, error, self.uuid_error_message)

        with self.assertRaises(TypeError) as error:
            reference.delete(self.uuid_1, 3, self.uuid_2)
        check_error_message(self, error, self.name_error_message(int))

        with self.assertRaises(ValueError) as error:
            reference.delete("str", "myProperty", self.uuid_2)
        check_error_message(self, error, self.valid_uuid_error_message)

        with self.assertRaises(ValueError) as error:
            reference.delete(self.uuid_1, "myProperty", "str")
        check_error_message(self, error, self.valid_uuid_error_message)

        mock_obj = mock_connection_method('delete', status_code=200)
        reference = Reference(mock_obj)
        with self.assertRaises(UnexpectedStatusCodeException) as error:
            reference.delete(self.uuid_1, "myProperty", self.uuid_2)
        check_startswith_error_message(self, error, unexpected_error_msg)

        mock_obj = mock_connection_method('delete', side_effect=RequestsConnectionError("Test!"))
        reference = Reference(mock_obj)
        with self.assertRaises(RequestsConnectionError) as error:
            reference.delete(self.uuid_1, "myProperty", self.uuid_2)
        check_error_message(self, error, connection_error_msg)

        # test valid calls
        connection_mock = mock_connection_method('delete', status_code=204)
        reference = Reference(connection_mock)

        reference.delete(
            self.uuid_1,
            "myProperty",
            self.uuid_2
        )

        connection_mock.delete.assert_called_with(
            path=f"/objects/{self.uuid_1}/references/myProperty",
            weaviate_object={"beacon": f"weaviate://localhost/{self.uuid_2}"},
        )

        reference.delete(
            self.uuid_1,
            "hasItem",
            f"http://localhost:8080/v1/objects/{self.uuid_2}"
        )

        connection_mock.delete.assert_called_with(
            path=f"/objects/{self.uuid_1}/references/hasItem",
            weaviate_object={"beacon": f"weaviate://localhost/{self.uuid_2}"},
        )