accsyn-python-api 2.2.1__tar.gz → 3.0.1__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.
Files changed (42) hide show
  1. accsyn-python-api-3.0.1/.gitignore +9 -0
  2. accsyn-python-api-3.0.1/PKG-INFO +56 -0
  3. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/README.md +7 -0
  4. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/release_notes.rst +14 -0
  5. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/setup.py +1 -1
  6. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_api/session.py +182 -277
  7. accsyn-python-api-3.0.1/source/accsyn_python_api.egg-info/PKG-INFO +56 -0
  8. accsyn-python-api-2.2.1/.gitignore +0 -1
  9. accsyn-python-api-2.2.1/PKG-INFO +0 -50
  10. accsyn-python-api-2.2.1/source/accsyn_python_api.egg-info/PKG-INFO +0 -50
  11. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/.github/workflows/github-actions-black.yml +0 -0
  12. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/.pre-commit-config.yaml +0 -0
  13. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/.readthedocs.yaml +0 -0
  14. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/_static/accsyn.css +0 -0
  15. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/api_reference/index.rst +0 -0
  16. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/api_reference/session.rst +0 -0
  17. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/clients.rst +0 -0
  18. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/conf.py +0 -0
  19. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/datatypes.rst +0 -0
  20. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/file.rst +0 -0
  21. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/glossary.rst +0 -0
  22. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/index.rst +0 -0
  23. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/installing.rst +0 -0
  24. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/introduction.rst +0 -0
  25. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/jobs.rst +0 -0
  26. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/misc.rst +0 -0
  27. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/publish.rst +0 -0
  28. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/queues.rst +0 -0
  29. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/render.rst +0 -0
  30. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/requirements.txt +0 -0
  31. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/shares.rst +0 -0
  32. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/users.rst +0 -0
  33. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/doc/using.rst +0 -0
  34. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/pyproject.toml +0 -0
  35. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/readthedocs.yaml +0 -0
  36. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/setup.cfg +0 -0
  37. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_api/__init__.py +0 -0
  38. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_api/_version.py +0 -0
  39. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_python_api.egg-info/SOURCES.txt +0 -0
  40. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_python_api.egg-info/dependency_links.txt +0 -0
  41. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_python_api.egg-info/requires.txt +0 -0
  42. {accsyn-python-api-2.2.1 → accsyn-python-api-3.0.1}/source/accsyn_python_api.egg-info/top_level.txt +0 -0
@@ -0,0 +1,9 @@
1
+ *.pyc
2
+ .eggs
3
+ .idea
4
+ dist
5
+ build
6
+ deploy.sh
7
+ doc/_build
8
+ accsyn_python_api.egg-info
9
+ .DS_Store
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: accsyn-python-api
3
+ Version: 3.0.1
4
+ Summary: A Python API for accsyn programmable fast and secure data delivery software
5
+ Home-page: https://github.com/accsyn/accsyn-python-api.git
6
+ Author: Henrik Norin
7
+ Author-email: henrik.norin@accsyn.com
8
+ License: Apache License (2.0)
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=2.7.9, <4.0
13
+ Description-Content-Type: text/markdown
14
+
15
+ # accsyn-python-api
16
+ Official accsyn fast film delivery Python API
17
+
18
+ Complete Python API reference can be found [here](https://support.accsyn.com/python-api).
19
+
20
+
21
+ Changelog:
22
+ ----------
23
+
24
+ See doc/release_notes.rst
25
+
26
+
27
+ Documentation:
28
+ --------------
29
+
30
+ [https://accsyn-python-api.readthedocs.io/en/latest](https://accsyn-python-api.readthedocs.io/en/latest)
31
+
32
+
33
+ Building:
34
+ ---------
35
+
36
+ To build the documentation locally, run:
37
+
38
+ ```
39
+ cd doc
40
+ pip install -r requirements.txt
41
+ python -m sphinx -T -E -b html -d _build/doctrees -D language=en . ../dist/doc
42
+ ```
43
+
44
+ Deploying:
45
+ ----------
46
+
47
+ ```
48
+ python setup.py sdist bdist_wheel
49
+ twine upload --verbose --username accsyn dist/*
50
+ ```
51
+
52
+ Henrik Norin, HDR AB, 2023
53
+ accsyn(r) - secure data delivery and workflow sync
54
+ https://accsyn.com
55
+ https://support.accsyn.com
56
+
@@ -27,6 +27,13 @@ To build the documentation locally, run:
27
27
  python -m sphinx -T -E -b html -d _build/doctrees -D language=en . ../dist/doc
28
28
  ```
29
29
 
30
+ Deploying:
31
+ ----------
32
+
33
+ ```
34
+ python setup.py sdist bdist_wheel
35
+ twine upload --verbose --username accsyn dist/*
36
+ ```
30
37
 
31
38
  Henrik Norin, HDR AB, 2023
32
39
  accsyn(r) - secure data delivery and workflow sync
@@ -13,6 +13,20 @@ Release Notes
13
13
 
14
14
  `https://support.accsyn.com <https://support.accsyn.com>`_.
15
15
 
16
+ .. release:: 3.0.1
17
+ :date: 2024-11-18
18
+
19
+ .. change:: fix
20
+
21
+ * Bug fixes.
22
+
23
+ .. release:: 3.0.0
24
+ :date: 2024-11-17
25
+
26
+ .. change:: feat
27
+
28
+ * Compliance with new accsyn v3 workspaces.
29
+ * Removed pwd and session key authentication, accsyn v3 only support API key basic auth.
16
30
 
17
31
  .. release:: 2.2.0
18
32
  :date: 2023-11-09
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name='accsyn-python-api',
8
- version='2.2.1',
8
+ version='3.0.1',
9
9
  package_dir={'': 'source'},
10
10
  packages=['accsyn_api'],
11
11
  setup_requires=[
@@ -43,15 +43,16 @@ logging.basicConfig(
43
43
  datefmt="%Y-%m-%d %H:%M:%S",
44
44
  )
45
45
 
46
- ACCSYN_CLOUD_DOMAIN = "accsyn.com"
47
- ACCSYN_CLOUD_REGISTRY_HOSTNAME = "registry.%s" % ACCSYN_CLOUD_DOMAIN
46
+ ACCSYN_BACKEND_DOMAIN = "accsyn.com"
47
+ ACCSYN_BACKEND_MASTER_HOSTNAME = "master.{}".format(ACCSYN_BACKEND_DOMAIN)
48
48
  ACCSYN_PORT = 443
49
49
  DEFAULT_EVENT_PAYLOAD_COMPRESS_SIZE_TRESHOLD = 100 * 1024 # Compress event data payloads above 100k
50
50
 
51
- CLEARANCE_CLOUDADMIN = "cloudadmin"
51
+ CLEARANCE_SUPPORT = "support"
52
52
  CLEARANCE_ADMIN = "admin"
53
53
  CLEARANCE_EMPLOYEE = "employee"
54
- CLEARANCE_CLIENT = "client"
54
+ CLEARANCE_STANDARD = "standard"
55
+ CLEARANCE_CLIENT = CLEARANCE_STANDARD # BWCOMP
55
56
  CLEARANCE_NONE = "none"
56
57
 
57
58
 
@@ -65,7 +66,7 @@ class JSONEncoder(json.JSONEncoder):
65
66
 
66
67
 
67
68
  class JSONDecoder(json.JSONDecoder):
68
- """JSON deserialise."""
69
+ """JSON deserialize."""
69
70
 
70
71
  def decode(self, json_string):
71
72
  json_data = json.loads(json_string)
@@ -116,6 +117,8 @@ class Session(object):
116
117
  DEFAULT_CONNECT_TIMEOUT = 10 # Wait 10 seconds for connection
117
118
  DEFAULT_TIMEOUT = 2 * 60 # Wait 2 minutes for response
118
119
 
120
+ _p_logfile = None
121
+
119
122
  @property
120
123
  def username(self):
121
124
  return self._username
@@ -133,8 +136,6 @@ class Session(object):
133
136
  domain=None,
134
137
  username=None,
135
138
  api_key=None,
136
- pwd=None,
137
- session_key=None,
138
139
  hostname=None,
139
140
  port=None,
140
141
  proxy=None,
@@ -151,8 +152,6 @@ class Session(object):
151
152
  :param domain: The accsyn domain (or read from ACCSYN_DOMAIN environment variable)
152
153
  :param username: The accsyn username (or read from ACCSYN_API_USER environment variable)
153
154
  :param api_key: The secret API key for authentication (or read from ACCSYN_API_KEY environment variable)
154
- :param pwd: (No API key supplied) The secret password for authentication
155
- :param session_key: (No API key or password supplied) The secret session key to use for authentication.
156
155
  :param hostname: Override hostname/IP to connect to.
157
156
  :param port: Override default port 443.
158
157
  :param proxy: The proxy settings (or read from ACCSYN_PROXY environment variable).
@@ -165,81 +164,70 @@ class Session(object):
165
164
  """
166
165
  # Generate a session ID
167
166
  self.__version__ = __version__
168
- self._pwd = None
169
167
  self._session_id = str(uuid.uuid4())
170
- self._session_key = None
171
- self._session_key_provided = None
168
+ self._uid = None
169
+ self._api_key = None
172
170
  self._be_verbose = verbose
173
171
  self._pretty_json = pretty_json
174
172
  self._proxy = proxy
175
173
  self._dev = dev is True or os.environ.get('ACCSYN_DEV', 'false') in ['true', '1']
176
174
  Session._p_logfile = path_logfile
177
- self._clearance = CLEARANCE_NONE
175
+ self._role = CLEARANCE_NONE
178
176
  self._verbose("Creating accsyn Python API session (v{})".format(__version__))
179
177
  for key in os.environ:
180
178
  if key.startswith("FILMHUB_"):
181
179
  Session._warning('Found old FilmHUB product environment variable "{}", ' "please migrate!".format(key))
182
- if domain is None:
183
- if not (
184
- "ACCSYN_DOMAIN" in os.environ
185
- or "ACCSYN_ORG" in os.environ
186
- or "FILMHUB_DOMAIN" in os.environ
187
- or "FILMHUB_ORG" in os.environ
188
- ):
189
- raise accsynException(
190
- "Please supply your accsyn domain/organization or set " "ACCSYN_DOMAIN environment!"
180
+ if not domain:
181
+ domain = (
182
+ os.environ["ACCSYN_DOMAIN"]
183
+ if "ACCSYN_DOMAIN" in os.environ
184
+ else os.environ.get(
185
+ "ACCSYN_ORG",
191
186
  )
192
- self._domain = domain or (
193
- os.environ["ACCSYN_DOMAIN"]
194
- if "ACCSYN_DOMAIN" in os.environ
195
- else os.environ.get(
196
- "ACCSYN_ORG",
197
- os.environ.get("FILMHUB_DOMAIN", os.environ.get("FILMHUB_ORG")),
198
187
  )
199
- )
200
- if username is None:
201
- if not ("ACCSYN_API_USER" in os.environ or "FILMHUB_API_USER" in os.environ):
202
- raise accsynException(
203
- "Please supply your accsyn user name (E-mail) or set " "ACCSYN_API_USER environment!"
188
+ if not domain:
189
+ raise AccsynException(
190
+ "Please supply your accsyn domain/organization or set " "ACCSYN_DOMAIN environment!"
191
+ )
192
+ if not username:
193
+ username = os.environ.get("ACCSYN_API_USER")
194
+ if not username:
195
+ if not ("ACCSYN_API_USER" in os.environ):
196
+ raise AccsynException(
197
+ "Please supply your accsyn user name (E-mail) or set ACCSYN_API_USER environment!"
204
198
  )
205
- self._username = username or os.environ.get("ACCSYN_API_USER") or os.environ["FILMHUB_API_USER"]
206
- if api_key:
207
- self._api_key = api_key
208
- else:
209
- self._api_key = os.environ.get("ACCSYN_API_KEY") or os.environ.get("FILMHUB_API_KEY")
210
- if len(session_key or "") == 0:
211
- session_key = os.environ.get("ACCSYN_SESSION_KEY")
212
- if 0 < len(session_key or ""):
213
- # User has a session key for us to use, validate at login, store it
214
- # temporarily
215
- self._session_key_provided = session_key
216
- elif len(self._api_key or "") == 0:
217
- if 0 < len(pwd or ""):
218
- # Store it temporarily
219
- self._pwd = pwd
220
- else:
221
- raise accsynException("Please supply your accsyn API KEY or set ACCSYN_API_KEY " "environment!")
199
+ if not api_key:
200
+ api_key = os.environ.get("ACCSYN_API_KEY")
201
+ if not api_key:
202
+ raise AccsynException("Please supply your accsyn API KEY or set ACCSYN_API_KEY environment!")
222
203
  self._hostname = hostname
223
- self._port = port or ACCSYN_PORT
204
+ self._port = port
224
205
  self._timeout = timeout or Session.DEFAULT_TIMEOUT
225
206
  self._connect_timeout = connect_timeout or Session.DEFAULT_CONNECT_TIMEOUT
226
207
  if self._hostname is None:
227
208
  if self._dev:
228
- self._hostname = "172.16.178.161"
209
+ self._hostname = "127.0.0.1"
229
210
  else:
230
211
  # Get domain
231
- result = self._rest(
232
- "PUT",
233
- ACCSYN_CLOUD_REGISTRY_HOSTNAME,
234
- "registry/organization/domain",
235
- {"organization": self._domain},
212
+ response = self._rest(
213
+ "GET",
214
+ ACCSYN_BACKEND_MASTER_HOSTNAME,
215
+ "J3PKTtDvolDMBtTy6AFGA",
216
+ {"ident": domain},
236
217
  )
237
218
  # Store hostname
238
- assert "domain" in result, "No domain were provided for us!"
239
- self._hostname = "%s.%s" % (
240
- result["domain"],
241
- ACCSYN_CLOUD_DOMAIN,
242
- )
219
+ if "message" in response:
220
+ raise AccsynException(response["message"])
221
+ result = response.get('result', {})
222
+ assert "hostname" in result, "No API endpoint hostname were provided for us!"
223
+ self._hostname = result["hostname"]
224
+ if self._port is None:
225
+ self._port = result["port"]
226
+ if self._port is None:
227
+ self._port = ACCSYN_PORT if not self._dev else 8181
228
+ self._domain = domain
229
+ self._username = username
230
+ self._api_key = api_key
243
231
  self._last_message = None
244
232
  self.login()
245
233
 
@@ -286,66 +274,32 @@ class Session(object):
286
274
  """Retreive error message from last API call."""
287
275
  return self._last_message
288
276
 
289
- def login(self, revive_session_key=None):
277
+ def login(self):
290
278
  """Attempt to login to accsyn and get a session."""
291
279
  # TODO: Load session key from safe disk storage/key chain?
292
- assert self._session_key is None, "Already logged in!"
293
- d = {
294
- "session": self._session_id,
280
+ assert self._uid is None, "Already logged in!"
281
+ payload = dict(
282
+ session_id=self._session_id,
283
+ )
284
+ headers = {
285
+ "Authorization": "basic {}:{}".format(
286
+ Session._base64_encode(self._username),
287
+ Session._base64_encode(self._api_key),
288
+ ),
289
+ "X-Accsyn-Workspace": self._domain,
295
290
  }
296
- if revive_session_key:
297
- d["session_key_reuse"] = revive_session_key
298
- if self._api_key:
299
- headers = {
300
- "Authorization": "ASCredentials {}".format(
301
- Session._base64_encode(
302
- '{"domain":"%s","username":"%s","api_key":"%s"}'
303
- % (self._domain, self._username, self._api_key)
304
- )
305
- )
306
- }
307
- elif self._pwd:
308
- headers = {
309
- "Authorization": "ASCredentials {}".format(
310
- Session._base64_encode(
311
- '{"domain":"%s","username":"%s","pwd":"%s"}'
312
- % (
313
- self._domain,
314
- self._username,
315
- Session._base64_encode(self._pwd),
316
- )
317
- )
318
- )
319
- }
320
- self._pwd = None # Forget this now
321
- elif self._session_key_provided:
322
- headers = {
323
- "Authorization": "ASSession {}".format(
324
- Session._base64_encode(
325
- '{"domain":"%s","username":"%s","session_key":"%s"}'
326
- % (
327
- self._domain,
328
- self._username,
329
- self._session_key_provided,
330
- )
331
- )
332
- )
333
- }
334
- self._session_key_provided = None # Forget this now
335
- else:
336
- raise Exception("No means of authentication available!")
337
- result = self._rest(
291
+ response = self._rest(
338
292
  "PUT",
339
293
  self._hostname,
340
- "/user/login/auth",
341
- d,
294
+ "/api/login",
295
+ payload,
342
296
  headers=headers,
343
297
  port=self._port,
344
298
  )
345
299
  # Store session key
346
- assert "session_key" in result, "No session key were provided!"
347
- self._session_key = result["session_key"]
348
- self._clearance = result["clearance"] or CLEARANCE_NONE
300
+ assert "result" in response, "No result were provided!"
301
+ result = response["result"]
302
+ self._role = result["role"]
349
303
  self._uid = result["id"]
350
304
  return True
351
305
 
@@ -373,7 +327,7 @@ class Session(object):
373
327
  if os.path.exists(data):
374
328
  data = json.load(open(data, "r"))
375
329
  else:
376
- raise accsynException(
330
+ raise AccsynException(
377
331
  "Cannot build JSON payload data, not a valid JSON " "string or path to a JSON file!"
378
332
  )
379
333
  else:
@@ -998,7 +952,7 @@ class Session(object):
998
952
  :return: Processed publish data, see documentation.
999
953
  """
1000
954
  if data is None or not isinstance(data, list):
1001
- raise accsynException("None or empty data supplied!")
955
+ raise AccsynException("None or empty data supplied!")
1002
956
 
1003
957
  # Check entries, calculate size
1004
958
  def recursive_get_size(files):
@@ -1046,19 +1000,6 @@ class Session(object):
1046
1000
  """Fetch API key, by default disabled in backend."""
1047
1001
  return self._event("GET", "user/api_key", {})["api_key"]
1048
1002
 
1049
- def get_session_key(self):
1050
- """Return the current API session key."""
1051
- return self._session_key
1052
-
1053
- def generate_session_key(self, lifetime=None):
1054
- """Generate a new API session key, with the given *lifetime*."""
1055
- return self._event(
1056
- "POST",
1057
- "user/generate_session_key",
1058
- {"lifetime": lifetime},
1059
- query=self._username,
1060
- )["session_key"]
1061
-
1062
1003
  def gui_is_running(self):
1063
1004
  """
1064
1005
  Check if a GUI is running on the same machine (hostname match) and with same username.
@@ -1168,7 +1109,7 @@ class Session(object):
1168
1109
  if port is None:
1169
1110
  port = self._port or ACCSYN_PORT
1170
1111
  if hostname is None:
1171
- hostname = "%s.%s" % (self._domain, ACCSYN_CLOUD_DOMAIN)
1112
+ hostname = "{}.{}".format(self._domain, ACCSYN_BACKEND_DOMAIN)
1172
1113
  # Proxy set?
1173
1114
  proxy_type = None
1174
1115
  proxy_hostname = None
@@ -1196,12 +1137,12 @@ class Session(object):
1196
1137
  if proxy_type == "accsyn":
1197
1138
  if proxy_port == -1:
1198
1139
  proxy_port = 80
1199
- self._verbose("Using accsyn proxy @ %s:%s" % (proxy_hostname, proxy_port))
1140
+ self._verbose("Using accsyn proxy @ {}:{}".format(proxy_hostname, proxy_port))
1200
1141
  hostname = proxy_hostname
1201
1142
  port = proxy_port
1202
1143
  elif proxy_type in ["socks", "socks5"]:
1203
1144
  try:
1204
- self._verbose("Using SOCKS5 proxy @ %s:%s" % (proxy_hostname, proxy_port))
1145
+ self._verbose("Using SOCKS5 proxy @ {}:{}".format(proxy_hostname, proxy_port))
1205
1146
  import socks
1206
1147
 
1207
1148
  socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, proxy_hostname, proxy_port)
@@ -1210,8 +1151,8 @@ class Session(object):
1210
1151
  Session._warning('Python lacks SOCKS support, please install "pysocks" and' " try again...")
1211
1152
  raise ie
1212
1153
  elif proxy_type is not None:
1213
- raise accsynException('Unknown proxy type "{}"!'.format(proxy_type))
1214
- url = "http{}://{}:{}/api/v1.0{}".format(
1154
+ raise AccsynException('Unknown proxy type "{}"!'.format(proxy_type))
1155
+ url = "http{}://{}:{}/api/v3{}".format(
1215
1156
  "s" if ssl else "",
1216
1157
  hostname,
1217
1158
  port,
@@ -1224,161 +1165,125 @@ class Session(object):
1224
1165
  # Wait 10s to reach machine, 2min for it to send back data
1225
1166
  CONNECT_TO, READ_TO = (self.connect_timeout, timeout)
1226
1167
  r = None
1227
- for iteration in range(0, 2):
1228
- if headers:
1229
- headers_effective = copy.deepcopy(headers)
1230
- else:
1231
- if uri.find("registry/") != 0:
1232
- assert self._session_key is not None, "Need to be authenticated when communicating with " "accsyn!"
1233
- header_data = '{"domain":"%s","username":"%s","session_key":"%s"}' % (
1234
- self._domain,
1235
- self._username,
1236
- self._session_key,
1237
- )
1238
- headers_effective = {"Authorization": "ASSession {}".format(Session._base64_encode(header_data))}
1239
- else:
1240
- headers_effective = {}
1241
- headers_effective["ASDevice"] = "PythonAPI v%s @ %s %s(%s)" % (
1242
- __version__,
1243
- sys.platform,
1244
- Session.get_hostname(),
1245
- os.name,
1168
+ retval = None
1169
+
1170
+ headers_effective = dict()
1171
+ if headers:
1172
+ headers_effective = copy.deepcopy(headers)
1173
+ elif self._api_key:
1174
+ headers_effective = {
1175
+ "Authorization": "basic {}:{}".format(
1176
+ Session._base64_encode(self._username),
1177
+ Session._base64_encode(self._api_key)
1178
+ ),
1179
+ "X-Accsyn-Workspace": self._domain,
1180
+ }
1181
+ headers_effective["X-Accsyn-Device"] = "PythonAPI v%s @ %s %s(%s)" % (
1182
+ __version__,
1183
+ sys.platform,
1184
+ Session.get_hostname(),
1185
+ os.name,
1186
+ )
1187
+ if 3 <= sys.version_info.major:
1188
+ t_start = int(round(time.time() * 1000))
1189
+ else:
1190
+ t_start = long(round(time.time() * 1000))
1191
+ try:
1192
+ self._verbose(
1193
+ "REST %s %s, data: %s"
1194
+ % (
1195
+ method,
1196
+ url,
1197
+ data if not self._pretty_json else Session.str(data),
1198
+ )
1246
1199
  )
1247
- if 3 <= sys.version_info.major:
1248
- t_start = int(round(time.time() * 1000))
1249
- else:
1250
- t_start = long(round(time.time() * 1000))
1251
- try:
1252
- self._verbose(
1253
- "REST %s %s, data: %s"
1254
- % (
1255
- method,
1256
- url,
1257
- data if not self._pretty_json else Session.str(data),
1258
- )
1200
+ if method.lower() == "get":
1201
+ r = requests.get(
1202
+ url,
1203
+ params=Session._url_quote(data),
1204
+ timeout=(CONNECT_TO, READ_TO),
1205
+ verify=False,
1206
+ headers=headers_effective,
1259
1207
  )
1260
- if method.lower() == "get":
1261
- r = requests.get(
1262
- url,
1263
- params=Session._url_quote(data),
1264
- timeout=(CONNECT_TO, READ_TO),
1265
- verify=False,
1266
- headers=headers_effective,
1267
- )
1268
- elif method.lower() == "put":
1269
- r = requests.put(
1270
- url,
1271
- Session._safe_dumps(data),
1272
- timeout=(CONNECT_TO, READ_TO),
1273
- verify=False,
1274
- headers=headers_effective,
1275
- )
1276
- elif method.lower() == "post":
1277
- r = requests.post(
1278
- url,
1279
- Session._safe_dumps(data),
1280
- timeout=(CONNECT_TO, READ_TO),
1281
- verify=False,
1282
- headers=headers_effective,
1283
- )
1284
- elif method.lower() == "delete":
1285
- r = requests.delete(
1286
- url,
1287
- params=Session._url_quote(data),
1288
- timeout=(CONNECT_TO, READ_TO),
1289
- verify=False,
1290
- headers=headers_effective,
1291
- )
1292
- t_end = int(round(time.time() * 1000))
1293
- # break
1294
- except BaseException:
1295
- # if timeout <= 0:
1296
- raise accsynException(
1297
- "Could not reach {}:{}! Make sure cloud server({}) can"
1298
- " be reached from you location and no firewall is "
1299
- "blocking outgoing TCP traffic at port {}. "
1300
- "Details: {}".format(
1301
- hostname,
1302
- port,
1303
- hostname,
1304
- port,
1305
- traceback.format_exc() if not quiet else "(quiet)",
1306
- )
1208
+ elif method.lower() == "put":
1209
+ r = requests.put(
1210
+ url,
1211
+ Session._safe_dumps(data),
1212
+ timeout=(CONNECT_TO, READ_TO),
1213
+ verify=False,
1214
+ headers=headers_effective,
1307
1215
  )
1308
- # sleep_time = 2
1309
- # t_end = int(round(time.time() * 1000))
1310
- # timeout -= int((t_end - t_start) / 1000)
1311
- # timeout -= sleep_time
1312
- #
1313
- # Session._warning(
1314
- # "Could not reach {}:{}! Waited {}s/{}, will try again in "
1315
- # "{}s... Details: {}".format(
1316
- # hostname,
1317
- # port,
1318
- # initial_timeout - timeout,
1319
- # "%ss" % initial_timeout if initial_timeout < 99999999 else "INF",
1320
- # sleep_time,
1321
- # traceback.format_exc(),
1322
- # )
1323
- # )
1324
- # time.sleep(sleep_time)
1325
-
1326
- try:
1327
- retval = json.loads(r.text, cls=JSONDecoder)
1328
- if not quiet:
1329
- self._verbose(
1330
- "{}/{} REST {} result: {} (~{}ms)".format(
1331
- hostname,
1332
- uri,
1333
- method,
1334
- Session._obscure_dict_string(
1335
- Session._safely_printable(
1336
- str(retval) if not self._pretty_json else Session.str(retval)
1337
- ).replace("'", '"')
1338
- ),
1339
- t_start - t_end + 1,
1340
- )
1341
- )
1342
- do_retry = False
1343
- if not retval.get("message") is None:
1344
- # Something went wrong
1345
- if retval.get("session_expired") is True:
1346
- if self._api_key is not None:
1347
- # We should be able to get a new session and retry
1348
- revive_session_key = self._session_key
1349
- self._session_key = None
1350
- self.login(revive_session_key=revive_session_key)
1351
- self._info('Authenticated using API KEY and reused expired session...')
1352
- do_retry = True
1353
- if not do_retry:
1354
- self._last_message = retval["message"]
1355
- if not do_retry:
1356
- break
1357
- except BaseException:
1358
- sys.stderr.write(traceback.format_exc())
1359
- message = 'The {}:{}/{} REST {} {} operation failed! Details: '
1360
- '{} {}'.format(
1216
+ elif method.lower() == "post":
1217
+ r = requests.post(
1218
+ url,
1219
+ Session._safe_dumps(data),
1220
+ timeout=(CONNECT_TO, READ_TO),
1221
+ verify=False,
1222
+ headers=headers_effective,
1223
+ )
1224
+ elif method.lower() == "delete":
1225
+ r = requests.delete(
1226
+ url,
1227
+ params=Session._url_quote(data),
1228
+ timeout=(CONNECT_TO, READ_TO),
1229
+ verify=False,
1230
+ headers=headers_effective,
1231
+ )
1232
+ t_end = int(round(time.time() * 1000))
1233
+ # break
1234
+ except BaseException:
1235
+ # if timeout <= 0:
1236
+ raise AccsynException(
1237
+ "Could not reach {}:{}! Make sure backend({}) can"
1238
+ " be reached from you location and no firewall is "
1239
+ "blocking outgoing TCP traffic at port {}. "
1240
+ "Details: {}".format(
1361
1241
  hostname,
1362
1242
  port,
1363
- uri,
1364
- method,
1365
- Session._obscure_dict_string(Session._safely_printable(str(data)).replace("'", '"')),
1366
- r.text,
1367
- traceback.format_exc(),
1243
+ hostname,
1244
+ port,
1245
+ traceback.format_exc() if not quiet else "(quiet)",
1246
+ )
1247
+ )
1248
+ try:
1249
+ retval = json.loads(r.text, cls=JSONDecoder)
1250
+ if not quiet:
1251
+ self._verbose(
1252
+ "{}/{} REST {} result: {} (~{}ms)".format(
1253
+ hostname,
1254
+ uri,
1255
+ method,
1256
+ Session._obscure_dict_string(
1257
+ Session._safely_printable(
1258
+ str(retval) if not self._pretty_json else Session.str(retval)
1259
+ ).replace("'", '"')
1260
+ ),
1261
+ t_start - t_end + 1,
1262
+ )
1368
1263
  )
1369
- Session._warning(message)
1370
- raise accsynException(message)
1264
+ except BaseException:
1265
+ sys.stderr.write(traceback.format_exc())
1266
+ message = 'The {} REST {} {} operation failed! Details: {} {}'.format(
1267
+ url,
1268
+ method,
1269
+ Session._obscure_dict_string(Session._safely_printable(str(data)).replace("'", '"')),
1270
+ r.text,
1271
+ traceback.format_exc(),
1272
+ )
1273
+ Session._warning(message)
1274
+ raise AccsynException(message)
1275
+
1371
1276
  if "exception" in retval:
1372
1277
  message = "{} caused an exception! Please contact {} admin for more"
1373
1278
  " further support.".format(uri, self._domain)
1374
1279
  Session._warning(message)
1375
- if self._clearance in [CLEARANCE_ADMIN, CLEARANCE_CLOUDADMIN]:
1280
+ if self._role in [CLEARANCE_ADMIN, CLEARANCE_SUPPORT]:
1376
1281
  Session._warning(retval["exception"])
1377
- raise accsynException(message)
1282
+ raise AccsynException(message)
1378
1283
  elif "message" in retval:
1379
1284
  message_effective = retval.get("message_hr") or retval["message"]
1380
1285
  Session._warning(message_effective)
1381
- raise accsynException(message_effective)
1286
+ raise AccsynException(message_effective)
1382
1287
  return retval
1383
1288
 
1384
1289
  # REST get
@@ -1395,7 +1300,7 @@ class Session(object):
1395
1300
  quiet=False,
1396
1301
  ):
1397
1302
  """Utility; Construct an event and send using REST to accsyn backend."""
1398
- assert self._session_key, "Login before posting event!"
1303
+ assert self._uid, "Login before posting event!"
1399
1304
  event = {
1400
1305
  "audience": "api",
1401
1306
  "domain": self._domain,
@@ -1608,6 +1513,6 @@ class Session(object):
1608
1513
  return binascii.b2a_base64(s)
1609
1514
 
1610
1515
 
1611
- class accsynException(Exception):
1516
+ class AccsynException(Exception):
1612
1517
  def __init__(self, message):
1613
- super(accsynException, self).__init__(message)
1518
+ super(AccsynException, self).__init__(message)
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: accsyn-python-api
3
+ Version: 3.0.1
4
+ Summary: A Python API for accsyn programmable fast and secure data delivery software
5
+ Home-page: https://github.com/accsyn/accsyn-python-api.git
6
+ Author: Henrik Norin
7
+ Author-email: henrik.norin@accsyn.com
8
+ License: Apache License (2.0)
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=2.7.9, <4.0
13
+ Description-Content-Type: text/markdown
14
+
15
+ # accsyn-python-api
16
+ Official accsyn fast film delivery Python API
17
+
18
+ Complete Python API reference can be found [here](https://support.accsyn.com/python-api).
19
+
20
+
21
+ Changelog:
22
+ ----------
23
+
24
+ See doc/release_notes.rst
25
+
26
+
27
+ Documentation:
28
+ --------------
29
+
30
+ [https://accsyn-python-api.readthedocs.io/en/latest](https://accsyn-python-api.readthedocs.io/en/latest)
31
+
32
+
33
+ Building:
34
+ ---------
35
+
36
+ To build the documentation locally, run:
37
+
38
+ ```
39
+ cd doc
40
+ pip install -r requirements.txt
41
+ python -m sphinx -T -E -b html -d _build/doctrees -D language=en . ../dist/doc
42
+ ```
43
+
44
+ Deploying:
45
+ ----------
46
+
47
+ ```
48
+ python setup.py sdist bdist_wheel
49
+ twine upload --verbose --username accsyn dist/*
50
+ ```
51
+
52
+ Henrik Norin, HDR AB, 2023
53
+ accsyn(r) - secure data delivery and workflow sync
54
+ https://accsyn.com
55
+ https://support.accsyn.com
56
+
@@ -1 +0,0 @@
1
- *.pyc
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: accsyn-python-api
3
- Version: 2.2.1
4
- Summary: A Python API for accsyn programmable fast and secure data delivery software
5
- Home-page: https://github.com/accsyn/accsyn-python-api.git
6
- Author: Henrik Norin
7
- Author-email: henrik.norin@accsyn.com
8
- License: Apache License (2.0)
9
- Description: # accsyn-python-api
10
- Official accsyn fast film delivery Python API
11
-
12
- Complete Python API reference can be found [here](https://support.accsyn.com/python-api).
13
-
14
-
15
- Changelog:
16
- ----------
17
-
18
- See doc/release_notes.rst
19
-
20
-
21
- Documentation:
22
- --------------
23
-
24
- [https://accsyn-python-api.readthedocs.io/en/latest](https://accsyn-python-api.readthedocs.io/en/latest)
25
-
26
-
27
- Building:
28
- ---------
29
-
30
- To build the documentation locally, run:
31
-
32
- ```
33
- cd doc
34
- pip install -r requirements.txt
35
- python -m sphinx -T -E -b html -d _build/doctrees -D language=en . ../dist/doc
36
- ```
37
-
38
-
39
- Henrik Norin, HDR AB, 2023
40
- accsyn(r) - secure data delivery and workflow sync
41
- https://accsyn.com
42
- https://support.accsyn.com
43
-
44
-
45
- Platform: UNKNOWN
46
- Classifier: Programming Language :: Python :: 3
47
- Classifier: License :: OSI Approved :: MIT License
48
- Classifier: Operating System :: OS Independent
49
- Requires-Python: >=2.7.9, <4.0
50
- Description-Content-Type: text/markdown
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: accsyn-python-api
3
- Version: 2.2.1
4
- Summary: A Python API for accsyn programmable fast and secure data delivery software
5
- Home-page: https://github.com/accsyn/accsyn-python-api.git
6
- Author: Henrik Norin
7
- Author-email: henrik.norin@accsyn.com
8
- License: Apache License (2.0)
9
- Description: # accsyn-python-api
10
- Official accsyn fast film delivery Python API
11
-
12
- Complete Python API reference can be found [here](https://support.accsyn.com/python-api).
13
-
14
-
15
- Changelog:
16
- ----------
17
-
18
- See doc/release_notes.rst
19
-
20
-
21
- Documentation:
22
- --------------
23
-
24
- [https://accsyn-python-api.readthedocs.io/en/latest](https://accsyn-python-api.readthedocs.io/en/latest)
25
-
26
-
27
- Building:
28
- ---------
29
-
30
- To build the documentation locally, run:
31
-
32
- ```
33
- cd doc
34
- pip install -r requirements.txt
35
- python -m sphinx -T -E -b html -d _build/doctrees -D language=en . ../dist/doc
36
- ```
37
-
38
-
39
- Henrik Norin, HDR AB, 2023
40
- accsyn(r) - secure data delivery and workflow sync
41
- https://accsyn.com
42
- https://support.accsyn.com
43
-
44
-
45
- Platform: UNKNOWN
46
- Classifier: Programming Language :: Python :: 3
47
- Classifier: License :: OSI Approved :: MIT License
48
- Classifier: Operating System :: OS Independent
49
- Requires-Python: >=2.7.9, <4.0
50
- Description-Content-Type: text/markdown