def describe(self, company: SomeResourceIds, **kwargs) -> SomeResources: """Describe a company or multiple companies. Args: company: Identifier of the company to describe, or list of such identifiers. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: The company description or a list of company description. """ data = kwargs if isinstance(company, list): results = [] ids_chunks = get_chunks(company, self._provider.max_per_describe) for ids_chunk in ids_chunks: data['companies'] = ids_chunk descs = self._provider.post('describe-companies', data=data) results += [Resource(**desc) for desc in descs] return results else: data['company'] = company desc = self._provider.post('describe-company', data=data) return Resource(**desc)
def describe(self, flight: SomeResourceIds, **kwargs) -> SomeResources: """Describe a flight or a list of flights. Args: flight: Identifier of the flight to describe, or list of such identifiers. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: The flight description or a list of flight descriptions. """ data = kwargs if isinstance(flight, list): results = [] ids_chunks = get_chunks(flight, self._provider.max_per_describe) for ids_chunk in ids_chunks: data['flights'] = ids_chunk descs = self._provider.post('describe-flights', data=data) results += [Resource(**desc) for desc in descs] return results else: data['flight'] = flight desc = self._provider.post('describe-flight', data=data) return Resource(**desc)
def describe(self, annotation: SomeResourceIds, **kwargs) -> SomeResources: """Describe a dataset or a list of datasets. Args: annotation: Identifier of the annotation to describe, or list of such identifiers. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: The annotation description or a list of annotation description. """ data = kwargs if isinstance(annotation, list): results = [] ids_chunks = get_chunks(annotation, self._provider.max_per_describe) for ids_chunk in ids_chunks: data['annotations'] = ids_chunk descs = self._provider.post('describe-annotations', data=data) results += [Resource(**desc) for desc in descs] return results else: data['annotation'] = annotation desc = self._provider.post('describe-annotation', data=data) return Resource(**desc)
def describe(self, carrier: SomeResourceIds, **kwargs) -> SomeResources: """Describe a carrier or a list of carriers. Args: carrier: Identifier of the carrier to describe, or list of such identifiers. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: The carrier description or a list of carriers descriptions. """ data = kwargs if isinstance(carrier, list): results = [] ids_chunks = get_chunks(carrier, self._provider.max_per_describe) for ids_chunk in ids_chunks: data['carriers'] = ids_chunk descs = self._provider.post('describe-carriers', data=data) results += [Resource(**desc) for desc in descs] return results else: data['carrier'] = carrier desc = self._provider.post('describe-carrier', data=data) return Resource(**desc)
def describe(self, team: SomeResourceIds, **kwargs) -> SomeResources: """Describe a team or list of teams. Args: team: Identifier of the team to describe, or list of such identifiers. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: A team resource or a list of team resources. """ data = kwargs if isinstance(team, list): results = [] ids_chunks = get_chunks(team, self._provider.max_per_describe) for ids_chunk in ids_chunks: data['teams'] = ids_chunk descs = self._provider.post('describe-teams', data=data) results += [Resource(**desc) for desc in descs] return results else: data['team'] = team desc = self._provider.post('describe-team', data=data) return Resource(**desc)
def describe(self, task: SomeResourceIds, **kwargs) -> SomeResources: """Describe a collection task. Args: task: Identifier of the collection task to describe, or list of such identifiers. Returns: Resource: The collection task description or a list of collection task descriptions. """ data = kwargs if isinstance(task, list): results = [] ids_chunks = get_chunks(task, self._provider.max_per_describe) for ids_chunk in ids_chunks: data['tasks'] = ids_chunk descs = self._provider.post('describe-tasks', data=data) results += [Resource(**desc) for desc in descs] return results else: data['task'] = task desc = self._provider.post('describe-task', data=data) return Resource(**desc)
def create_datasets(self, datasets: List[dict]) -> Union[List[Resource]]: """Create several datasets *(bulk dataset creation)*. Args: datasets: List of dataset dictionnaries (refer to ``/create-datasets`` definition in the Data Manager API for a detailed description of ``datasets``) Returns: A list of the created dataset descriptions. Example: >>> sdk.datasets.create_datasets( ... datasets=[{'name': 'My file dataset', ... 'project': '4037636c9a406900074dc253', ... 'type': 'file', ... 'components': [{'name': 'kind_of_file'}]}, ... {'name': 'My image', ... 'type': 'image', ... 'project': '4037636c9a406900074dc253', ... 'components': [{'name': 'image'}]}]) [Resource(_id='406ee155647ec6006df3aa21'), ...] """ for desc in datasets: if 'vertical_srs_wkt' in desc: desc['vertical_srs_wkt'] = \ expand_vertcrs_to_wkt(desc['vertical_srs_wkt']) data = {'datasets': datasets} created_datasets = self._provider.post('create-datasets', data=data) return [Resource(**dataset) for dataset in created_datasets]
def create(self, *, geometry: dict = None, properties: dict = None, collection: ResourceId = None, **kwargs) -> Resource: """Create a feature. Args: geometry: A dictionary following GeoJSON specification. properties: Dictionary of properties. collection: Identifier of a collection to add the created feature to. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource for the created feature. """ data = kwargs if geometry is not None: data['geometry'] = geometry if collection is not None: data['collection'] = collection if properties is not None: data['properties'] = properties desc = self._provider.post('create-feature', data=data) return Resource(**desc)
def create(self, *, name: str, maker: str, type: str, company: ResourceId = None, unloaded_weight: dict = None, flight_time: dict = None, speed: dict = None, altitude: dict = None, compatible_sensor_models: List[ResourceId] = None, **kwargs) -> Resource: """Create a carrier model. Args: name: Carrier model name. maker: Maker name. type: Model type, among``fixed-wind``, ``multirotor``, ``ground-robot``, ``helicopter``, ``pedestrian``. company: Optional identifier of the company. unloaded_weight: Optional unloaded weight ``{ value: weight without sensor, unit: unit (g, kg) }``. flight_time : Optional flight time ``{ value: maximum flight time, unit: unit (min) }``. speed : Optional speed ``{ min: {value, unit}, max: {value, unit(m/s, mph ,ft/s, km/h, knot)} }``. altitude : Optional altitude ``{ min: {value, unit}, max: {value, unit(m, ft)} }``. compatible_sensor_models: Optional list of compatible sensors identifiers. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: A carrier model resource. """ data = kwargs data.update({'name': name, 'maker': maker, 'type': type}) for param_name, param_value in (('company', company), ('unloaded_weight', unloaded_weight), ('flight_time', flight_time), ('speed', speed), ('altitude', altitude), ('unloaded_weight', unloaded_weight), ('compatible_sensor_models', compatible_sensor_models)): if param_value is not None: data[param_name] = param_value content = self._provider.post(path='create-carrier-model', data=data) return Resource(**content)
def create(self, *, company: ResourceId, name: str, leader: ResourceId = None, **kwargs) -> Resource: """Create a team. Args: company: Identifier of the company. name: Team name. leader: Optional team leader (pilot id). **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: A team resource. """ data = kwargs data.update({ 'name': name, 'company': company, }) if leader is not None: data['leader'] = leader content = self._provider.post(path='create-team', data=data) return Resource(**content)
def search(self, *, project: ResourceId = None, filter: dict = None, limit: int = None, page: int = None, sort: dict = None, return_total: bool = False, **kwargs) -> Union[ResourcesWithTotal, List[Resource]]: """Search annotations. Args: project: Optional identifier of a project to search annotations for. filter: Search filter dictionary (refer to ``/search-annotations`` in the Annotation API specification for a detailed description). limit: Optional Maximum number of results. page: Optional Page number (starting at page 1). sort: Optional. Sort the results on the specified attributes (``1`` is sorting in ascending order, ``-1`` is sorting in descending order). return_total: Optional. Change the type of return: If ``False`` (default), the method will return a limited list of resources (limited by ``limit`` value). If ``True``, the method will return a namedtuple with the total number of all results, and the limited list of resources. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: A list of annotation descriptions or a namedtuple with total number of results and list of annotation descriptions. """ data = kwargs for name, value in [('filter', filter or {}), ('limit', limit), ('page', page), ('sort', sort)]: if value is not None: data.update({name: value}) if project is not None: data['filter'].update({'project': {'$eq': project}}) r = self._provider.post('search-annotations', data=data) annotations = r.get('results') results = [Resource(**a) for a in annotations] if return_total is True: total = r.get('total') return ResourcesWithTotal(total=total, results=results) else: return results
def create(self, name: str, *, client_type='sdk', expiration_date: datetime = None, **kwargs) -> Resource: """Create an OAuth client. This client will be used to generate a temporary connection token. Args: name: OAuth client name. client_type: Client type (only `sdk` is supported). expiration_date: Optional expiration date. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource for the client created. """ data = kwargs data.update({ 'name': name, 'client_type': client_type, }) if expiration_date is not None: data['expiration_date'] = expiration_date desc = self._provider.post(path='create-client', data=data) return Resource(**desc)
def search(self, *, name: str = None, filter: Dict = None, limit: int = None, page: int = None, sort: dict = None, return_total: bool = False, **kwargs) -> Union[ResourcesWithTotal, List[Resource]]: """Search for a list of analytics. Args: name: Optional Analytic name. filter: Search filter dictionary (refer to ``/search-analytics`` definition in the Analytics-service API for a detailed description of ``filter``). limit: Optional Maximum number of results to extract. page: Optional Page number (starting at page 0). sort: Optional. Sort the results on the specified attributes (``1`` is sorting in ascending order, ``-1`` is sorting in descending order). return_total: Optional. Change the type of return: If ``False`` (default), the method will return a limited list of resources (limited by ``limit`` value). If ``True``, the method will return a namedtuple with the total number of all results, and the limited list of resources. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Analytics: A list of analytics resources OR a namedtuple with total number of results and list of analytics resources. """ data = kwargs for prop_name, value in [('filter', filter or {}), ('limit', limit), ('page', page), ('sort', sort)]: if value is not None: data.update({prop_name: value}) if name is not None: data['filter']['name'] = {'$eq': name} search_desc = self._provider.post( path='search-analytics', data=data, as_json=True) analytics = search_desc.get('results') results = [Resource(**analytic) for analytic in analytics] if return_total is True: total = search_desc.get('total') return ResourcesWithTotal(total=total, results=results) else: return results
def test_initialization(self): """Test resource initialization.""" r = Resource(**self.user_desc) self.assertEqual(r.id, '5aa7f7fd8e329e5d1858ee7e') with self.assertRaises(AttributeError): _ = r.fake_attribute del r.id # For comparison assert self.user_desc == r.__dict__
def create(self, dataset: Union[ResourceId, List[ResourceId]], *, duration: int = None, **kwargs) -> Resource: """Create a share token for a given dataset. Share token creation is restricted to users with admin profile or a manager role on their company. When sharing multiple datasets, all datasets are expected to belong to a single company. Args: dataset: Dataset identifier or list of dataset identifiers to create a share token for. duration: Optional duration in seconds of the created token. When equal to ``None`` (the default) the created token won't expire. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Dictionary with ``token``, ``expiration_date`` and ``scope`` keys. Example: >>> desc = sdk.share_tokens.create('5d08ebe86a17271b23bc0fcd') >>> desc.token[:16] 'YfkX6oB5JB02L9x5' """ data = kwargs if isinstance(dataset, list): dataset_ids = dataset else: dataset_ids = [dataset] data.update({'scope': {'datasets': dataset_ids}}) datasets = self._sdk.datasets.describe(dataset_ids, fields={'include': ['company']}) company_ids = set([d.company for d in datasets]) if len(company_ids) != 1: raise RuntimeError('Expecting datasets in a single company') data['company'] = list(company_ids)[0] if duration is not None: data['duration'] = duration desc = self._provider.post(path='/create-share-token', data=data) return Resource(**desc)
def describe_uploads_status(self, *, flights: SomeResourceIds = None, missions: SomeResourceIds = None, projects: SomeResourceIds = None, limit: int = None, page: int = None, return_total: bool = False, **kwargs) -> Union[ResourcesWithTotal, List[Resource]]: """Describe uncompleted flights status, descending sort by flight creation date. Args: flights: Optional Identifier of a flight or list of such identifiers. missions: Optional Identifier of a mission or list of such identifiers. projects: Optional Identifier of a project or list of such identifiers. limit: Optional Maximum number of results to extract. page: Optional Page number (starting at page 1). return_total: Optional Return the number of results found, default ``False``. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: A list of flights OR a namedtuple with total number of results and list of flights. """ if flights is not None and not isinstance(flights, list): flights = [flights] if missions is not None and not isinstance(missions, list): missions = [missions] if projects is not None and not isinstance(projects, list): projects = [projects] data = kwargs for name, value in [('flights', flights), ('missions', missions), ('projects', projects), ('page', page), ('limit', limit)]: if value is not None: data.update({name: value}) r = self._provider.post('describe-flight-uploads-status', data=data) descriptions = r.get('results') results = [Resource(id=desc.get('flight'), **desc) for desc in descriptions] if return_total is True: total = r.get('total') return ResourcesWithTotal(total=total, results=results) return results
def test_setattr(self): """Test setting resource attribute.""" r = Resource(**self.user_desc) self.assertEqual(r.lastName, 'Eiffel') r.lastName = 'Courbet' self.assertEqual(r.lastName, 'Courbet') r.lastName = 'Choquet' self.assertEqual(r.lastName, 'Choquet') r.email = '*****@*****.**' self.assertEqual(r.lastName, 'Choquet') r.fake_attribute = 'value' self.assertEqual(r.fake_attribute, 'value')
def create(self, *, carrier_model: str, team: ResourceId, serial_number: str, firmware: str = None, status: str = None, comment: str = None, **kwargs) -> Resource: """Create a carrier. Args: carrier_model: Identifier of the carrier model. team: Identifier of the team. serial_number: Serial number of the carrier. firmware : Optional firmware. status: Optional status, among ``ready``, ``in-maintenance``, ``out-of-service``. comment: Optional comment. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: A carrier resource. """ data = kwargs data.update({ 'carrier_model': carrier_model, 'team': team, 'serial_number': serial_number }) for param_name, param_value in (('status', status), ('comment', comment), ('firmware', firmware)): if param_value is not None: data[param_name] = param_value content = self._provider.post(path='create-carrier', data=data) return Resource(**content)
def delete(self, client: ResourceId, **kwargs) -> Resource: """Delete an OAuth client. Args: client: Identifier of OAuth client to delete. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Deleted resource. """ data = kwargs data['client'] = client desc = self._provider.post(path='delete-client', data=data) return Resource(**desc)
def cancel(self, product: ResourceId) -> Resource: """Cancel a running Analytics product. Args: product: Identifier of the product to cancel. Returns: The product description. Raises: ResponseError: When the ``product`` identifier is incorrect or has not been found. """ data = {'product': product} desc = self._provider.post('cancel-product', data=data) return Resource(**desc)
def describe(self, analytic: ResourceId, **kwargs) -> Resource: """Describe an analytic. Args: analytic: Identifier of the analytic to describe. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: The analytic description. """ data = kwargs data['analytic'] = analytic desc = self._provider.post('describe-analytic', data=data) return Resource(**desc)
def _create(self, dataset_type: str, component_names: Union[List[str], List[Dict[str, Any]]], **kwargs) -> Resource: components = _build_component_dict_list_from_names(component_names) if dataset_type not in ('file', 'mesh', 'image', 'raster', 'pcl', 'vector', 'file'): raise ValueError(f'Unsupported type "{dataset_type}"') adapted_params = _adapt_params(kwargs) if 'vertical_srs_wkt' in adapted_params: adapted_params['vertical_srs_wkt'] = \ expand_vertcrs_to_wkt(kwargs['vertical_srs_wkt']) params = {'type': dataset_type, 'components': components} params.update(adapted_params) desc = self._provider.post('create-dataset', data=params) return Resource(**desc)
def create_annotations(self, annotations: List[dict], **kwargs) -> List[Resource]: """Create several annotations. Args: annotations: List of annotation descriptions, each description is a dictionary with keys among arguments of ``create()``. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Descriptions of the created annotations. """ data = {'annotations': annotations} resp = self._provider.post('create-annotations', data=data) return [Resource(**desc) for desc in resp]
def describe(self, user: ResourceId = None, **kwargs) -> Resource: """Describe a user. Args: user: User identifier to describe. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: User : User resource. """ data = kwargs if user: data['user'] = user content = self._provider.post(path='describe-user', data=data) return Resource(**content)
def create_features(self, descriptions: Iterable[dict], **kwargs) -> List[Resource]: """Create features. Args: descriptions: List of features descriptions, each description is a dictionary with keys among arguments of ``create()``. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: List of resource for the created features. """ data = kwargs data['features'] = descriptions descs = self._provider.post('create-features', data=data) return [Resource(**desc) for desc in descs]
def rename(self, task: ResourceId, *, name: str, **kwargs): """Rename a collection task. Args: task: Collection task to rename. name: New task name. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: The renamed collection task. """ data = kwargs data.update({'task': task, 'name': name}) content = self._provider.post('set-task-name', data=data) return Resource(**content)
def set_leader(self, team: ResourceId, *, leader: ResourceId, **kwargs) -> Resource: """Set the team leader. Args: team: Identifier of the team. leader: Identifier of the pilot to promote to leader. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: The updated team resource. """ data = kwargs data['team'] = team data['leader'] = leader desc = self._provider.post('set-team-leader', data=data) return Resource(**desc)
def rename(self, team: ResourceId, name: str, **kwargs) -> Resource: """Rename a team. Args: team: Identifier of the team. name: New name. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resource: The updated team resource. """ data = kwargs data['team'] = team data['name'] = name desc = self._provider.post('set-team-name', data=data) return Resource(**desc)
def search(self, *, filter: dict = None, limit: int = None, page: int = None, sort: dict = None, **kwargs) -> List[Resource]: """Search carriers. Args: filter: Search filter dictionary. limit: Maximum number of results to extract. page: Page number (starting at page 0). sort: Sort the results on the specified attributes (``1`` is sorting in ascending order, ``-1`` is sorting in descending order). **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: Resources: A list of carrier resources. """ data = kwargs for name, value in [('filter', filter or {}), ('limit', limit), ('page', page), ('sort', sort)]: if value is not None: data.update({name: value}) r = self._provider.post('search-carriers', data=data) results = r.get('results') return [Resource(**m) for m in results]
def describe(self, product: ResourceId, **kwargs) -> Resource: """Describe an Analytics product. Args: product: Identifier of the product to describe. **kwargs: Optional keyword arguments. Those arguments are passed as is to the API provider. Returns: The product description. Raises: ResponseError: When the ``product`` identifier is incorrect or has not been found. """ data = kwargs data['product'] = product desc = self._provider.post('describe-product', data=data) return Resource(**desc)