spotlight-sdk 0.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spotlight-sdk-0.0.0/PKG-INFO +36 -0
- spotlight-sdk-0.0.0/README.md +22 -0
- spotlight-sdk-0.0.0/setup.cfg +4 -0
- spotlight-sdk-0.0.0/setup.py +50 -0
- spotlight-sdk-0.0.0/spotlight/__init__.py +3 -0
- spotlight-sdk-0.0.0/spotlight/api/__init__.py +0 -0
- spotlight-sdk-0.0.0/spotlight/api/auth/__init__.py +9 -0
- spotlight-sdk-0.0.0/spotlight/api/auth/__util.py +49 -0
- spotlight-sdk-0.0.0/spotlight/api/auth/asynchronous.py +69 -0
- spotlight-sdk-0.0.0/spotlight/api/auth/synchronous.py +60 -0
- spotlight-sdk-0.0.0/spotlight/api/data/__init__.py +17 -0
- spotlight-sdk-0.0.0/spotlight/api/data/__util.py +13 -0
- spotlight-sdk-0.0.0/spotlight/api/data/asynchronous.py +82 -0
- spotlight-sdk-0.0.0/spotlight/api/data/model.py +47 -0
- spotlight-sdk-0.0.0/spotlight/api/data/synchronous.py +82 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/__init__.py +16 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/__util.py +29 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/abstract/__init__.py +16 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/abstract/__util.py +34 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/abstract/asynchronous.py +113 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/abstract/model.py +38 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/abstract/synchronous.py +107 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/asynchronous.py +107 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/model.py +57 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/synchronous.py +107 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/view/__init__.py +10 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/view/__util.py +16 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/view/asynchronous.py +57 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/view/model.py +26 -0
- spotlight-sdk-0.0.0/spotlight/api/dataset/view/synchronous.py +55 -0
- spotlight-sdk-0.0.0/spotlight/api/permission/__init__.py +19 -0
- spotlight-sdk-0.0.0/spotlight/api/permission/__util.py +25 -0
- spotlight-sdk-0.0.0/spotlight/api/permission/asynchronous.py +116 -0
- spotlight-sdk-0.0.0/spotlight/api/permission/enum.py +7 -0
- spotlight-sdk-0.0.0/spotlight/api/permission/model.py +12 -0
- spotlight-sdk-0.0.0/spotlight/api/permission/synchronous.py +109 -0
- spotlight-sdk-0.0.0/spotlight/core/__init__.py +0 -0
- spotlight-sdk-0.0.0/spotlight/core/common/__init__.py +3 -0
- spotlight-sdk-0.0.0/spotlight/core/common/base.py +91 -0
- spotlight-sdk-0.0.0/spotlight/core/common/base_enum.py +14 -0
- spotlight-sdk-0.0.0/spotlight/core/common/config.py +89 -0
- spotlight-sdk-0.0.0/spotlight/core/common/date/__init__.py +8 -0
- spotlight-sdk-0.0.0/spotlight/core/common/date/function.py +103 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/__init__.py +10 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/authorization/__init__.py +9 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/authorization/__util.py +36 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/authorization/asynchronous.py +120 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/authorization/synchronous.py +123 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/data/__init__.py +5 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/data/__util.py +25 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/data/asynchronous.py +45 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/data/synchronous.py +45 -0
- spotlight-sdk-0.0.0/spotlight/core/common/decorators/timeit.py +30 -0
- spotlight-sdk-0.0.0/spotlight/core/common/enum.py +42 -0
- spotlight-sdk-0.0.0/spotlight/core/common/errors.py +34 -0
- spotlight-sdk-0.0.0/spotlight/core/common/function.py +174 -0
- spotlight-sdk-0.0.0/spotlight/core/common/metaclass/__init__.py +0 -0
- spotlight-sdk-0.0.0/spotlight/core/common/metaclass/singleton.py +37 -0
- spotlight-sdk-0.0.0/spotlight/core/common/requests/__init__.py +15 -0
- spotlight-sdk-0.0.0/spotlight/core/common/requests/asynchronous.py +164 -0
- spotlight-sdk-0.0.0/spotlight/core/common/requests/synchronous.py +143 -0
- spotlight-sdk-0.0.0/spotlight/core/common/type.py +10 -0
- spotlight-sdk-0.0.0/spotlight_sdk.egg-info/PKG-INFO +36 -0
- spotlight-sdk-0.0.0/spotlight_sdk.egg-info/SOURCES.txt +65 -0
- spotlight-sdk-0.0.0/spotlight_sdk.egg-info/dependency_links.txt +1 -0
- spotlight-sdk-0.0.0/spotlight_sdk.egg-info/requires.txt +11 -0
- spotlight-sdk-0.0.0/spotlight_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: spotlight-sdk
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: Spotlight Python SDK
|
|
5
|
+
Home-page: https://spotlight.dev
|
|
6
|
+
Author: Spotlight
|
|
7
|
+
Author-email: hello@spotlight.dev
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description: # Spotlight: The OTC Commodity Research Platform
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
**[Spotlight](https://spotlight.dev/)** is the world's first OTC commodity research platform. Stay on top of market
|
|
14
|
+
trends, discover new product opportunities, and win more sales.
|
|
15
|
+
|
|
16
|
+
The [Spotlight SDK](https://pypi.org/project/spotlight-sdk/) enables you to programmatically query dataset configurations and data.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Set the following environment variables for your username and password for
|
|
21
|
+
the [Spotlight platform](https://app.spotlight.dev/).
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
SPOTLIGHT_USER=<username>
|
|
25
|
+
SPOTLIGHT_PWD=<password>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Support
|
|
29
|
+
|
|
30
|
+
If you need help or have feedback, please email us at [support@spotlight.dev](mailto:support@spotlight.dev).
|
|
31
|
+
|
|
32
|
+
Platform: UNKNOWN
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Operating System :: OS Independent
|
|
35
|
+
Requires-Python: >=3.7
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Spotlight: The OTC Commodity Research Platform
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
**[Spotlight](https://spotlight.dev/)** is the world's first OTC commodity research platform. Stay on top of market
|
|
6
|
+
trends, discover new product opportunities, and win more sales.
|
|
7
|
+
|
|
8
|
+
The [Spotlight SDK](https://pypi.org/project/spotlight-sdk/) enables you to programmatically query dataset configurations and data.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Set the following environment variables for your username and password for
|
|
13
|
+
the [Spotlight platform](https://app.spotlight.dev/).
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
SPOTLIGHT_USER=<username>
|
|
17
|
+
SPOTLIGHT_PWD=<password>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Support
|
|
21
|
+
|
|
22
|
+
If you need help or have feedback, please email us at [support@spotlight.dev](mailto:support@spotlight.dev).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
import setuptools
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
import pypandoc
|
|
7
|
+
|
|
8
|
+
long_description = pypandoc.convert_file('README.md', 'rst')
|
|
9
|
+
except(IOError, ImportError):
|
|
10
|
+
long_description = open('README.md').read()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_tag():
|
|
14
|
+
tag = subprocess.getoutput('git tag --sort=version:refname | tail -n1')
|
|
15
|
+
commits = subprocess.getoutput(f'git rev-list {tag}..HEAD --count')
|
|
16
|
+
return f'{tag}.{commits}'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
setuptools.setup(
|
|
20
|
+
name="spotlight-sdk",
|
|
21
|
+
version=get_tag(),
|
|
22
|
+
author="Spotlight",
|
|
23
|
+
author_email="hello@spotlight.dev",
|
|
24
|
+
description="Spotlight Python SDK",
|
|
25
|
+
long_description=long_description,
|
|
26
|
+
long_description_content_type="text/markdown",
|
|
27
|
+
url="https://spotlight.dev",
|
|
28
|
+
classifiers=[
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Operating System :: OS Independent"
|
|
31
|
+
],
|
|
32
|
+
python_requires=">=3.7",
|
|
33
|
+
packages=setuptools.find_packages(
|
|
34
|
+
include=['spotlight*'],
|
|
35
|
+
exclude=['tests.*']
|
|
36
|
+
),
|
|
37
|
+
install_requires=[
|
|
38
|
+
"requests==2.28.1",
|
|
39
|
+
"aiohttp>=3.8.4",
|
|
40
|
+
"pandas>=2.0.1",
|
|
41
|
+
"duckdb>=0.7.1",
|
|
42
|
+
"trycast>=1.0.0",
|
|
43
|
+
"pydash>=7.0.3",
|
|
44
|
+
"cachetools>=5.3.0",
|
|
45
|
+
"pydantic>=1.10.7",
|
|
46
|
+
"aiocache>=0.12.1",
|
|
47
|
+
"backoff>=2.2.1",
|
|
48
|
+
"asyncstdlib>=3.10.7"
|
|
49
|
+
]
|
|
50
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from spotlight.core.common.config import EnvironmentConfig
|
|
4
|
+
|
|
5
|
+
config = EnvironmentConfig()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _login_request_info(
|
|
9
|
+
username: str, password: str, scope: Optional[str] = None
|
|
10
|
+
) -> dict:
|
|
11
|
+
data = {
|
|
12
|
+
"client_id": "spotlight-api",
|
|
13
|
+
"grant_type": "password",
|
|
14
|
+
"username": username,
|
|
15
|
+
"password": password,
|
|
16
|
+
}
|
|
17
|
+
if scope is not None:
|
|
18
|
+
data.update({"scope": scope})
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
"url": f"{config.get_url('keycloak')}/protocol/openid-connect/token",
|
|
22
|
+
"data": data,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _refresh_token_request_info(refresh_token: Optional[str] = None) -> dict:
|
|
27
|
+
return {
|
|
28
|
+
"url": f"{config.get_url('keycloak')}/protocol/openid-connect/token",
|
|
29
|
+
"data": {
|
|
30
|
+
"client_id": "spotlight-api",
|
|
31
|
+
"grant_type": "refresh_token",
|
|
32
|
+
"refresh_token": refresh_token,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _token_exchange_request_info(requested_subject: str, subject_token: str) -> dict:
|
|
38
|
+
data = {
|
|
39
|
+
"client_id": "spotlight-api",
|
|
40
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
41
|
+
"requested_subject": requested_subject,
|
|
42
|
+
"subject_token": subject_token,
|
|
43
|
+
"scope": "offline_access",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
"url": f"{config.get_url('keycloak')}/protocol/openid-connect/token",
|
|
48
|
+
"data": data,
|
|
49
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Asynchronous auth API requests.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import aiohttp
|
|
7
|
+
from requests import Response
|
|
8
|
+
|
|
9
|
+
from spotlight.api.auth.__util import (
|
|
10
|
+
_login_request_info,
|
|
11
|
+
_refresh_token_request_info,
|
|
12
|
+
_token_exchange_request_info,
|
|
13
|
+
)
|
|
14
|
+
from spotlight.core.common.function import build_response_obj
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def async_login(
|
|
18
|
+
username: str, password: str, scope: Optional[str] = None
|
|
19
|
+
) -> Response:
|
|
20
|
+
"""
|
|
21
|
+
Asynchronously login.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
username (str): Username
|
|
25
|
+
password (str): Password
|
|
26
|
+
scope (Optional[str]): Token scope, such as 'offline_access'
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
dict: Authentication/authorization response
|
|
30
|
+
"""
|
|
31
|
+
request_info = _login_request_info(username, password, scope)
|
|
32
|
+
async with aiohttp.ClientSession() as session:
|
|
33
|
+
async with session.post(**request_info) as response:
|
|
34
|
+
return await build_response_obj(response)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def async_refresh_token(token: Optional[str]) -> Response:
|
|
38
|
+
"""
|
|
39
|
+
Asynchronously refresh token. To get an offline access token, initial authentication (login) needs to use the scope
|
|
40
|
+
'offline_access', then an offline token can be created using the refresh_token in the authentication response.
|
|
41
|
+
[Stack overflow reference](https://stackoverflow.com/questions/69207734/keycloak-offline-access-token-with-refresh-token-grant-type).
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
token (str): Refresh token
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
dict: Authentication/authorization response
|
|
48
|
+
"""
|
|
49
|
+
request_info = _refresh_token_request_info(token)
|
|
50
|
+
async with aiohttp.ClientSession() as session:
|
|
51
|
+
async with session.post(**request_info) as response:
|
|
52
|
+
return await build_response_obj(response)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async def async_exchange_token(requested_subject: str, subject_token: str) -> Response:
|
|
56
|
+
"""
|
|
57
|
+
Asynchronously exchange token.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
requested_subject (str): Request subject (Username or ID)
|
|
61
|
+
subject_token (str): Token to swap
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
dict: Authentication/authorization response
|
|
65
|
+
"""
|
|
66
|
+
request_info = _token_exchange_request_info(requested_subject, subject_token)
|
|
67
|
+
async with aiohttp.ClientSession() as session:
|
|
68
|
+
async with session.post(**request_info) as response:
|
|
69
|
+
return await build_response_obj(response)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auth API requests.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
from requests import Response
|
|
8
|
+
|
|
9
|
+
from spotlight.api.auth.__util import (
|
|
10
|
+
_login_request_info,
|
|
11
|
+
_refresh_token_request_info,
|
|
12
|
+
_token_exchange_request_info,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def login(username: str, password: str, scope: Optional[str] = None) -> Response:
|
|
17
|
+
"""
|
|
18
|
+
Login.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
username (str): Username
|
|
22
|
+
password (str): Password
|
|
23
|
+
scope (Optional[str]): Token scope, such as 'offline_access'
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
dict: Authentication/authorization response
|
|
27
|
+
"""
|
|
28
|
+
request_info = _login_request_info(username, password, scope)
|
|
29
|
+
return requests.post(**request_info)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def refresh_token(token: Optional[str]) -> Response:
|
|
33
|
+
"""
|
|
34
|
+
Refresh token. To get an offline access token, initial authentication (login) needs to use the scope
|
|
35
|
+
'offline_access', then an offline token can be created using the refresh_token in the authentication response.
|
|
36
|
+
[Stack overflow reference](https://stackoverflow.com/questions/69207734/keycloak-offline-access-token-with-refresh-token-grant-type).
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
token (str): Refresh token
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
dict: Authentication/authorization response
|
|
43
|
+
"""
|
|
44
|
+
request_info = _refresh_token_request_info(token)
|
|
45
|
+
return requests.post(**request_info)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def exchange_token(requested_subject: str, subject_token: str) -> Response:
|
|
49
|
+
"""
|
|
50
|
+
Exchange token.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
requested_subject (str): Request subject (Username or ID)
|
|
54
|
+
subject_token (str): Token to swap
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
dict: Authentication/authorization response
|
|
58
|
+
"""
|
|
59
|
+
request_info = _token_exchange_request_info(requested_subject, subject_token)
|
|
60
|
+
return requests.post(**request_info)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data API query functions for timeseries data.
|
|
3
|
+
"""
|
|
4
|
+
from spotlight.api.data.asynchronous import (
|
|
5
|
+
async_query_timeseries,
|
|
6
|
+
async_query_dataset_csv,
|
|
7
|
+
async_query_distinct_fields,
|
|
8
|
+
_async_query_timeseries,
|
|
9
|
+
_async_query_distinct_fields,
|
|
10
|
+
)
|
|
11
|
+
from spotlight.api.data.synchronous import (
|
|
12
|
+
query_timeseries,
|
|
13
|
+
query_dataset_csv,
|
|
14
|
+
query_distinct_fields,
|
|
15
|
+
_query_timeseries,
|
|
16
|
+
_query_distinct_fields,
|
|
17
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from spotlight.api.data.model import TimeseriesQueryRequest, DistinctQueryRequest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _query_timeseries_request_info(request: TimeseriesQueryRequest) -> dict:
|
|
5
|
+
return {"endpoint": f"data/v1.1/timeseries", "json": request.request_dict()}
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _query_dataset_csv_request_info(id: str, request: TimeseriesQueryRequest) -> dict:
|
|
9
|
+
return {"endpoint": f"data/v1.1/{id}.csv", "json": request.request_dict()}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _query_distinct_fields_request_info(request: DistinctQueryRequest) -> dict:
|
|
13
|
+
return {"endpoint": f"data/v1.1/distinct", "json": request.request_dict()}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from requests import Response
|
|
3
|
+
|
|
4
|
+
from spotlight.api.data.__util import (
|
|
5
|
+
_query_dataset_csv_request_info,
|
|
6
|
+
_query_timeseries_request_info,
|
|
7
|
+
_query_distinct_fields_request_info,
|
|
8
|
+
)
|
|
9
|
+
from spotlight.api.data.model import TimeseriesQueryRequest, DistinctQueryRequest
|
|
10
|
+
from spotlight.core.common.decorators import async_data_request
|
|
11
|
+
from spotlight.core.common.requests import __async_get_request, __async_post_request
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def _async_query_timeseries(request: TimeseriesQueryRequest):
|
|
15
|
+
"""
|
|
16
|
+
Asynchronously query timeseries dataset by timeseries query request.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
request (TimeseriesQueryRequest): Timeseries query request
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Response: Response
|
|
23
|
+
"""
|
|
24
|
+
request_info = _query_timeseries_request_info(request)
|
|
25
|
+
return await __async_post_request(**request_info)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def _async_query_distinct_fields(request: DistinctQueryRequest):
|
|
29
|
+
"""
|
|
30
|
+
Asynchronously query dataset for distinct values of a specified field.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
request (DistinctQueryRequest): Distinct query request
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Response: Response
|
|
37
|
+
"""
|
|
38
|
+
request_info = _query_distinct_fields_request_info(request)
|
|
39
|
+
return await __async_post_request(**request_info)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@async_data_request
|
|
43
|
+
async def async_query_timeseries(request: TimeseriesQueryRequest) -> pd.DataFrame:
|
|
44
|
+
"""
|
|
45
|
+
Asynchronously query timeseries dataset by timeseries query request.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
request (TimeseriesQueryRequest): Timeseries query request
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
pd.DataFrame: Timeseries DataFrame
|
|
52
|
+
"""
|
|
53
|
+
return await _async_query_timeseries(request)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def async_query_dataset_csv(id: str, request: TimeseriesQueryRequest) -> Response:
|
|
57
|
+
"""
|
|
58
|
+
Asynchronously query dataset CSV by ID.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
id (str): Dataset ID
|
|
62
|
+
request (TimeseriesQueryRequest): Timeseries query request
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Response: HTTP response object
|
|
66
|
+
"""
|
|
67
|
+
request_info = _query_dataset_csv_request_info(id, request)
|
|
68
|
+
return await __async_get_request(**request_info)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@async_data_request
|
|
72
|
+
async def async_query_distinct_fields(request: DistinctQueryRequest) -> pd.DataFrame:
|
|
73
|
+
"""
|
|
74
|
+
Asynchronously query dataset for distinct values of a specified field.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
request (DistinctQueryRequest): Distinct query request
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
pd.DataFrame: Timeseries DataFrame
|
|
81
|
+
"""
|
|
82
|
+
return await _async_query_distinct_fields(request)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data classes for API requests.
|
|
3
|
+
"""
|
|
4
|
+
from typing import List, Optional, Any
|
|
5
|
+
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
from spotlight.core.common.base import Base
|
|
9
|
+
from spotlight.core.common.enum import Order, ComparisonOperator, LogicalOperator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Sort(Base):
|
|
13
|
+
field: str
|
|
14
|
+
order: Order
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Filter(Base):
|
|
18
|
+
field: str
|
|
19
|
+
operator: ComparisonOperator
|
|
20
|
+
value: Any
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WhereClause(Base):
|
|
24
|
+
filter: Optional[Filter] = Field(default=None)
|
|
25
|
+
operator: Optional[LogicalOperator] = Field(default=None)
|
|
26
|
+
left: Optional["WhereClause"] = Field(default=None)
|
|
27
|
+
right: Optional["WhereClause"] = Field(default=None)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TimeseriesQueryRequest(Base):
|
|
31
|
+
id: Optional[str] = Field(default=None)
|
|
32
|
+
dataset_name: Optional[str] = Field(default=None)
|
|
33
|
+
reference_name: Optional[str] = Field(default=None)
|
|
34
|
+
page: Optional[int] = Field(default=None)
|
|
35
|
+
limit: Optional[int] = Field(default=None)
|
|
36
|
+
fields: Optional[List[str]] = Field(default=None)
|
|
37
|
+
sort: Optional[List[Sort]] = Field(default=None)
|
|
38
|
+
where: Optional[WhereClause] = Field(default=None)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class DistinctQueryRequest(Base):
|
|
42
|
+
id: Optional[str] = Field(default=None)
|
|
43
|
+
dataset_name: Optional[str] = Field(default=None)
|
|
44
|
+
reference_name: Optional[str] = Field(default=None)
|
|
45
|
+
field: str = Field(default=None)
|
|
46
|
+
sort: Optional[List[Sort]] = Field(default=None)
|
|
47
|
+
where: Optional[WhereClause] = Field(default=None)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from requests import Response
|
|
3
|
+
|
|
4
|
+
from spotlight.api.data.__util import (
|
|
5
|
+
_query_dataset_csv_request_info,
|
|
6
|
+
_query_timeseries_request_info,
|
|
7
|
+
_query_distinct_fields_request_info,
|
|
8
|
+
)
|
|
9
|
+
from spotlight.api.data.model import TimeseriesQueryRequest, DistinctQueryRequest
|
|
10
|
+
from spotlight.core.common.decorators import data_request
|
|
11
|
+
from spotlight.core.common.requests import __get_request, __post_request
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _query_timeseries(request: TimeseriesQueryRequest):
|
|
15
|
+
"""
|
|
16
|
+
Query timeseries dataset by timeseries query request.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
request (TimeseriesQueryRequest): Timeseries query request
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Response: Response
|
|
23
|
+
"""
|
|
24
|
+
request_info = _query_timeseries_request_info(request)
|
|
25
|
+
return __post_request(**request_info)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _query_distinct_fields(request: DistinctQueryRequest):
|
|
29
|
+
"""
|
|
30
|
+
Query dataset for distinct values of a specified field.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
request (DistinctQueryRequest): Distinct query request
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Response: Response
|
|
37
|
+
"""
|
|
38
|
+
request_info = _query_distinct_fields_request_info(request)
|
|
39
|
+
return __post_request(**request_info)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@data_request
|
|
43
|
+
def query_timeseries(request: TimeseriesQueryRequest) -> pd.DataFrame:
|
|
44
|
+
"""
|
|
45
|
+
Query timeseries dataset by timeseries query request.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
request (TimeseriesQueryRequest): Timeseries query request
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
pd.DataFrame: Timeseries DataFrame
|
|
52
|
+
"""
|
|
53
|
+
return _query_timeseries(request)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def query_dataset_csv(id: str, request: TimeseriesQueryRequest) -> Response:
|
|
57
|
+
"""
|
|
58
|
+
Query dataset CSV by ID.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
id (str): Dataset ID
|
|
62
|
+
request (TimeseriesQueryRequest): Timeseries query request
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Response: HTTP response object
|
|
66
|
+
"""
|
|
67
|
+
request_info = _query_dataset_csv_request_info(id, request)
|
|
68
|
+
return __get_request(**request_info)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@data_request
|
|
72
|
+
def query_distinct_fields(request: DistinctQueryRequest) -> pd.DataFrame:
|
|
73
|
+
"""
|
|
74
|
+
Query dataset for distinct values of a specified field.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
request (DistinctQueryRequest): Distinct query request
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
pd.DataFrame: Timeseries DataFrame
|
|
81
|
+
"""
|
|
82
|
+
return _query_distinct_fields(request)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from spotlight.api.dataset.asynchronous import (
|
|
2
|
+
async_get_dataset,
|
|
3
|
+
async_get_datasets,
|
|
4
|
+
async_create_dataset,
|
|
5
|
+
async_update_dataset,
|
|
6
|
+
async_delete_dataset,
|
|
7
|
+
async_search_datasets,
|
|
8
|
+
)
|
|
9
|
+
from spotlight.api.dataset.synchronous import (
|
|
10
|
+
get_dataset,
|
|
11
|
+
get_datasets,
|
|
12
|
+
create_dataset,
|
|
13
|
+
update_dataset,
|
|
14
|
+
delete_dataset,
|
|
15
|
+
search_datasets,
|
|
16
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from spotlight.api.dataset.model import DatasetRequest
|
|
2
|
+
from spotlight.api.dataset.model import SearchRequest
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _get_dataset_request_info(id: str) -> dict:
|
|
6
|
+
return {"endpoint": f"config/dataset/{id}"}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _get_datasets_request_info() -> dict:
|
|
10
|
+
return {"endpoint": f"config/dataset"}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _search_datasets_request_info(request: SearchRequest) -> dict:
|
|
14
|
+
return {
|
|
15
|
+
"endpoint": f"config/dataset/search",
|
|
16
|
+
"json": request.request_dict(),
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _create_dataset_request_info(request: DatasetRequest) -> dict:
|
|
21
|
+
return {"endpoint": f"config/dataset", "json": request.request_dict()}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _update_dataset_request_info(id: str, request: DatasetRequest) -> dict:
|
|
25
|
+
return {"endpoint": f"config/dataset/{id}", "json": request.request_dict()}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _delete_dataset_request_info(id: str) -> dict:
|
|
29
|
+
return {"endpoint": f"config/dataset/{id}"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from spotlight.api.dataset.abstract.asynchronous import (
|
|
2
|
+
async_get_abstract_dataset,
|
|
3
|
+
async_get_abstract_datasets,
|
|
4
|
+
async_search_abstract_datasets,
|
|
5
|
+
async_create_abstract_dataset,
|
|
6
|
+
async_update_abstract_dataset,
|
|
7
|
+
async_delete_abstract_dataset,
|
|
8
|
+
)
|
|
9
|
+
from spotlight.api.dataset.abstract.synchronous import (
|
|
10
|
+
get_abstract_dataset,
|
|
11
|
+
get_abstract_datasets,
|
|
12
|
+
search_abstract_datasets,
|
|
13
|
+
create_abstract_dataset,
|
|
14
|
+
update_abstract_dataset,
|
|
15
|
+
delete_abstract_dataset,
|
|
16
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from spotlight.api.dataset.abstract.model import AbstractDatasetRequest
|
|
2
|
+
from spotlight.api.dataset.model import SearchRequest
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _get_abstract_dataset_request_info(id: str) -> dict:
|
|
6
|
+
return {"endpoint": f"config/dataset/abstract/{id}"}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _get_abstract_datasets_request_info() -> dict:
|
|
10
|
+
return {"endpoint": f"config/dataset/abstract"}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _search_abstract_datasets_request_info(request: SearchRequest) -> dict:
|
|
14
|
+
return {
|
|
15
|
+
"endpoint": f"config/dataset/abstract/search",
|
|
16
|
+
"json": request.request_dict(),
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _create_abstract_dataset_request_info(request: AbstractDatasetRequest) -> dict:
|
|
21
|
+
return {"endpoint": f"config/dataset/abstract", "json": request.request_dict()}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _update_abstract_dataset_request_info(
|
|
25
|
+
id: str, request: AbstractDatasetRequest
|
|
26
|
+
) -> dict:
|
|
27
|
+
return {
|
|
28
|
+
"endpoint": f"config/dataset/abstract/{id}",
|
|
29
|
+
"json": request.request_dict(),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _delete_abstract_dataset_request_info(id: str) -> dict:
|
|
34
|
+
return {"endpoint": f"config/dataset/abstract/{id}"}
|