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.
- development_framework_cli-1.7.3.dist-info/METADATA +141 -0
- development_framework_cli-1.7.3.dist-info/RECORD +71 -0
- development_framework_cli-1.7.3.dist-info/WHEEL +4 -0
- development_framework_cli-1.7.3.dist-info/entry_points.txt +2 -0
- development_framework_cli-1.7.3.dist-info/licenses/LICENSE +21 -0
- dm_cli/__init__.py +1 -0
- dm_cli/cli.py +180 -0
- dm_cli/command_group/__init__.py +0 -0
- dm_cli/command_group/data_source.py +176 -0
- dm_cli/command_group/entities.py +116 -0
- dm_cli/dmss.py +104 -0
- dm_cli/dmss_api/__init__.py +27 -0
- dm_cli/dmss_api/api/__init__.py +3 -0
- dm_cli/dmss_api/api/access_control_api.py +349 -0
- dm_cli/dmss_api/api/attribute_api.py +175 -0
- dm_cli/dmss_api/api/blob_api.py +344 -0
- dm_cli/dmss_api/api/blueprint_api.py +326 -0
- dm_cli/dmss_api/api/datasource_api.py +448 -0
- dm_cli/dmss_api/api/default_api.py +4439 -0
- dm_cli/dmss_api/api/document_api.py +922 -0
- dm_cli/dmss_api/api/entity_api.py +464 -0
- dm_cli/dmss_api/api/export_api.py +313 -0
- dm_cli/dmss_api/api/file_api.py +197 -0
- dm_cli/dmss_api/api/health_check_api.py +160 -0
- dm_cli/dmss_api/api/lookup_table_api.py +323 -0
- dm_cli/dmss_api/api/meta_api.py +185 -0
- dm_cli/dmss_api/api/personal_access_token_api.py +433 -0
- dm_cli/dmss_api/api/reference_api.py +174 -0
- dm_cli/dmss_api/api/search_api.py +183 -0
- dm_cli/dmss_api/api/whoami_api.py +163 -0
- dm_cli/dmss_api/api_client.py +896 -0
- dm_cli/dmss_api/apis/__init__.py +32 -0
- dm_cli/dmss_api/configuration.py +482 -0
- dm_cli/dmss_api/exceptions.py +158 -0
- dm_cli/dmss_api/model/__init__.py +5 -0
- dm_cli/dmss_api/model/access_control_list.py +287 -0
- dm_cli/dmss_api/model/access_level.py +290 -0
- dm_cli/dmss_api/model/acl.py +287 -0
- dm_cli/dmss_api/model/data_source_information.py +282 -0
- dm_cli/dmss_api/model/data_source_request.py +281 -0
- dm_cli/dmss_api/model/dependency.py +294 -0
- dm_cli/dmss_api/model/entity.py +275 -0
- dm_cli/dmss_api/model/error_response.py +278 -0
- dm_cli/dmss_api/model/export_meta_response.py +277 -0
- dm_cli/dmss_api/model/get_blueprint_response.py +280 -0
- dm_cli/dmss_api/model/lookup.py +283 -0
- dm_cli/dmss_api/model/pat_data.py +299 -0
- dm_cli/dmss_api/model/recipe.py +311 -0
- dm_cli/dmss_api/model/recipe_attribute.py +304 -0
- dm_cli/dmss_api/model/reference.py +280 -0
- dm_cli/dmss_api/model/reference_entity.py +288 -0
- dm_cli/dmss_api/model/repository.py +317 -0
- dm_cli/dmss_api/model/repository_type.py +290 -0
- dm_cli/dmss_api/model/storage_attribute.py +295 -0
- dm_cli/dmss_api/model/storage_data_types.py +292 -0
- dm_cli/dmss_api/model/storage_recipe.py +293 -0
- dm_cli/dmss_api/model_utils.py +2057 -0
- dm_cli/dmss_api/models/__init__.py +29 -0
- dm_cli/dmss_api/rest.py +358 -0
- dm_cli/domain.py +166 -0
- dm_cli/enums.py +48 -0
- dm_cli/import_entity.py +128 -0
- dm_cli/import_package.py +173 -0
- dm_cli/package_tree_from_zip.py +120 -0
- dm_cli/state.py +12 -0
- dm_cli/utils/__init__.py +0 -0
- dm_cli/utils/file_structure.py +31 -0
- dm_cli/utils/reference.py +129 -0
- dm_cli/utils/resolve_local_ids.py +142 -0
- dm_cli/utils/utils.py +161 -0
- 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
|
dm_cli/dmss_api/rest.py
ADDED
|
@@ -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"
|