development-framework-cli 1.7.3__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 (71) hide show
  1. development_framework_cli-1.7.3.dist-info/METADATA +141 -0
  2. development_framework_cli-1.7.3.dist-info/RECORD +71 -0
  3. development_framework_cli-1.7.3.dist-info/WHEEL +4 -0
  4. development_framework_cli-1.7.3.dist-info/entry_points.txt +2 -0
  5. development_framework_cli-1.7.3.dist-info/licenses/LICENSE +21 -0
  6. dm_cli/__init__.py +1 -0
  7. dm_cli/cli.py +180 -0
  8. dm_cli/command_group/__init__.py +0 -0
  9. dm_cli/command_group/data_source.py +176 -0
  10. dm_cli/command_group/entities.py +116 -0
  11. dm_cli/dmss.py +104 -0
  12. dm_cli/dmss_api/__init__.py +27 -0
  13. dm_cli/dmss_api/api/__init__.py +3 -0
  14. dm_cli/dmss_api/api/access_control_api.py +349 -0
  15. dm_cli/dmss_api/api/attribute_api.py +175 -0
  16. dm_cli/dmss_api/api/blob_api.py +344 -0
  17. dm_cli/dmss_api/api/blueprint_api.py +326 -0
  18. dm_cli/dmss_api/api/datasource_api.py +448 -0
  19. dm_cli/dmss_api/api/default_api.py +4439 -0
  20. dm_cli/dmss_api/api/document_api.py +922 -0
  21. dm_cli/dmss_api/api/entity_api.py +464 -0
  22. dm_cli/dmss_api/api/export_api.py +313 -0
  23. dm_cli/dmss_api/api/file_api.py +197 -0
  24. dm_cli/dmss_api/api/health_check_api.py +160 -0
  25. dm_cli/dmss_api/api/lookup_table_api.py +323 -0
  26. dm_cli/dmss_api/api/meta_api.py +185 -0
  27. dm_cli/dmss_api/api/personal_access_token_api.py +433 -0
  28. dm_cli/dmss_api/api/reference_api.py +174 -0
  29. dm_cli/dmss_api/api/search_api.py +183 -0
  30. dm_cli/dmss_api/api/whoami_api.py +163 -0
  31. dm_cli/dmss_api/api_client.py +896 -0
  32. dm_cli/dmss_api/apis/__init__.py +32 -0
  33. dm_cli/dmss_api/configuration.py +482 -0
  34. dm_cli/dmss_api/exceptions.py +158 -0
  35. dm_cli/dmss_api/model/__init__.py +5 -0
  36. dm_cli/dmss_api/model/access_control_list.py +287 -0
  37. dm_cli/dmss_api/model/access_level.py +290 -0
  38. dm_cli/dmss_api/model/acl.py +287 -0
  39. dm_cli/dmss_api/model/data_source_information.py +282 -0
  40. dm_cli/dmss_api/model/data_source_request.py +281 -0
  41. dm_cli/dmss_api/model/dependency.py +294 -0
  42. dm_cli/dmss_api/model/entity.py +275 -0
  43. dm_cli/dmss_api/model/error_response.py +278 -0
  44. dm_cli/dmss_api/model/export_meta_response.py +277 -0
  45. dm_cli/dmss_api/model/get_blueprint_response.py +280 -0
  46. dm_cli/dmss_api/model/lookup.py +283 -0
  47. dm_cli/dmss_api/model/pat_data.py +299 -0
  48. dm_cli/dmss_api/model/recipe.py +311 -0
  49. dm_cli/dmss_api/model/recipe_attribute.py +304 -0
  50. dm_cli/dmss_api/model/reference.py +280 -0
  51. dm_cli/dmss_api/model/reference_entity.py +288 -0
  52. dm_cli/dmss_api/model/repository.py +317 -0
  53. dm_cli/dmss_api/model/repository_type.py +290 -0
  54. dm_cli/dmss_api/model/storage_attribute.py +295 -0
  55. dm_cli/dmss_api/model/storage_data_types.py +292 -0
  56. dm_cli/dmss_api/model/storage_recipe.py +293 -0
  57. dm_cli/dmss_api/model_utils.py +2057 -0
  58. dm_cli/dmss_api/models/__init__.py +29 -0
  59. dm_cli/dmss_api/rest.py +358 -0
  60. dm_cli/domain.py +166 -0
  61. dm_cli/enums.py +48 -0
  62. dm_cli/import_entity.py +128 -0
  63. dm_cli/import_package.py +173 -0
  64. dm_cli/package_tree_from_zip.py +120 -0
  65. dm_cli/state.py +12 -0
  66. dm_cli/utils/__init__.py +0 -0
  67. dm_cli/utils/file_structure.py +31 -0
  68. dm_cli/utils/reference.py +129 -0
  69. dm_cli/utils/resolve_local_ids.py +142 -0
  70. dm_cli/utils/utils.py +161 -0
  71. dm_cli/utils/zip.py +70 -0
@@ -0,0 +1,29 @@
1
+ # flake8: noqa
2
+
3
+ # import all models into this package
4
+ # if you have many models here with many references from one model to another this may
5
+ # raise a RecursionError
6
+ # to avoid this, import only the models that you directly need like:
7
+ # from from dm_cli.dmss_api.model.pet import Pet
8
+ # or import this package, but before doing it, use:
9
+ # import sys
10
+ # sys.setrecursionlimit(n)
11
+
12
+ from dm_cli.dmss_api.model.access_control_list import AccessControlList
13
+ from dm_cli.dmss_api.model.access_level import AccessLevel
14
+ from dm_cli.dmss_api.model.data_source_information import DataSourceInformation
15
+ from dm_cli.dmss_api.model.data_source_request import DataSourceRequest
16
+ from dm_cli.dmss_api.model.dependency import Dependency
17
+ from dm_cli.dmss_api.model.entity import Entity
18
+ from dm_cli.dmss_api.model.error_response import ErrorResponse
19
+ from dm_cli.dmss_api.model.export_meta_response import ExportMetaResponse
20
+ from dm_cli.dmss_api.model.get_blueprint_response import GetBlueprintResponse
21
+ from dm_cli.dmss_api.model.lookup import Lookup
22
+ from dm_cli.dmss_api.model.pat_data import PATData
23
+ from dm_cli.dmss_api.model.recipe import Recipe
24
+ from dm_cli.dmss_api.model.recipe_attribute import RecipeAttribute
25
+ from dm_cli.dmss_api.model.repository import Repository
26
+ from dm_cli.dmss_api.model.repository_type import RepositoryType
27
+ from dm_cli.dmss_api.model.storage_attribute import StorageAttribute
28
+ from dm_cli.dmss_api.model.storage_data_types import StorageDataTypes
29
+ from dm_cli.dmss_api.model.storage_recipe import StorageRecipe
@@ -0,0 +1,358 @@
1
+ """
2
+ Data Modelling Storage Service
3
+
4
+ API for basic data modelling interaction # noqa: E501
5
+
6
+ The version of the OpenAPI document: 1.3.0
7
+ Generated by: https://openapi-generator.tech
8
+ """
9
+
10
+
11
+ import io
12
+ import ipaddress
13
+ import json
14
+ import logging
15
+ import re
16
+ import ssl
17
+ from urllib.parse import urlencode, urlparse
18
+ from urllib.request import proxy_bypass_environment
19
+
20
+ import urllib3
21
+
22
+ from dm_cli.dmss_api.exceptions import (
23
+ ApiException,
24
+ ApiValueError,
25
+ ForbiddenException,
26
+ NotFoundException,
27
+ ServiceException,
28
+ UnauthorizedException,
29
+ )
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ class RESTResponse(io.IOBase):
35
+
36
+ def __init__(self, resp):
37
+ self.urllib3_response = resp
38
+ self.status = resp.status
39
+ self.reason = resp.reason
40
+ self.data = resp.data
41
+
42
+ def getheaders(self):
43
+ """Returns a dictionary of the response headers."""
44
+ return self.urllib3_response.getheaders()
45
+
46
+ def getheader(self, name, default=None):
47
+ """Returns a given response header."""
48
+ return self.urllib3_response.getheader(name, default)
49
+
50
+
51
+ class RESTClientObject(object):
52
+
53
+ def __init__(self, configuration, pools_size=4, maxsize=None):
54
+ # urllib3.PoolManager will pass all kw parameters to connectionpool
55
+ # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501
56
+ # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501
57
+ # maxsize is the number of requests to host that are allowed in parallel # noqa: E501
58
+ # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501
59
+
60
+ # cert_reqs
61
+ if configuration.verify_ssl:
62
+ cert_reqs = ssl.CERT_REQUIRED
63
+ else:
64
+ cert_reqs = ssl.CERT_NONE
65
+
66
+ addition_pool_args = {}
67
+ if configuration.assert_hostname is not None:
68
+ addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501
69
+
70
+ if configuration.retries is not None:
71
+ addition_pool_args['retries'] = configuration.retries
72
+
73
+ if configuration.socket_options is not None:
74
+ addition_pool_args['socket_options'] = configuration.socket_options
75
+
76
+ if maxsize is None:
77
+ if configuration.connection_pool_maxsize is not None:
78
+ maxsize = configuration.connection_pool_maxsize
79
+ else:
80
+ maxsize = 4
81
+
82
+ # https pool manager
83
+ if configuration.proxy and not should_bypass_proxies(
84
+ configuration.host, no_proxy=configuration.no_proxy or ''):
85
+ self.pool_manager = urllib3.ProxyManager(
86
+ num_pools=pools_size,
87
+ maxsize=maxsize,
88
+ cert_reqs=cert_reqs,
89
+ ca_certs=configuration.ssl_ca_cert,
90
+ cert_file=configuration.cert_file,
91
+ key_file=configuration.key_file,
92
+ proxy_url=configuration.proxy,
93
+ proxy_headers=configuration.proxy_headers,
94
+ **addition_pool_args
95
+ )
96
+ else:
97
+ self.pool_manager = urllib3.PoolManager(
98
+ num_pools=pools_size,
99
+ maxsize=maxsize,
100
+ cert_reqs=cert_reqs,
101
+ ca_certs=configuration.ssl_ca_cert,
102
+ cert_file=configuration.cert_file,
103
+ key_file=configuration.key_file,
104
+ **addition_pool_args
105
+ )
106
+
107
+ def request(self, method, url, query_params=None, headers=None,
108
+ body=None, post_params=None, _preload_content=True,
109
+ _request_timeout=None):
110
+ """Perform requests.
111
+
112
+ :param method: http request method
113
+ :param url: http request url
114
+ :param query_params: query parameters in the url
115
+ :param headers: http request headers
116
+ :param body: request json body, for `application/json`
117
+ :param post_params: request post parameters,
118
+ `application/x-www-form-urlencoded`
119
+ and `multipart/form-data`
120
+ :param _preload_content: if False, the urllib3.HTTPResponse object will
121
+ be returned without reading/decoding response
122
+ data. Default is True.
123
+ :param _request_timeout: timeout setting for this request. If one
124
+ number provided, it will be total request
125
+ timeout. It can also be a pair (tuple) of
126
+ (connection, read) timeouts.
127
+ """
128
+ method = method.upper()
129
+ assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
130
+ 'PATCH', 'OPTIONS']
131
+
132
+ if post_params and body:
133
+ raise ApiValueError(
134
+ "body parameter cannot be used with post_params parameter."
135
+ )
136
+
137
+ post_params = post_params or {}
138
+ headers = headers or {}
139
+
140
+ timeout = None
141
+ if _request_timeout:
142
+ if isinstance(_request_timeout, (int, float)): # noqa: E501,F821
143
+ timeout = urllib3.Timeout(total=_request_timeout)
144
+ elif (isinstance(_request_timeout, tuple) and
145
+ len(_request_timeout) == 2):
146
+ timeout = urllib3.Timeout(
147
+ connect=_request_timeout[0], read=_request_timeout[1])
148
+
149
+ try:
150
+ # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
151
+ if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
152
+ # Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
153
+ if (method != 'DELETE') and ('Content-Type' not in headers):
154
+ headers['Content-Type'] = 'application/json'
155
+ if query_params:
156
+ url += '?' + urlencode(query_params)
157
+ if ('Content-Type' not in headers) or (re.search('json',
158
+ headers['Content-Type'], re.IGNORECASE)):
159
+ request_body = None
160
+ if body is not None:
161
+ request_body = json.dumps(body)
162
+ r = self.pool_manager.request(
163
+ method, url,
164
+ body=request_body,
165
+ preload_content=_preload_content,
166
+ timeout=timeout,
167
+ headers=headers)
168
+ elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501
169
+ r = self.pool_manager.request(
170
+ method, url,
171
+ fields=post_params,
172
+ encode_multipart=False,
173
+ preload_content=_preload_content,
174
+ timeout=timeout,
175
+ headers=headers)
176
+ elif headers['Content-Type'] == 'multipart/form-data':
177
+ # must del headers['Content-Type'], or the correct
178
+ # Content-Type which generated by urllib3 will be
179
+ # overwritten.
180
+ del headers['Content-Type']
181
+ r = self.pool_manager.request(
182
+ method, url,
183
+ fields=post_params,
184
+ encode_multipart=True,
185
+ preload_content=_preload_content,
186
+ timeout=timeout,
187
+ headers=headers)
188
+ # Pass a `string` parameter directly in the body to support
189
+ # other content types than Json when `body` argument is
190
+ # provided in serialized form
191
+ elif isinstance(body, str) or isinstance(body, bytes):
192
+ request_body = body
193
+ r = self.pool_manager.request(
194
+ method, url,
195
+ body=request_body,
196
+ preload_content=_preload_content,
197
+ timeout=timeout,
198
+ headers=headers)
199
+ else:
200
+ # Cannot generate the request from given parameters
201
+ msg = """Cannot prepare a request message for provided
202
+ arguments. Please check that your arguments match
203
+ declared content type."""
204
+ raise ApiException(status=0, reason=msg)
205
+ # For `GET`, `HEAD`
206
+ else:
207
+ r = self.pool_manager.request(method, url,
208
+ fields=query_params,
209
+ preload_content=_preload_content,
210
+ timeout=timeout,
211
+ headers=headers)
212
+ except urllib3.exceptions.SSLError as e:
213
+ msg = "{0}\n{1}".format(type(e).__name__, str(e))
214
+ raise ApiException(status=0, reason=msg)
215
+
216
+ if _preload_content:
217
+ r = RESTResponse(r)
218
+
219
+ # log response body
220
+ logger.debug("response body: %s", r.data)
221
+
222
+ if not 200 <= r.status <= 299:
223
+ if r.status == 401:
224
+ raise UnauthorizedException(http_resp=r)
225
+
226
+ if r.status == 403:
227
+ raise ForbiddenException(http_resp=r)
228
+
229
+ if r.status == 404:
230
+ raise NotFoundException(http_resp=r)
231
+
232
+ if 500 <= r.status <= 599:
233
+ raise ServiceException(http_resp=r)
234
+
235
+ raise ApiException(http_resp=r)
236
+
237
+ return r
238
+
239
+ def GET(self, url, headers=None, query_params=None, _preload_content=True,
240
+ _request_timeout=None):
241
+ return self.request("GET", url,
242
+ headers=headers,
243
+ _preload_content=_preload_content,
244
+ _request_timeout=_request_timeout,
245
+ query_params=query_params)
246
+
247
+ def HEAD(self, url, headers=None, query_params=None, _preload_content=True,
248
+ _request_timeout=None):
249
+ return self.request("HEAD", url,
250
+ headers=headers,
251
+ _preload_content=_preload_content,
252
+ _request_timeout=_request_timeout,
253
+ query_params=query_params)
254
+
255
+ def OPTIONS(self, url, headers=None, query_params=None, post_params=None,
256
+ body=None, _preload_content=True, _request_timeout=None):
257
+ return self.request("OPTIONS", url,
258
+ headers=headers,
259
+ query_params=query_params,
260
+ post_params=post_params,
261
+ _preload_content=_preload_content,
262
+ _request_timeout=_request_timeout,
263
+ body=body)
264
+
265
+ def DELETE(self, url, headers=None, query_params=None, body=None,
266
+ _preload_content=True, _request_timeout=None):
267
+ return self.request("DELETE", url,
268
+ headers=headers,
269
+ query_params=query_params,
270
+ _preload_content=_preload_content,
271
+ _request_timeout=_request_timeout,
272
+ body=body)
273
+
274
+ def POST(self, url, headers=None, query_params=None, post_params=None,
275
+ body=None, _preload_content=True, _request_timeout=None):
276
+ return self.request("POST", url,
277
+ headers=headers,
278
+ query_params=query_params,
279
+ post_params=post_params,
280
+ _preload_content=_preload_content,
281
+ _request_timeout=_request_timeout,
282
+ body=body)
283
+
284
+ def PUT(self, url, headers=None, query_params=None, post_params=None,
285
+ body=None, _preload_content=True, _request_timeout=None):
286
+ return self.request("PUT", url,
287
+ headers=headers,
288
+ query_params=query_params,
289
+ post_params=post_params,
290
+ _preload_content=_preload_content,
291
+ _request_timeout=_request_timeout,
292
+ body=body)
293
+
294
+ def PATCH(self, url, headers=None, query_params=None, post_params=None,
295
+ body=None, _preload_content=True, _request_timeout=None):
296
+ return self.request("PATCH", url,
297
+ headers=headers,
298
+ query_params=query_params,
299
+ post_params=post_params,
300
+ _preload_content=_preload_content,
301
+ _request_timeout=_request_timeout,
302
+ body=body)
303
+
304
+ # end of class RESTClientObject
305
+
306
+
307
+ def is_ipv4(target):
308
+ """ Test if IPv4 address or not
309
+ """
310
+ try:
311
+ chk = ipaddress.IPv4Address(target)
312
+ return True
313
+ except ipaddress.AddressValueError:
314
+ return False
315
+
316
+
317
+ def in_ipv4net(target, net):
318
+ """ Test if target belongs to given IPv4 network
319
+ """
320
+ try:
321
+ nw = ipaddress.IPv4Network(net)
322
+ ip = ipaddress.IPv4Address(target)
323
+ if ip in nw:
324
+ return True
325
+ return False
326
+ except ipaddress.AddressValueError:
327
+ return False
328
+ except ipaddress.NetmaskValueError:
329
+ return False
330
+
331
+
332
+ def should_bypass_proxies(url, no_proxy=None):
333
+ """ Yet another requests.should_bypass_proxies
334
+ Test if proxies should not be used for a particular url.
335
+ """
336
+
337
+ parsed = urlparse(url)
338
+
339
+ # special cases
340
+ if parsed.hostname in [None, '']:
341
+ return True
342
+
343
+ # special cases
344
+ if no_proxy in [None, '']:
345
+ return False
346
+ if no_proxy == '*':
347
+ return True
348
+
349
+ no_proxy = no_proxy.lower().replace(' ', '');
350
+ entries = (
351
+ host for host in no_proxy.split(',') if host
352
+ )
353
+
354
+ if is_ipv4(parsed.hostname):
355
+ for item in entries:
356
+ if in_ipv4net(parsed.hostname, item):
357
+ return True
358
+ return proxy_bypass_environment(parsed.hostname, {'no': no_proxy})
dm_cli/domain.py ADDED
@@ -0,0 +1,166 @@
1
+ import io
2
+ from dataclasses import dataclass
3
+ from pathlib import Path
4
+ from typing import Callable, List, Literal, NewType, Union
5
+ from uuid import UUID, uuid4
6
+
7
+ from .enums import SIMOS, ReferenceTypes
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class File:
12
+ """Class for a file"""
13
+
14
+ content: io.BytesIO
15
+ path: Path
16
+ name: str = ""
17
+ uid: str = ""
18
+
19
+ def __getitem__(self, item):
20
+ return self.__getattribute__(item)
21
+
22
+
23
+ class Package:
24
+ def __init__(
25
+ self,
26
+ name: str,
27
+ description: str = "",
28
+ uid: UUID = None,
29
+ is_root: bool = False,
30
+ meta: dict = None,
31
+ parent: "Package" = None,
32
+ ):
33
+ self.name = name
34
+ self.description = description
35
+ self.uid = uid if uid else uuid4()
36
+ self.is_root = is_root
37
+ self.content: List[Union[Package, dict, File]] = []
38
+ self.meta: Union[dict, None] = meta if meta else {}
39
+ self.parent = parent if parent else None
40
+
41
+ def __str__(self):
42
+ return f"Name: {self.name}, Content: {len(self.content)}"
43
+
44
+ def __getitem__(self, item):
45
+ return self.__getattribute__(item)
46
+
47
+ def search(self, filename: str) -> Union["Package", dict]:
48
+ return next((child for child in self.content if child["name"] == filename), None)
49
+
50
+ def to_dict(self):
51
+ return {
52
+ "_id": str(self.uid),
53
+ "type": self.type,
54
+ "name": self.name,
55
+ "description": self.description,
56
+ "isRoot": self.is_root,
57
+ "_meta_": self.meta,
58
+ "content": self._content_to_ref_dict(),
59
+ }
60
+
61
+ def path(self):
62
+ if not self.parent:
63
+ return self.name
64
+ return f"{self.parent.path()}/{self.name}"
65
+
66
+ def traverse_documents(self, func: Callable, update: bool = False, **kwargs) -> None:
67
+ """
68
+ Traverses the Package structure, calling the passed function on every non-Package node.
69
+
70
+ @param func: A function that takes the document node as it's first parameter
71
+ @param update: Whether to set the tree node to be the return value from the passed function
72
+ @param kwargs: Keyword arguments to be passed to 'func'
73
+ """
74
+ for i, child in enumerate(self.content):
75
+ if isinstance(child, Package):
76
+ child.traverse_documents(func, update=update, **kwargs)
77
+ else:
78
+ child_file_path = self.path() # The file's path in the package is needed to resolve dotted references
79
+ if update:
80
+ self.content[i] = func(child, file_path=child_file_path, **kwargs)
81
+ else:
82
+ func(child, file_path=child_file_path, **kwargs)
83
+
84
+ def traverse_package(self, func: Callable, update: bool = False, **kwargs) -> None:
85
+ """
86
+ Traverses the Package structure, calling the passed function on every Package node.
87
+
88
+ @param func: A function that takes the Package node as it's first parameter
89
+ @param update: Whether to set the tree node to be the return value from the passed function
90
+ @param kwargs: Keyword arguments to be passed to 'func'
91
+ """
92
+ for i, child in enumerate(self.content):
93
+ if isinstance(child, Package):
94
+ if update:
95
+ self.content[i] = func(child, **kwargs)
96
+ else:
97
+ func(child, **kwargs)
98
+ child.traverse_package(func, update, **kwargs)
99
+
100
+ @property
101
+ def type(self):
102
+ return SIMOS.PACKAGE.value
103
+
104
+ def _content_to_ref_dict(self):
105
+ result = []
106
+ for child in self.content:
107
+ if isinstance(child, File):
108
+ result.append(
109
+ {
110
+ "address": f"${str(child.uid)}",
111
+ "type": SIMOS.REFERENCE.value,
112
+ "referenceType": ReferenceTypes.STORAGE.value,
113
+ }
114
+ )
115
+ elif isinstance(child, Package):
116
+ result.append(
117
+ {
118
+ "address": f"${str(child.uid)}",
119
+ "type": SIMOS.REFERENCE.value,
120
+ "referenceType": ReferenceTypes.STORAGE.value,
121
+ }
122
+ )
123
+ else: # Assume the child is a dict
124
+ if "name" in child:
125
+ result.append(
126
+ {
127
+ "address": f"${child['_id']}",
128
+ "type": SIMOS.REFERENCE.value,
129
+ "referenceType": ReferenceTypes.STORAGE.value,
130
+ }
131
+ )
132
+
133
+ else:
134
+ result.append(
135
+ {
136
+ "address": f"${child['_id']}",
137
+ "type": SIMOS.REFERENCE.value,
138
+ "referenceType": ReferenceTypes.STORAGE.value,
139
+ }
140
+ )
141
+ return result
142
+
143
+
144
+ TDependencyProtocol = NewType("TDependencyProtocol", Literal["dmss", "http"])
145
+
146
+
147
+ @dataclass(frozen=True)
148
+ class Dependency:
149
+ """Class for any dependencies (external types) a entity references"""
150
+
151
+ alias: str
152
+ # Different ways we support to fetch dependencies.
153
+ # dmss: Internally within the DMSS instance
154
+ # http: A public HTTP GET call
155
+ protocol: TDependencyProtocol
156
+ address: str
157
+ version: str = ""
158
+ type: str = ""
159
+
160
+ def __eq__(self, other):
161
+ return (
162
+ self.alias == other.alias
163
+ and self.protocol == other.protocol
164
+ and self.address == other.address
165
+ and self.version == other.version
166
+ )
dm_cli/enums.py ADDED
@@ -0,0 +1,48 @@
1
+ from enum import Enum
2
+
3
+
4
+ class StorageDataTypes(Enum):
5
+ DEFAULT = "default"
6
+ LARGE = "large"
7
+ VERY_LARGE = "veryLarge"
8
+ VIDEO = "video"
9
+ BLOB = "blob"
10
+
11
+
12
+ class BuiltinDataTypes(Enum):
13
+ STR = "string"
14
+ NUM = "number"
15
+ INT = "integer"
16
+ BOOL = "boolean"
17
+ OBJECT = "object" # Any complex type (i.e. any blueprint type)
18
+ BINARY = "binary"
19
+ ANY = "any"
20
+
21
+ def to_py_type(self):
22
+ if self is BuiltinDataTypes.BOOL:
23
+ return bool
24
+ elif self is BuiltinDataTypes.INT:
25
+ return int
26
+ elif self is BuiltinDataTypes.NUM:
27
+ return float
28
+ elif self is BuiltinDataTypes.STR:
29
+ return str
30
+ elif self is BuiltinDataTypes.OBJECT:
31
+ return dict
32
+
33
+
34
+ class SIMOS(Enum):
35
+ BLOB = "dmss://system/SIMOS/Blob"
36
+ PACKAGE = "dmss://system/SIMOS/Package"
37
+ REFERENCE = "dmss://system/SIMOS/Reference"
38
+ FILE = "dmss://system/SIMOS/File"
39
+ DEPENDENCY = "dmss://system/SIMOS/Dependency"
40
+ ATTRIBUTE = "dmss://system/SIMOS/BlueprintAttribute"
41
+ BLUEPRINT = "dmss://system/SIMOS/Blueprint"
42
+ RECIPE_LINK = "dmss://system/SIMOS/RecipeLink"
43
+
44
+
45
+ class ReferenceTypes(Enum):
46
+ LINK = "link"
47
+ POINTER = "pointer"
48
+ STORAGE = "storage"