Source code for blackfynn.client

# -*- coding: utf-8 -*-

# blackfynn-specific
from blackfynn import Settings
from blackfynn.models import (Dataset, ModelTemplate)
from blackfynn.api.transfers import IOAPI
from blackfynn.api.compute import ComputeAPI
from blackfynn.api.user import UserAPI
from blackfynn.api.concepts import (
    ModelsAPI, RecordsAPI, ModelRelationshipsAPI, ModelRelationshipInstancesAPI, ModelTemplatesAPI
)
from blackfynn.api.timeseries import TimeSeriesAPI
from blackfynn.base import ClientSession
import blackfynn.log as log
from blackfynn.api.core import (
    CoreAPI, SecurityAPI, OrganizationsAPI, SearchAPI
)
from blackfynn.api.data import (
    DatasetsAPI, PackagesAPI, FilesAPI, DataAPI, TabularAPI
)

[docs]class Blackfynn(object): """ The client provides an interface to the Blackfynn platform, giving you the ability to retrieve, add, and manipulate data. Args: profile (str, optional): Preferred profile to use api_token (str, optional): Preferred api token to use api_secret (str, optional): Preferred api secret to use host (str, optional): Preferred host to use streaming_host (str, optional): Preferred streaming host to use concepts_host (str, optional): Preferred concepts service host to use env_override (bool, optional): Should environment variables override settings **overrides (dict, optional): Settings to override Examples: Load the client library and initialize:: from blackfynn import Blackfynn # note: no API token needed if environment variables are set bf = Blackfynn() Retrieve/modify items on the platform:: # get some dataset ds = bf.get_dataset('my dataset') print "Dataset {} has ID={}".format(ds.name, ds.id) # list all first-level items in dataset for item in ds: print "Item: {}".format(item) # grab some data package pkg = bf.get("N:package:1234-1234-1234-1234") # modify a package's name pkg.name = "New Package Name" # add some property pkg.set_property('Room', 'ICU-123') # sync changes pkg.update() Note: To initialize your ``Blackfynn`` client without passing any arguments, ensure that your ``BLACKFYNN_API_TOKEN`` and ``BLACKFYNN_API_SECRET`` environment variables are properly set. """ def __init__(self, profile=None, api_token=None, api_secret=None, host=None, streaming_host=None, concepts_host=None, env_override=True, **overrides): self._logger = log.get_logger("blackfynn.client.Blackfynn") overrides.update({ k: v for k, v in { 'api_token': api_token, 'api_secret': api_secret, 'api_host': host, 'api_streaming_host': streaming_host, 'api_concepts_host': concepts_host, }.items() if v != None }) self.settings = Settings(profile, overrides, env_override) if self.settings.api_token is None: raise Exception('Error: No API token found. Cannot connect to Blackfynn.') if self.settings.api_secret is None: raise Exception('Error: No API secret found. Cannot connect to Blackfynn.') # direct interface to REST API. self._api = ClientSession(self.settings) # account try: self._api.authenticate() except Exception as e: raise e self._api.register( CoreAPI, OrganizationsAPI, DatasetsAPI, FilesAPI, DataAPI, PackagesAPI, TimeSeriesAPI, TabularAPI, SecurityAPI, ComputeAPI, SearchAPI, IOAPI, UserAPI, ModelsAPI, RecordsAPI, ModelRelationshipsAPI, ModelRelationshipInstancesAPI, ModelTemplatesAPI ) self._api._context = self._api.organizations.get(self._api._organization) @property def context(self): """ The current organizational context of the active client. """ return self._api._context @property def profile(self): """ The profile of the current active user. """ return self._api.profile
[docs] def organizations(self): """ Return all organizations for user. """ return self._api.organizations.get_all()
[docs] def datasets(self): """ Return all datasets for user for an organization (current context). """ self._check_context() return self.context.datasets
[docs] def get(self, id, update=True): """ Get any DataPackage or Collection object by ID. Args: id (str): The ID of the Blackfynn object. Returns: Object of type/subtype ``DataPackage`` or ``Collection``. """ try: return self._api.core.get(id, update=update) except: self._logger.info("Unable to retrieve object"\ "\n\nAcceptable objects for get() are:"\ "\n - DataPackages"\ "\n - Collections"\ "\n\nUse get_dataset() if trying to retrieve a dataset")
[docs] def create(self, thing): """ Create a object on the platform. """ return self._api.core.create(thing)
[docs] def create_dataset(self, name): """ Create a dataset under the active organization. Args: name (str): The name of the to-be-created dataset Returns: The created ``Dataset`` object """ self._check_context() return self._api.datasets.create(Dataset(name))
[docs] def get_dataset(self, name_or_id): """ Get Dataset by name or ID. Args: name_or_id (str): the name or the ID of the dataset Note: When using name, this method gnores case, spaces, hyphens, and underscores such that these are equivelent: - "My Dataset" - "My-dataset" - "mydataset" - "my_DataSet" - "mYdata SET" """ try: return self._api.datasets.get(name_or_id) except: pass result = self._api.datasets.get_by_name_or_id(name_or_id) if result is None: raise Exception("No dataset matching name or ID '{}'.".format(name_or_id)) return result
[docs] def update(self, thing): """ Update an item on the platform. Args: thing (object or str): the ID or object to update Example:: my_eeg = bf.get('N:package:1234-1234-1234-1234') my_eeg.name = "New EEG Name" bf.update(my_eeg) Note: You can also call update directly on objects, for example:: my_eeg.name = "New EEG Name" my_eeg.update() """ return self._api.core.update(thing)
[docs] def delete(self, *things): """ Deletes items from the platform. Args: things (list): ID or object of items to delete Example:: # delete a package by passing in object bf.delete(my_package) # delete a package by ID bf.delete('N:package:1234-1234-1234-1235') # delete many things (mix of IDs and objects) bf.delete(my_package, 'N:collection:1234-1234-1234-1235', another_collection) Note: When deleting ``Collection``, all child items will also be deleted. """ return self._api.core.delete(*things)
[docs] def move(self, destination, *things): """ Moves item(s) from their current location to the destination. Args: destination (object or str): The ID of the destination. This must be of type type ``Collection`` or ``None``. If destination is ``None``, ``things`` will be moved to the top of their containing ``Dataset`` things (list): the IDs or objects to move. """ r = self._api.data.move(destination, *things)
[docs] def search(self, query, max_results=10): """ Find an object on the platform. Args: query (str): query string to perform search. max_results (int, optional): the number of results to return Example:: # find some items belonging to patient123 for result in bf.search('patient123'): print "found:", result """ return self._api.search.query(query, max_results=max_results)
def _check_context(self): if self.context is None: raise Exception('Must set context before executing method.')
[docs] def get_model_template(self, template_id): """ Get a model template belonging to the current organization. Args: template_id (str): The ID of the model template object. Returns: Object of type ModelTemplate. """ return self._api.templates.get(template_id)
[docs] def get_model_templates(self): """ Get all of the model templates belonging to the current organization. Returns: A list of objects of type ModelTemplate. """ return self._api.templates.get_all()
[docs] def create_model_template( self, name=None, description=None, category=None, required=None, properties=None, template=None ): """ Create a new model template belonging to the current organization. Args: template (ModelTemplate): A ModelTemplate object. OR name (str): The name of the template description (str, optional): A description of the template category (str): The category of the template required ([str], optional): The names of the required template properties properties (dict OR tuples): The template properties Example:: my_template = ModelTemplate( schema="http://schema.blackfynn.io/model/draft-01/schema", name="Patient", description="This is a patient.", category="Person", properties=dict( name=dict( type="string", description="Name" ), DOB=dict( type="string", format="date", description="Date of Birth" ) ), required=["name"] bf.create_model_template(my_template) Example:: bf.create_model_template( name="Patient", description="This is a patient.", category="Person", required=["name"], properties=[("name", "string"), ("DOB", "date")] ) Returns: The created ModelTemplate object. """ if (template is None): template_to_create = ModelTemplate(name=name, description=description, category=category, required=required, properties=properties) else: template_to_create = template assert isinstance(template_to_create, ModelTemplate), "template must be type ModelTemplate" return self._api.templates.create(template=template_to_create)
[docs] def validate_model_template( self, name=None, description=None, category=None, required=None, properties=None, template=None ): """ Validate a model template schema. Args: template (ModelTemplate): A ModelTemplate object. OR name (str): The name of the template description (str, optional): A description of the template category (str): The category of the template required ([str], optional): The names of the required template properties properties (dict OR tuples): The template properties Example:: my_template = ModelTemplate( schema="http://schema.blackfynn.io/model/draft-01/schema", name="Patient", description="This is a patient.", category="Person", properties=dict( name=dict( type="string", description="Name" ), DOB=dict( type="string", format="date", description="Date of Birth" ) ), required=["name"] bf.validate_model_template(my_template) Example:: bf.validate_model_template( name="Patient", category="Person", properties=[("name", "string"), ("Weight", "number")] ) Returns: "True" or a list of validation errors """ if (template is None): template_to_validate = ModelTemplate(name=name, description=description, category=category, required=required, properties=properties) else: template_to_validate = template assert isinstance(template_to_validate, ModelTemplate), "template must be type ModelTemplate" return self._api.templates.validate(template=template_to_validate)
[docs] def delete_model_template(self, template_id): """ Deletes a model template from the platform. Args: template_id (str): The ID of the model template object. """ return self._api.templates.delete(template_id)
def __repr__(self): return "<Blackfynn user='{}' organization='{}'>".format(self.profile.email, self.context.name)