Source code for fdpclient.client

import logging
import requests
from fdpclient import operations

logger = logging.getLogger(__name__)

[docs]class Client: def __init__(self, host): """The Client object to connect to a FAIR Data Point server. FAIR Data Point server contains 4 types of metadata as described in the `specification`_: ============ ====================== type path ============ ====================== fdp <host>/fdp or <host> catalog <host>/catalog dataset <host>/dataset distribution <host>/distribution ============ ====================== A server may use the host URL to store the 'fdp' metadata, and then the 'fdp' path is the same as the host. .. _`specification`: https://github.com/FAIRDataTeam/FAIRDataPoint-Spec/blob/master/spec.md Args: host(str): the host URL Examples: >>> client = Client('http://fdp.fairdatapoint.nl`) >>> fdp_metadata = client.read_fdp() >>> catalog_metadata = client.read_catalog('catalog01') >>> print(fdp_metadata, catalog_metadata) """ self.host = host.rstrip('/') self.fdp_id = self._detect_fdp_url() # Create metadata
[docs] def create_fdp(self, data, format='turtle', **kwargs): """Create fdp metadata. Args: data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('create', self.fdp_id, data=data, format=format, **kwargs)
[docs] def create_catalog(self, data, format='turtle', **kwargs): """Create a new catalog metadata. Args: data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('create', 'catalog', data=data, format=format, **kwargs)
[docs] def create_dataset(self, data, format='turtle', **kwargs): """Create a new dataset metadata. Args: data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('create', 'dataset', data=data, format=format, **kwargs)
[docs] def create_distribution(self, data, format='turtle', **kwargs): """Create a new distribution metadata. Args: data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('create', 'distribution', data=data, format=format, **kwargs)
# Read metadata
[docs] def read_fdp(self, format='turtle', **kwargs): """Read the fdp metadata. Args: format (str, optional): the format of the metadata. This argument overwrites the request header ``accept``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. Returns: :class:`rdflib.Graph`: RDF graph of the requested metadata. """ return self._request('read', self.fdp_id, id='', format=format, **kwargs)
[docs] def read_catalog(self, id, format='turtle', **kwargs): """Read a catalog metadata. Args: id(str): the identifier of the metadata. format (str, optional): the format of the metadata. This argument overwrites the request header ``accept``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. Returns: :class:`rdflib.Graph`: RDF graph of the requested metadata. """ return self._request('read', 'catalog', id=id, format=format, **kwargs)
[docs] def read_dataset(self, id, format='turtle', **kwargs): """Read a dataset metadata. Args: id(str): the identifier of the metadata. format (str, optional): the format of the metadata. This argument overwrites the request header ``accept``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. Returns: :class:`rdflib.Graph`: RDF graph of the requested metadata. """ return self._request('read', 'dataset', id=id, format=format, **kwargs)
[docs] def read_distribution(self, id, format='turtle', **kwargs): """Read a distribution metadata. Args: id(str): the identifier of the metadata. format (str, optional): the format of the metadata. This argument overwrites the request header ``accept``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. Returns: :class:`rdflib.Graph`: RDF graph of the requested metadata. """ return self._request('read', 'distribution', id=id, format=format, **kwargs)
# Update metadata
[docs] def update_fdp(self, data, format='turtle', **kwargs): """Update the fdp metadata. Args: data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('update', self.fdp_id, id='', data=data, format=format, **kwargs)
[docs] def update_catalog(self, id, data, format='turtle', **kwargs): """Update a catalog metadata. Args: id(str): the identifier of the metadata. data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('update', 'catalog', id=id, data=data, format=format, **kwargs)
[docs] def update_dataset(self, id, data, format='turtle', **kwargs): """Update a dataset metadata. Args: id(str): the identifier of the metadata. data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('update', 'dataset', id=id, data=data, format=format, **kwargs)
[docs] def update_distribution(self, id, data, format='turtle', **kwargs): """Update a distribution metadata. Args: id(str): the identifier of the metadata. data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('update', 'distribution', id=id, data=data, format=format, **kwargs)
# Delete metadata
[docs] def delete_catalog(self, id, **kwargs): """Delete a catalog metadata. Args: id(str): the identifier of the metadata. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('delete', 'catalog', id=id, **kwargs)
[docs] def delete_dataset(self, id, **kwargs): """Delete a dataset metadata. Args: id(str): the identifier of the metadata. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('delete', 'dataset', id=id, **kwargs)
[docs] def delete_distribution(self, id, **kwargs): """Delete a distribution metadata. Args: id(str): the identifier of the metadata. **kwargs: Optional arguments that :func:`requests.request` takes. """ self._request('delete', 'distribution', id=id, **kwargs)
# Private methods
[docs] def _detect_fdp_url(self): """Detect the internal path of fdp Raises: RuntimeError: failed to find the fdp url Returns: str: the internal path of fdp, i.e. 'fdp' or ''. """ fmt = 'text/turtle' r = requests.get(self.host + '/fdp', params={'Accept':fmt}) if r.status_code == 200 and r.headers['content-type'] == fmt: return 'fdp' r = requests.get(self.host, params={'Accept':fmt}) if r.status_code == 200 and r.headers['content-type'] == fmt: return '' raise RuntimeError('Failed to detect the fdp url. Check if the server ' + 'uses "<host>" or "<host>/fdp" as the fdp url.')
[docs] def _request(self, operation, type, id=None, data=None, format='turtle', **kwargs): """Private request method. Args: operation(str): the request operation. Available options: 'read', 'write', 'update' and 'delete'. See :class:`fdpclient.operations`. type(str): the type of metadata. Available types: 'fdp', 'catalog', 'dataset' and 'distribution'. id(str): the identifier of the metadata. Defaults to `None`. data(str, bytes, file-like object or :class:`rdflib.Graph`): the content of metadata to send in the request body. Defaults to `None`. format (str, optional): the format of the metadata. This argument overwrites the request header ``content-type`` or ``accept``. Available options are 'turtle', 'n3', 'nt', 'xml' and 'json-ld'. See :const:`fdpclient.config.DATA_FORMATS`. Defaults to 'turtle'. **kwargs: Optional arguments that :func:`requests.request` takes. Returns: `None` or :class:`rdflib.Graph`: RDF graph of the requested metadata. """ request_methods = ('create', 'read', 'update', 'delete') if operation not in request_methods: raise ValueError(f'Invalid request method: {operation}') if operation in ('read', 'delete', 'update') and id is None: raise ValueError(f'Metadata "id" must be given for request method {operation}') if operation in ('create', 'update') and data is None: raise ValueError(f'Metadata "data" must be given for request method {operation}') if id is not None: url = '/'.join([self.host, type, id]) else: url = '/'.join([self.host, type]) url = url.rstrip('/') logger.debug(f'Request: {operation} metadata on {url}') request = getattr(operations, operation) if operation == 'delete': r = request(url=url, data=data, **kwargs) else: r = request(url=url, data=data, format=format, **kwargs) return r