dealcloud-sdk 0.1.0__py3-none-any.whl

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.
Files changed (35) hide show
  1. dealcloud_sdk/__init__.py +6 -0
  2. dealcloud_sdk/base/__init__.py +0 -0
  3. dealcloud_sdk/base/dealcloud_base.py +174 -0
  4. dealcloud_sdk/constants/__init__.py +0 -0
  5. dealcloud_sdk/constants/auth.py +1 -0
  6. dealcloud_sdk/constants/data.py +4 -0
  7. dealcloud_sdk/constants/env_var_names.py +3 -0
  8. dealcloud_sdk/constants/field_types.py +13 -0
  9. dealcloud_sdk/constants/request.py +3 -0
  10. dealcloud_sdk/data/__init__.py +0 -0
  11. dealcloud_sdk/data/dealcloud_data.py +805 -0
  12. dealcloud_sdk/dealcloud.py +25 -0
  13. dealcloud_sdk/factories/__init__.py +0 -0
  14. dealcloud_sdk/factories/from_env.py +53 -0
  15. dealcloud_sdk/factories/from_json.py +27 -0
  16. dealcloud_sdk/factories/from_yaml.py +28 -0
  17. dealcloud_sdk/models/__init__.py +0 -0
  18. dealcloud_sdk/models/auth.py +10 -0
  19. dealcloud_sdk/models/data.py +8 -0
  20. dealcloud_sdk/models/factory_models.py +7 -0
  21. dealcloud_sdk/models/schema.py +116 -0
  22. dealcloud_sdk/schema/__init__.py +0 -0
  23. dealcloud_sdk/schema/dealcloud_schema.py +145 -0
  24. dealcloud_sdk/utils/__init__.py +0 -0
  25. dealcloud_sdk/utils/common_argument_parse.py +10 -0
  26. dealcloud_sdk/utils/data_utils.py +78 -0
  27. dealcloud_sdk/utils/get_key.py +15 -0
  28. dealcloud_sdk/utils/process_response_errors.py +19 -0
  29. dealcloud_sdk/utils/request_retry.py +168 -0
  30. dealcloud_sdk/utils/resolve_references.py +9 -0
  31. dealcloud_sdk/utils/validation.py +8 -0
  32. dealcloud_sdk-0.1.0.dist-info/LICENSE +114 -0
  33. dealcloud_sdk-0.1.0.dist-info/METADATA +920 -0
  34. dealcloud_sdk-0.1.0.dist-info/RECORD +35 -0
  35. dealcloud_sdk-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,6 @@
1
+ # ruff: noqa
2
+ from dealcloud_sdk.base.dealcloud_base import DealCloudBase
3
+
4
+ from dealcloud_sdk.data.dealcloud_data import DealCloudData
5
+ from dealcloud_sdk.dealcloud import DealCloud
6
+ from dealcloud_sdk.schema.dealcloud_schema import DealCloudSchema
File without changes
@@ -0,0 +1,174 @@
1
+ import logging
2
+ from time import time
3
+ from typing import Optional
4
+
5
+ from requests.exceptions import HTTPError
6
+
7
+ from dealcloud_sdk.constants.auth import AVAILABLE_SCOPES
8
+ from dealcloud_sdk.constants.env_var_names import (
9
+ SITE_URL_ENV_NAME,
10
+ CLIENT_ID_ENV_NAME,
11
+ CLIENT_SECRET_ENV_NAME,
12
+ )
13
+ from dealcloud_sdk.factories.from_json import dc_from_json_config
14
+ from dealcloud_sdk.factories.from_yaml import dc_from_yaml_config
15
+ from dealcloud_sdk.factories.from_env import dc_from_environment_variables
16
+ from dealcloud_sdk.models.auth import Tokens
17
+ from dealcloud_sdk.utils.get_key import get_key
18
+ from dealcloud_sdk.utils.request_retry import request_with_retry
19
+ from dealcloud_sdk.utils.validation import validate_scope
20
+
21
+
22
+ class DealCloudBase:
23
+ """DealCloudBase provides the base definition for authentication, etc. to provide DealCloud python wrappers"""
24
+
25
+ def __init__(
26
+ self,
27
+ site_url: str = None,
28
+ client_id: str = None,
29
+ client_secret: str = None,
30
+ scope: tuple[str] = AVAILABLE_SCOPES,
31
+ refresh_id_maps: bool = True,
32
+ ):
33
+ """
34
+ Init function for DealCloudBase
35
+
36
+ Args:
37
+ site_url(str): the target DealCloud site in the format "{client}.dealcloud.com" - i.e. no https:// or /
38
+ client_id(int): the client id from the user api key
39
+ client_secret(str): the client secret from the user api key
40
+ scope(tuple[str]): the authentication scopes, defaults to ("data", "user_management", "publish")
41
+ """
42
+ # log with provided logger
43
+ self._logger = logging.getLogger(__name__)
44
+
45
+ # api credentials
46
+ self._site = site_url
47
+ self._client_id = client_id
48
+ self._client_secret = client_secret
49
+
50
+ # encode auth string for authentication using request header
51
+ self._basic_auth = get_key(self._client_id, self._client_secret)
52
+
53
+ # validate provided scopes against available scopes
54
+ validate_scope(scope)
55
+ self._scope = " ".join(scope)
56
+
57
+ # id map refresh flag
58
+ self._refresh_id_maps = refresh_id_maps
59
+
60
+ # base urls
61
+ self._url_root = f"https://{self._site}/api/rest/v4"
62
+ self._url_root_v1 = f"https://{self._site}/api/rest/v1"
63
+
64
+ # schema endpoint
65
+ self._schema_url = f"{self._url_root}/schema"
66
+
67
+ # data endpoints
68
+ self._data_url = f"{self._url_root}/data"
69
+ self._entrydata_url = f"{self._data_url}/entrydata"
70
+ self._rows_url = f"{self._entrydata_url}/rows"
71
+ self._query_url = f"{self._rows_url}/query"
72
+ self._views_url = f"{self._data_url}/rows/view"
73
+
74
+ # setup token storage
75
+ self._access_token = None
76
+ self._expiry_time = None
77
+
78
+ # check valid credentials
79
+ self._logger.debug("validating credentials")
80
+ self._auth()
81
+ self._logger.debug("credentials validated")
82
+
83
+ # store schema
84
+ self._site_schema = self.get_schema()
85
+ # store users
86
+ self._user_map = dict({u.email.lower(): u.id for u in self.get_users()})
87
+
88
+ # id mapping store
89
+ self._id_map = {}
90
+
91
+ @classmethod
92
+ def from_env(
93
+ cls,
94
+ site_url_env_name: str = SITE_URL_ENV_NAME,
95
+ client_id_env_name: str = CLIENT_ID_ENV_NAME,
96
+ client_secret_env_name: str = CLIENT_SECRET_ENV_NAME,
97
+ ):
98
+ config = dc_from_environment_variables(
99
+ site_url_env_name,
100
+ client_id_env_name,
101
+ client_secret_env_name,
102
+ )
103
+
104
+ return cls(
105
+ config.site_url,
106
+ config.client_id,
107
+ config.client_secret,
108
+ )
109
+
110
+ @classmethod
111
+ def from_json(
112
+ cls, json_file_path: str, json_path_to_credentials: Optional[str] = None
113
+ ):
114
+ config = dc_from_json_config(json_file_path, json_path_to_credentials)
115
+ return cls(
116
+ config.site_url,
117
+ config.client_id,
118
+ config.client_secret,
119
+ )
120
+
121
+ @classmethod
122
+ def from_yaml(
123
+ cls, yaml_file_path: str, yaml_path_to_credentials: Optional[str] = None
124
+ ):
125
+ config = dc_from_yaml_config(yaml_file_path, yaml_path_to_credentials)
126
+ return cls(
127
+ config.site_url,
128
+ config.client_id,
129
+ config.client_secret,
130
+ )
131
+
132
+ def _auth(self) -> Tokens:
133
+ """
134
+ Authenticate with the DealCloud API
135
+
136
+ Returns:
137
+ tokens (Tokens): Pydantic model containing auth tokens
138
+ """
139
+ url = f"{self._url_root_v1}/oauth/token"
140
+ payload = f"grant_type=client_credentials&scope={self._scope}"
141
+
142
+ response = request_with_retry(
143
+ "GET",
144
+ url,
145
+ self._basic_auth,
146
+ data=payload,
147
+ status_force_list=[429],
148
+ auth_type="Basic",
149
+ max_retries=5,
150
+ content_type="application/x-www-form-urlencoded",
151
+ )
152
+
153
+ if response.status_code != 200:
154
+ self._logger.warning(response.text)
155
+ raise HTTPError("Could not authenticate! - check credentials")
156
+ tokens = Tokens(**response.json())
157
+
158
+ self._access_token = tokens.access_token
159
+ self._expiry_time = time() + (tokens.expires_in - 120)
160
+
161
+ return tokens
162
+
163
+ def _get_access_token(self) -> str:
164
+ if time() > self._expiry_time:
165
+ self._logger.warning("RE-AUTHENTICATING")
166
+ self._auth()
167
+
168
+ return self._access_token
169
+
170
+ def get_schema(self):
171
+ pass
172
+
173
+ def get_users(self):
174
+ pass
File without changes
@@ -0,0 +1 @@
1
+ AVAILABLE_SCOPES = ("data", "user_management", "publish")
@@ -0,0 +1,4 @@
1
+ CELL_PAGINATION_LIMIT = 9000
2
+ DELETION_PAGINATION_LIMIT = 10000
3
+ DATA_READ_WORKER_COUNT = 8
4
+ VIEW_READ_WORKER_COUNT = 2
@@ -0,0 +1,3 @@
1
+ SITE_URL_ENV_NAME = "DC_SDK_SITE_URL"
2
+ CLIENT_ID_ENV_NAME = "DC_SDK_CLIENT_ID"
3
+ CLIENT_SECRET_ENV_NAME = "DC_SDK_CLIENT_SECRET"
@@ -0,0 +1,13 @@
1
+ TEXT = 1
2
+ CHOICE = 2
3
+ NUMBER = 3
4
+ DATE = 4
5
+ REFERENCE = 5
6
+ BOOLEAN = 6
7
+ USER = 7
8
+ BINARY = 13
9
+ ENTRY_LIST_ID = 14
10
+ COUNTER = 15
11
+ IMAGE = 16
12
+ DATA_SOURCE = 17
13
+ CURRENCY = 18
@@ -0,0 +1,3 @@
1
+ MAX_RETRIES = 100000
2
+ STATUS_FORCE_LIST = [429]
3
+ BACKOFF_FACTOR = 10
File without changes