-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
385 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,235 @@ | ||
import pydeck as pdk | ||
from typing import Any, TypedDict, List | ||
from typing_extensions import NotRequired, Unpack, assert_type | ||
|
||
# TYPES | ||
|
||
def base_source(connection_name: str, access_token: str, api_base_url: str): | ||
|
||
class Options(TypedDict): | ||
pass | ||
|
||
|
||
class BaseSourceOptions(Options): | ||
connection_name: str | ||
access_token: str | ||
api_base_url: str | ||
|
||
|
||
class TableSourceOptions(BaseSourceOptions): | ||
table_name: str | ||
spatial_data_column: NotRequired[str] | ||
|
||
|
||
class QuerySourceOptions(BaseSourceOptions): | ||
sql_query: str | ||
spatial_data_column: NotRequired[str] | ||
|
||
|
||
class TilesetSourceOptions(BaseSourceOptions): | ||
table_name: str | ||
|
||
|
||
class ColumnOptions(Options): | ||
columns: NotRequired[List[str]] | ||
|
||
|
||
class AggregationOptions(Options): | ||
aggregation_exp: str | ||
aggregation_res_level: NotRequired[int] | ||
|
||
|
||
# VALIDATORS | ||
|
||
# The 'interface' arguments are unused, but could be used with | ||
# 'get_type_hints' to provide type hints in the future. | ||
|
||
|
||
def validate_str( | ||
interface: Any, args: Options, arg: str, required: bool = True | ||
): | ||
"""Validates given key on an options object is a string.""" | ||
if arg not in args and required: | ||
raise AssertionError('Missing argument "{}".'.format(arg)) | ||
elif arg in args: | ||
assert type(args[arg]) is str, "Argument {} must be of type str".format(arg) | ||
|
||
|
||
def validate_int( | ||
interface: Any, args: Options, arg: str, required: bool = True | ||
): | ||
"""Validates given key on an options object is an int.""" | ||
if arg not in args and required: | ||
raise AssertionError('Missing argument "{}".'.format(arg)) | ||
elif arg in args: | ||
assert type(args[arg]) is int, "Argument {} must be of type int".format(arg) | ||
|
||
|
||
# BASE | ||
|
||
|
||
def base_options(**kwargs: Unpack[BaseSourceOptions]): | ||
assert_type(kwargs, BaseSourceOptions) | ||
validate_str(BaseSourceOptions, kwargs, "connection_name") | ||
validate_str(BaseSourceOptions, kwargs, "access_token") | ||
validate_str(BaseSourceOptions, kwargs, "api_base_url") | ||
return { | ||
"connectionName": connection_name, | ||
"accessToken": access_token, | ||
"apiBaseUrl": api_base_url, | ||
"connectionName": kwargs["connection_name"], | ||
"accessToken": kwargs["access_token"], | ||
"apiBaseUrl": kwargs["api_base_url"], | ||
"clientId": "pydeck-carto", | ||
} | ||
|
||
|
||
def vector_table_source(table_name: str, spatial_data_column: str, **kwargs): | ||
def table_options(**kwargs: Unpack[TableSourceOptions]): | ||
assert_type(kwargs, TableSourceOptions) | ||
validate_str(TableSourceOptions, kwargs, "table_name") | ||
validate_str(TableSourceOptions, kwargs, "spatial_data_column", False) | ||
return { | ||
"tableName": kwargs.get("table_name"), | ||
**({"spatialDataColumn": kwargs["spatial_data_column"]} if "spatial_data_column" in kwargs else {}), | ||
**base_options(**kwargs), | ||
} | ||
|
||
|
||
def query_options(**kwargs: Unpack[QuerySourceOptions]): | ||
assert_type(kwargs, QuerySourceOptions) | ||
validate_str(TableSourceOptions, kwargs, "sql_query") | ||
validate_str(TableSourceOptions, kwargs, "spatial_data_column", False) | ||
return { | ||
"sqlQuery": kwargs.get("sql_query"), | ||
**({"spatialDataColumn": kwargs["spatial_data_column"]} if "spatial_data_column" in kwargs else {}), | ||
**base_options(**kwargs), | ||
} | ||
|
||
|
||
def tileset_options(**kwargs: Unpack[TilesetSourceOptions]): | ||
assert_type(kwargs, TilesetSourceOptions) | ||
validate_str(TableSourceOptions, kwargs, "table_name") | ||
return { | ||
"tableName": kwargs["table_name"], | ||
**base_options(**kwargs), | ||
} | ||
|
||
|
||
def column_options(**kwargs: Unpack[ColumnOptions]): | ||
assert_type(kwargs, ColumnOptions) | ||
return {"columns": kwargs["columns"]} if "columns" in kwargs else {} | ||
|
||
|
||
def aggregation_options(**kwargs: Unpack[AggregationOptions]): | ||
assert_type(kwargs, AggregationOptions) | ||
validate_str(AggregationOptions, kwargs, "aggregation_exp") | ||
validate_int(AggregationOptions, kwargs, "aggregation_res_level", False) | ||
return { | ||
"aggregationExp": kwargs["aggregation_exp"], | ||
**({"aggregationResLevel": kwargs["aggregation_res_level"]} if "aggregation_res_level" in kwargs else {}), | ||
} | ||
|
||
|
||
# VECTOR | ||
|
||
|
||
class VectorTableSourceOptions(TableSourceOptions, ColumnOptions): | ||
pass | ||
|
||
|
||
class VectorQuerySourceOptions(QuerySourceOptions, ColumnOptions): | ||
pass | ||
|
||
|
||
class VectorTilesetSourceOptions(TilesetSourceOptions): | ||
pass | ||
|
||
|
||
def vector_table_source(**kwargs: Unpack[VectorTableSourceOptions]): | ||
return pdk.types.Function( | ||
"vectorTableSource", **{**column_options(**kwargs), **table_options(**kwargs)} | ||
) | ||
|
||
|
||
def vector_query_source(**kwargs: Unpack[VectorQuerySourceOptions]): | ||
return pdk.types.Function( | ||
"vectorQuerySource", **{**column_options(**kwargs), **query_options(**kwargs)} | ||
) | ||
|
||
|
||
def vector_tileset_source(**kwargs: Unpack[VectorTilesetSourceOptions]): | ||
return pdk.types.Function("vectorTilesetSource", **tileset_options(**kwargs)) | ||
|
||
|
||
# H3 | ||
|
||
|
||
class H3TableSourceOptions(TableSourceOptions, AggregationOptions): | ||
pass | ||
|
||
|
||
class H3QuerySourceOptions(QuerySourceOptions, AggregationOptions): | ||
pass | ||
|
||
|
||
class H3TilesetSourceOptions(TilesetSourceOptions, AggregationOptions): | ||
pass | ||
|
||
|
||
def h3_table_source(**kwargs: Unpack[H3TableSourceOptions]): | ||
return pdk.types.Function( | ||
"vectorTableSource", | ||
**{ | ||
"tableName": table_name, | ||
"spatialDataColumn": spatial_data_column, | ||
**base_source(**kwargs), | ||
} | ||
"h3TableSource", **{**aggregation_options(**kwargs), **table_options(**kwargs)} | ||
) | ||
|
||
|
||
def vector_query_source(sql_query: str, spatial_data_column: str, **kwargs): | ||
def h3_query_source(**kwargs: Unpack[H3QuerySourceOptions]): | ||
return pdk.types.Function( | ||
"vectorQuerySource", | ||
**{ | ||
"sqlQuery": sql_query, | ||
"spatialDataColumn": spatial_data_column, | ||
**base_source(**kwargs), | ||
} | ||
"h3QuerySource", **{**aggregation_options(**kwargs), **query_options(**kwargs)} | ||
) | ||
|
||
|
||
def vector_tileset_source(table_name: str, **kwargs): | ||
def h3_tileset_source(**kwargs: Unpack[H3TilesetSourceOptions]): | ||
return pdk.types.Function( | ||
"vectorTilesetSource", **{"tableName": table_name, **base_source(**kwargs)} | ||
"h3TilesetSource", | ||
**tileset_options(**kwargs) | ||
) | ||
|
||
|
||
# TODO: Implement all the source functions and parameters | ||
# https://felixpalmer.github.io/deck.gl/docs/api-reference/carto/data-sources | ||
# h3_table_source | ||
# h3_query_source | ||
# h3_tileset_source | ||
# quadbin_table_source | ||
# quadbin_query_source | ||
# quadbin_tileset_source | ||
# raster_tileset_source (experimental) | ||
# QUADBIN | ||
|
||
|
||
class QuadbinTableSourceOptions(TableSourceOptions, AggregationOptions): | ||
pass | ||
|
||
|
||
class QuadbinQuerySourceOptions(QuerySourceOptions, AggregationOptions): | ||
pass | ||
|
||
|
||
class QuadbinTilesetSourceOptions(TilesetSourceOptions, AggregationOptions): | ||
pass | ||
|
||
|
||
def quadbin_table_source(**kwargs: Unpack[QuadbinTableSourceOptions]): | ||
return pdk.types.Function( | ||
"quadbinTableSource", | ||
**{**aggregation_options(**kwargs), **table_options(**kwargs)} | ||
) | ||
|
||
|
||
def quadbin_query_source(**kwargs: Unpack[QuadbinQuerySourceOptions]): | ||
return pdk.types.Function( | ||
"quadbinQuerySource", | ||
**{**aggregation_options(**kwargs), **query_options(**kwargs)} | ||
) | ||
|
||
|
||
def quadbin_tileset_source(**kwargs: Unpack[QuadbinTilesetSourceOptions]): | ||
return pdk.types.Function( | ||
"quadbinTilesetSource", | ||
**tileset_options(**kwargs) | ||
) | ||
|
||
|
||
# RASTER (EXPERIMENTAL) | ||
|
||
|
||
def raster_tileset_source(**kwargs): | ||
"""EXPERIMENTAL.""" | ||
raise RuntimeError("not implemented") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
wheel==0.37.1 | ||
flake8==4.0.1 | ||
black==22.3.0 | ||
carto-auth>=0.2.0 | ||
flake8==4.0.1 | ||
ipython>=7.8.0 | ||
tokenize-rt>=3.2.0 | ||
twine==4.0.0 | ||
pytest-cov==3.0.0 | ||
pytest-mock==3.8.2 | ||
pytest==7.1.2 | ||
requests-mock==1.9.3 | ||
pytest-mock==3.8.2 | ||
pytest-cov==3.0.0 | ||
tokenize-rt>=3.2.0 | ||
twine==4.0.0 | ||
typing-extensions>=4.0.0 | ||
wheel==0.37.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.