class APIKey(Resource): """ Represents an API key in CARTO. API keys are used to grant permissions to tables and maps. See the Auth API reference for more info: https://carto.com/developers/auth-api/ """ name = CharField() token = CharField() type = CharField() created_at = DateTimeField() updated_at = DateTimeField() grants = GrantsField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "name" def regenerate_token(self): """ Regenerates the associated token :return: :raise: CartoException """ try: endpoint = (self.Meta.collection_endpoint + "{name}/token/regenerate"). \ format(name=self.name) self.send(endpoint, "POST") except Exception as e: raise CartoException(e)
class Entity(Resource): """ Represents an entity in CARTO. This is an internal data type, with no specific API endpoints """ id = CharField() type = CharField()
class ExportJob(WarnAsyncResource): """ Equivalent to a .carto export in CARTO. Allows a CARTO export to be created using a visualization in the user's CARTO account .. warning:: Non-public API. It may change with no previous notice """ id = CharField() visualization_id = CharField() user_id = CharField() state = CharField() url = CharField() created_at = DateTimeField() updated_at = DateTimeField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) def __init__(self, client, visualization_id): """ :param client: Client to make authorized requests :param visualization_id: The id of the visualization (or dataset!!!) that will be exported :type client: :class:`carto.auth.APIKeyAuthClient` :type visualization_id: str :return: """ self.visualization_id = visualization_id super(ExportJob, self).__init__(client) def run(self, **export_params): """ Make the actual request to the Import API (exporting is part of the Import API). :param export_params: Any additional parameters to be sent to the Import API :type export_params: kwargs :return: .. note:: The export is asynchronous, so you should take care of the progression, by calling the :func:`carto.resources.AsyncResource.refresh` method and check the export job :py:attr:`~state` attribute. See :func:`carto.visualizations.Visualization.export` method implementation for more details """ export_params["visualization_id"] = self.visualization_id return super(ExportJob, self).run(params=export_params)
class User(WarnResource): """ Represents an enterprise CARTO user, i.e. a user that belongs to an organization Currently, CARTO's user API only supports enterprise users. .. warning:: Non-public API. It may change with no previous notice """ username = CharField() email = CharField() avatar_url = CharField() base_url = CharField() quota_in_bytes = IntegerField() db_size_in_bytes = IntegerField() table_count = IntegerField() public_visualization_count = IntegerField() all_visualization_count = IntegerField() password = CharField() soft_geocoding_limit = IntegerField() class Meta: id_field = "username" name_field = "username" def __init__(self, auth_client): """ Sets the collection endpoint dynamically, based on provided organization (see api/auth.py) :param auth_client: Auth client """ if auth_client.organization is None: raise CartoException( _("User management requires an \ organization-enabled APIKeyAuthClient")) super(User, self).__init__(auth_client) def get_collection_endpoint(self): """ """ return API_ENDPOINT.format(api_version=API_VERSION, organization=self.client.organization) def get_resource_endpoint(self): """ """ resource_id = getattr(self, self.Meta.id_field, None) if resource_id is None: return None return urljoin(self.get_collection_endpoint(), str(resource_id))
class DOSubscription(Resource): """ Represents a Data Observatory Subscriptions in CARTO. """ dataset = CharField() id = CharField() project = CharField() table = CharField() type = CharField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "id"
class Choice(Resource): id = IntegerField() question = QuestionField() choice_text = CharField() votes = IntegerField() class Meta: name_field = "choice_text"
class Question(Resource): id = IntegerField() question_text = CharField() pub_date = DateTimeField() choices = ChoiceField(many=True) class Meta: name_field = "question_text"
class Table(WarnResource): """ Represents a table in CARTO. This is an internal data type. Both Table and TableManager are not meant to be used outside the SDK If you are looking to work with datasets / tables from outside the SDK, please look into the datasets.py file. .. warning:: Non-public API. It may change with no previous notice """ id = CharField() name = CharField() privacy = CharField() permission = PermissionField() schema = CharField() updated_at = DateTimeField() rows_counted = IntegerField() row_count = IntegerField() size = IntegerField() table_size = IntegerField() map_id = CharField() description = CharField() geometry_types = CharField(many=True) table_visualization = VisualizationField() dependent_visualizations = None non_dependent_visualizations = None synchronization = SynchronizationField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "name"
class Kuviz(WarnResource): """ Represents a custom map visualization in CARTO. .. warning:: Non-public API. It may change with no previous notice """ created_at = DateTimeField() data = Base64EncodedField() id = CharField() name = CharField() password = PasswordAndPrivacyFields() privacy = CharField() updated_at = DateTimeField() url = CharField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "id"
class Grants(Resource): apis = CharField(many=True) tables = TableGrantField(many=True) services = CharField(many=True) def get_id(self): tables = [] if self.tables: tables = [x.to_json() for x in self.tables] return [{ 'type': 'apis', 'apis': self.apis or [] }, { 'type': 'database', 'tables': tables }, { 'type': 'dataservices', 'services': self.services or [] }]
class Permission(Resource): """ Represents a permission in CARTO. This is an internal data type, with no specific API endpoints """ acl = None created_at = DateTimeField() entity = EntityField() id = CharField() owner = UserField() updated_at = DateTimeField()
class DoToken(WarnResource): """ Represents a Data Observatory token in CARTO. .. warning:: Non-public API. It may change with no previous notice """ access_token = CharField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "access_token"
class TableGrant(Resource): """ Describes to which tables and which privleges on each table this API Key grants access to trough tables attribute. This is an internal data type, with no specific API endpoints See https://carto.com/developers/auth-api/reference/#section/API-Key-format Example: .. code:: { "type": "database", "tables": [ { "schema": "public", "name": "my_table", "permissions": [ "insert", "select", "update" ] } ] } """ schema = CharField() name = CharField() permissions = CharField(many=True) def to_json(self): return { 'schema': self.schema, 'name': self.name, 'permissions': self.permissions }
class DOSubscriptionInfo(Resource): """ Represents a Data Observatory Subscriptions in CARTO. """ id = CharField() estimated_delivery_days = FloatField() subscription_list_price = FloatField() tos = CharField() tos_link = CharField() licenses = CharField() licenses_link = CharField() rights = CharField() type = CharField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "id"
class DoToken(WarnResource): """ Represents a Data Observatory token in CARTO. .. warning:: Non-public API. It may change with no previous notice """ access_token = CharField() bq_public_project = CharField() gcp_execution_project = CharField() bq_project = CharField() bq_dataset = CharField() gcs_bucket = CharField() instant_licensing = BooleanField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "access_token"
class Dataset(WarnResource): """ Represents a dataset in CARTO. Typically, that means there is a table in the PostgreSQL server associated to this object. .. warning:: Non-public API. It may change with no previous notice """ active_child = CharField() active_layer_id = CharField() attributions = CharField() auth_tokens = CharField(many=True) children = CharField() created_at = DateTimeField() connector = CharField() dependent_visualizations = VisualizationField(many=True) dependent_visualizations_count = IntegerField() description = CharField() display_name = CharField() external_source = CharField() id = CharField() kind = CharField() license = CharField() liked = BooleanField() likes = IntegerField() locked = BooleanField() map_id = CharField() name = CharField() next_id = CharField() parent_id = CharField() permission = PermissionField() prev_id = CharField() privacy = CharField() source = CharField() stats = DateTimeField(many=True) synchronization = SynchronizationField() table = TableField() tags = CharField(many=True) title = CharField() transition_options = DictField() type = CharField() updated_at = DateTimeField() url = CharField() uses_builder_features = BooleanField() user = UserField() def delete(self): if self.dependent_visualizations_count > 0: raise CartoException( _('This dataset contains dependent visualizations. ' + 'Delete them to be able to delete this dataset or use `force_delete` ' + 'to delete the dataset and the dependent visualizations.')) super(WarnResource, self).delete() def force_delete(self): super(WarnResource, self).delete() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "name"
class SyncTableJob(AsyncResource): """ This class provides support for creating Sync Tables into CARTO """ id = CharField() name = CharField() interval = IntegerField() url = CharField() state = CharField() created_at = DateTimeField() updated_at = DateTimeField() run_at = DateTimeField() retried_times = IntegerField() log_id = CharField() error_code = IntegerField() error_message = CharField() ran_at = DateTimeField() modified_at = DateTimeField() etag = CharField() checksum = CharField() user_id = CharField() service_name = CharField() service_item_id = CharField() success = BooleanField() type_guessing = BooleanField() quoted_fields_guessing = BooleanField() content_guessing = BooleanField() visualization_id = CharField() from_external_source = BooleanField() synchronization_id = CharField() enqueued = BooleanField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) def __init__(self, url, interval, auth_client): """ :param url: Remote URL for the file :param interval: Number of seconds between update intervals (>=900) :param client: Client to make authorized requests (currently only APIKeyAuthClient is supported) :type url: str :type interval: int :type client: :class:`carto.auth.APIKeyAuthClient` :return: """ self.url = url self.interval = interval super(SyncTableJob, self).__init__(auth_client) def run(self, **import_params): """ Actually creates the job import on the CARTO server :param import_params: To be send to the Import API, see CARTO's docs on Import API for an updated list of accepted params :type import_params: kwargs :return: .. note:: The sync table job is asynchronous, so you should take care of the progression, by calling the :func:`carto.resources.AsyncResource.refresh` method and check the import job :py:attr:`~state` attribute. See :func:`carto.datasets.DatasetManager.create` for a unified method to import files into CARTO """ import_params["url"] = self.url import_params["interval"] = self.interval if "connection" in import_params: self.fields.append("connector") import_params["connection"]["interval"] = self.interval self.update_from_dict(import_params["connection"]) self.save(force_create=True) else: return super(SyncTableJob, self).run(params=import_params) def get_force_sync_endpoint(self): """ Get the relative path to the specific API resource :return: Relative path to the resource :raise: CartoException """ return urljoin(self.get_resource_endpoint(), API_FORCE_SYNC_SUFFIX) def force_sync(self): """ Forces to sync the SyncTableJob :return: :raise: CartoException """ try: self.send(self.get_resource_endpoint(), "put") except Exception as e: raise CartoException(e)
class FileImportJob(AsyncResource): """ This class provides support for one-time uploading and importing of remote and local files into CARTO """ item_queue_id = CharField() id = CharField() user_id = CharField() table_id = CharField() data_type = CharField() table_name = CharField() state = CharField() error_code = IntegerField() queue_id = CharField() tables_created_count = IntegerField() synchronization_id = CharField() type_guessing = BooleanField() quoted_fields_guessing = BooleanField() content_guessing = BooleanField() create_visualization = BooleanField() visualization_id = CharField() user_defined_limits = CharField() get_error_text = None display_name = CharField() success = BooleanField() warnings = None is_raster = BooleanField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) id_field = "item_queue_id" def __init__(self, archive, auth_client): """ :param auth_client: Client to make authorized requests (currently only APIKeyAuthClient is supported) :param archive: archive can be a pointer to a remote location, a path to a local file or a StringIO object :type auth_client: :class:`carto.auth.APIKeyAuthClient` :type archive: str :return: """ self.file = None self.files = None if archive is not None: if hasattr(archive, "startswith") and archive.startswith("http"): self.file = archive else: self.files = {'file': self.__open(archive, 'rb')} super(FileImportJob, self).__init__(auth_client) def run(self, **import_params): """ Actually creates the import job on the CARTO server :param import_params: To be send to the Import API, see CARTO's docs on Import API for an updated list of accepted params :type import_params: kwargs :return: .. note:: The import job is asynchronous, so you should take care of the progression, by calling the :func:`carto.resources.AsyncResource.refresh` method and check the import job :py:attr:`~state` attribute. See :func:`carto.datasets.DatasetManager.create` for a unified method to import files into CARTO """ if self.file: import_params["url"] = self.file self.id_field = "id" if "connection" in import_params: self.fields.append("connector") self.update_from_dict(import_params["connection"]) self.save(force_create=True) else: super(FileImportJob, self).run(params=import_params, files=self.files) def __open(self, name, mode): if hasattr(name, "read"): return name else: return open(name, mode)
class Visualization(WarnResource): """ Represents a map visualization in CARTO. .. warning:: Non-public API. It may change with no previous notice """ active_child = CharField() active_layer_id = CharField() attributions = CharField() auth_tokens = CharField(many=True) children = CharField(many=True) created_at = DateTimeField() description = CharField() display_name = CharField() external_source = DictField() id = CharField() kind = CharField() license = CharField() liked = BooleanField() likes = IntegerField() locked = BooleanField() map_id = CharField() name = CharField() next_id = CharField() parent_id = CharField() permission = PermissionField() prev_id = CharField() privacy = CharField() source = CharField() stats = DictField() synchronization = SynchronizationField() table = TableField() related_tables = TableField(many=True) tags = CharField(many=True) title = CharField() transition_options = DictField() type = CharField() updated_at = DateTimeField() url = CharField() uses_builder_features = BooleanField() version = IntegerField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "name" def export(self): """ Make the actual request to the Import API (exporting is part of the Import API) to export a map visualization as a .carto file :return: A URL pointing to the .carto file :rtype: str :raise: CartoException .. warning:: Non-public API. It may change with no previous notice .. note:: The export is asynchronous, but this method waits for the export to complete. See `MAX_NUMBER_OF_RETRIES` and `INTERVAL_BETWEEN_RETRIES_S` """ export_job = ExportJob(self.client, self.get_id()) export_job.run() export_job.refresh() count = 0 while export_job.state in ("exporting", "enqueued", "pending"): if count >= MAX_NUMBER_OF_RETRIES: raise CartoException( _("Maximum number of retries exceeded \ when polling the import API for \ visualization export")) time.sleep(INTERVAL_BETWEEN_RETRIES_S) export_job.refresh() count += 1 if export_job.state == "failure": raise CartoException(_("Visualization export failed")) if (export_job.state != "complete" and export_job.state != "created"): raise CartoException( _("Unexpected problem on visualization export \ (state: {state})").format( state=export_job.state)) return export_job.url
class User(WarnResource): """ Represents an enterprise CARTO user, i.e. a user that belongs to an organization Currently, CARTO's user API only supports enterprise users. .. warning:: Non-public API. It may change with no previous notice """ all_visualization_count = IntegerField() available_for_hire = BooleanField() avatar_url = CharField() base_url = CharField() db_size_in_bytes = IntegerField() description = CharField() disqus_shortname = CharField() email = CharField() google_maps_query_string = CharField() last_name = CharField() location = CharField() name = CharField() org_admin = BooleanField() org_user = BooleanField() password = CharField() public_visualization_count = IntegerField() quota_in_bytes = IntegerField() remove_logo = BooleanField() soft_geocoding_limit = IntegerField() table_count = IntegerField() twitter_username = CharField() username = CharField() viewer = BooleanField() website = CharField() class Meta: id_field = "username" name_field = "username" def __init__(self, auth_client): """ Sets the collection endpoint dynamically, based on provided organization (see api/auth.py) :param auth_client: Auth client """ if auth_client.organization is None: self._api_endpoint = API_NONORG_ENDPOINT else: self._api_endpoint = API_ENDPOINT super(User, self).__init__(auth_client) def get_collection_endpoint(self): """ """ return self._api_endpoint.format(api_version=API_VERSION, organization=self.client.organization) def get_resource_endpoint(self): """ """ resource_id = getattr(self, self.Meta.id_field, None) if resource_id is None: return None return urljoin(self.get_collection_endpoint(), str(resource_id))
class Dataset(WarnResource): """ Represents a dataset in CARTO. Typically, that means there is a table in the PostgreSQL server associated to this object. .. warning:: Non-public API. It may change with no previous notice """ active_child = None active_layer_id = CharField() attributions = CharField() auth_tokens = CharField(many=True) children = None created_at = DateTimeField() connector = None description = CharField() display_name = CharField() external_source = None id = CharField() kind = CharField() license = CharField() liked = BooleanField() likes = IntegerField() locked = BooleanField() map_id = CharField() name = CharField() next_id = None parent_id = CharField() permission = PermissionField() prev_id = None privacy = CharField() source = None stats = DateTimeField(many=True) synchronization = None table = TableField() tags = CharField(many=True) title = CharField() transition_options = None type = CharField() updated_at = DateTimeField() url = CharField() uses_builder_features = BooleanField() user = UserField() class Meta: collection_endpoint = API_ENDPOINT.format(api_version=API_VERSION) name_field = "name"
class Synchronization(Resource): """ Represents a synchronization in CARTO. This is an internal data type, with no specific API endpoints """ checksum = CharField() created_at = DateTimeField() error_code = CharField() error_message = CharField() id = CharField() interval = IntegerField() modified_at = DateTimeField() name = CharField() ran_at = DateTimeField() retried_times = IntegerField() run_at = DateTimeField() service_item_id = CharField() service_name = CharField() state = CharField() updated_at = DateTimeField() url = CharField() user_id = CharField() content_guessing = BooleanField() etag = CharField() log_id = BooleanField() quoted_fields_guessing = BooleanField() type_guessing = BooleanField() from_external_source = BooleanField() visualization_id = BooleanField()