예제 #1
0
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)
예제 #2
0
class Entity(Resource):
    """
    Represents an entity in CARTO. This is an internal data type, with no
    specific API endpoints
    """
    id = CharField()
    type = CharField()
예제 #3
0
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)
예제 #4
0
파일: users.py 프로젝트: drw/carto-python
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))
예제 #5
0
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"
예제 #6
0
class Choice(Resource):
    id = IntegerField()
    question = QuestionField()
    choice_text = CharField()
    votes = IntegerField()

    class Meta:
        name_field = "choice_text"
예제 #7
0
class Question(Resource):
    id = IntegerField()
    question_text = CharField()
    pub_date = DateTimeField()
    choices = ChoiceField(many=True)

    class Meta:
        name_field = "question_text"
예제 #8
0
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"
예제 #9
0
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"
예제 #10
0
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 []
        }]
예제 #11
0
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()
예제 #12
0
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"
예제 #13
0
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
        }
예제 #14
0
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"
예제 #15
0
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"
예제 #16
0
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"
예제 #17
0
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)
예제 #18
0
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)
예제 #19
0
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
예제 #20
0
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))
예제 #21
0
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"
예제 #22
0
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()