accsyn-python-api 2.2.0__tar.gz → 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. accsyn-python-api-3.0.0/PKG-INFO +56 -0
  2. accsyn-python-api-3.0.0/README.md +42 -0
  3. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/file.rst +23 -0
  4. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/release_notes.rst +7 -0
  5. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/setup.py +1 -1
  6. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_api/_version.py +1 -1
  7. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_api/session.py +159 -264
  8. accsyn-python-api-3.0.0/source/accsyn_python_api.egg-info/PKG-INFO +56 -0
  9. accsyn-python-api-2.2.0/PKG-INFO +0 -32
  10. accsyn-python-api-2.2.0/README.md +0 -17
  11. accsyn-python-api-2.2.0/source/accsyn_python_api.egg-info/PKG-INFO +0 -32
  12. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/.github/workflows/github-actions-black.yml +0 -0
  13. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/.gitignore +0 -0
  14. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/.pre-commit-config.yaml +0 -0
  15. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/.readthedocs.yaml +0 -0
  16. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/_static/accsyn.css +0 -0
  17. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/api_reference/index.rst +0 -0
  18. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/api_reference/session.rst +0 -0
  19. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/clients.rst +0 -0
  20. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/conf.py +0 -0
  21. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/datatypes.rst +0 -0
  22. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/glossary.rst +0 -0
  23. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/index.rst +0 -0
  24. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/installing.rst +0 -0
  25. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/introduction.rst +0 -0
  26. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/jobs.rst +0 -0
  27. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/misc.rst +0 -0
  28. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/publish.rst +0 -0
  29. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/queues.rst +0 -0
  30. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/render.rst +0 -0
  31. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/requirements.txt +0 -0
  32. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/shares.rst +0 -0
  33. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/users.rst +0 -0
  34. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/doc/using.rst +0 -0
  35. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/pyproject.toml +0 -0
  36. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/readthedocs.yaml +0 -0
  37. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/setup.cfg +0 -0
  38. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_api/__init__.py +0 -0
  39. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_python_api.egg-info/SOURCES.txt +0 -0
  40. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_python_api.egg-info/dependency_links.txt +0 -0
  41. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_python_api.egg-info/requires.txt +0 -0
  42. {accsyn-python-api-2.2.0 → accsyn-python-api-3.0.0}/source/accsyn_python_api.egg-info/top_level.txt +0 -0
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: accsyn-python-api
3
+ Version: 3.0.0
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
+
@@ -0,0 +1,42 @@
1
+ # accsyn-python-api
2
+ Official accsyn fast film delivery Python API
3
+
4
+ Complete Python API reference can be found [here](https://support.accsyn.com/python-api).
5
+
6
+
7
+ Changelog:
8
+ ----------
9
+
10
+ See doc/release_notes.rst
11
+
12
+
13
+ Documentation:
14
+ --------------
15
+
16
+ [https://accsyn-python-api.readthedocs.io/en/latest](https://accsyn-python-api.readthedocs.io/en/latest)
17
+
18
+
19
+ Building:
20
+ ---------
21
+
22
+ To build the documentation locally, run:
23
+
24
+ ```
25
+ cd doc
26
+ pip install -r requirements.txt
27
+ python -m sphinx -T -E -b html -d _build/doctrees -D language=en . ../dist/doc
28
+ ```
29
+
30
+ Deploying:
31
+ ----------
32
+
33
+ ```
34
+ python setup.py sdist bdist_wheel
35
+ twine upload --verbose --username accsyn dist/*
36
+ ```
37
+
38
+ Henrik Norin, HDR AB, 2023
39
+ accsyn(r) - secure data delivery and workflow sync
40
+ https://accsyn.com
41
+ https://support.accsyn.com
42
+
@@ -25,6 +25,8 @@ Optional arguments:
25
25
  * ``directories_only``: Return only directories in listing, True or False. Default is False.
26
26
  * ``files_only``: Return only files in listing, True or False. Default is False. Note: Providing recursive=True won't have any affect.
27
27
  * ``getsize``: Calculate and return size of directories.
28
+ * ``include``: Filter expression (string or list) dictating what to include in result: "word" - exact match, "*word" - ends with word, "word*" - starts with word, "*word*" - contains word, "start*end" - starts & ends with word and "re('...')" - regular expression. Has precedence over *exclude*.
29
+ * ``exclude``:Filter expression (string or list) dictating what to exclude from result: "word" - exact match, "*word" - ends with word, "word*" - starts with word, "*word*" - contains word, "start*end" - starts & ends with word and "re('...')" - regular expression.
28
30
 
29
31
 
30
32
 
@@ -69,6 +71,27 @@ If succeeds, this will return a list of dictionaries, one for each file found, w
69
71
  }
70
72
 
71
73
 
74
+
75
+ To search a directory, and its sub-directories, for files with a specific name, use the ``include`` argument::
76
+
77
+ session.ls("share=Documentation", include="FindMe.doc", recursive=True)
78
+
79
+
80
+ To exclude files matching a regular expression, use the ``exclude`` argument::
81
+
82
+ session.ls("share=Documentation", exclude="re('_Draft.*')")
83
+
84
+
85
+ To make it case insensitive::
86
+
87
+ session.ls("share=thefilm-DIT/TO_ACMEFILM", exclude="re('_draft.*', 'I')")
88
+
89
+
90
+ .. note::
91
+
92
+ Include and exclude can be combined, include has precedence over exclude.
93
+
94
+
72
95
  Failure scenarios
73
96
  *****************
74
97
 
@@ -13,6 +13,13 @@ Release Notes
13
13
 
14
14
  `https://support.accsyn.com <https://support.accsyn.com>`_.
15
15
 
16
+ .. release:: 3.0.0
17
+ :date: 2024-11-17
18
+
19
+ .. change:: feat
20
+
21
+ * Compliance with new accsyn v3 workspaces.
22
+ * Removed pwd and session key authentication, accsyn v3 only support API key basic auth.
16
23
 
17
24
  .. release:: 2.2.0
18
25
  :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.0',
8
+ version='3.0.0',
9
9
  package_dir={'': 'source'},
10
10
  packages=['accsyn_api'],
11
11
  setup_requires=[
@@ -1,4 +1,4 @@
1
1
  # :coding: utf-8
2
2
  # :copyright: Copyright (c) 2015-2023 accsyn/HDR AB
3
3
 
4
- __version__ = "2.1.3-0"
4
+ __version__ = "2.2.1-0"
@@ -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,16 +164,14 @@ 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
172
169
  self._be_verbose = verbose
173
170
  self._pretty_json = pretty_json
174
171
  self._proxy = proxy
175
172
  self._dev = dev is True or os.environ.get('ACCSYN_DEV', 'false') in ['true', '1']
176
173
  Session._p_logfile = path_logfile
177
- self._clearance = CLEARANCE_NONE
174
+ self._role = CLEARANCE_NONE
178
175
  self._verbose("Creating accsyn Python API session (v{})".format(__version__))
179
176
  for key in os.environ:
180
177
  if key.startswith("FILMHUB_"):
@@ -183,8 +180,6 @@ class Session(object):
183
180
  if not (
184
181
  "ACCSYN_DOMAIN" in os.environ
185
182
  or "ACCSYN_ORG" in os.environ
186
- or "FILMHUB_DOMAIN" in os.environ
187
- or "FILMHUB_ORG" in os.environ
188
183
  ):
189
184
  raise accsynException(
190
185
  "Please supply your accsyn domain/organization or set " "ACCSYN_DOMAIN environment!"
@@ -194,52 +189,42 @@ class Session(object):
194
189
  if "ACCSYN_DOMAIN" in os.environ
195
190
  else os.environ.get(
196
191
  "ACCSYN_ORG",
197
- os.environ.get("FILMHUB_DOMAIN", os.environ.get("FILMHUB_ORG")),
198
192
  )
199
193
  )
200
194
  if username is None:
201
- if not ("ACCSYN_API_USER" in os.environ or "FILMHUB_API_USER" in os.environ):
195
+ if not ("ACCSYN_API_USER" in os.environ):
202
196
  raise accsynException(
203
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"]
199
+ self._username = username or os.environ.get("ACCSYN_API_USER")
206
200
  if api_key:
207
201
  self._api_key = api_key
208
202
  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!")
203
+ self._api_key = os.environ.get("ACCSYN_API_KEY")
204
+ if not self._api_key:
205
+ raise accsynException("Please supply your accsyn API KEY or set ACCSYN_API_KEY environment!")
222
206
  self._hostname = hostname
223
- self._port = port or ACCSYN_PORT
207
+ self._port = port
224
208
  self._timeout = timeout or Session.DEFAULT_TIMEOUT
225
209
  self._connect_timeout = connect_timeout or Session.DEFAULT_CONNECT_TIMEOUT
226
210
  if self._hostname is None:
227
211
  if self._dev:
228
- self._hostname = "172.16.178.161"
212
+ self._hostname = "127.0.0.1"
229
213
  else:
230
214
  # Get domain
231
215
  result = self._rest(
232
216
  "PUT",
233
- ACCSYN_CLOUD_REGISTRY_HOSTNAME,
234
- "registry/organization/domain",
235
- {"organization": self._domain},
217
+ ACCSYN_BACKEND_MASTER_HOSTNAME,
218
+ "workspace/J3PKTtDvolDMBtTy6AFGA",
219
+ {"ident": self._domain},
236
220
  )
237
221
  # 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
- )
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
243
228
  self._last_message = None
244
229
  self.login()
245
230
 
@@ -286,66 +271,32 @@ class Session(object):
286
271
  """Retreive error message from last API call."""
287
272
  return self._last_message
288
273
 
289
- def login(self, revive_session_key=None):
274
+ def login(self):
290
275
  """Attempt to login to accsyn and get a session."""
291
276
  # 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,
277
+ assert self._uid is None, "Already logged in!"
278
+ payload = dict(
279
+ session_id=self._session_id,
280
+ )
281
+ headers = {
282
+ "Authorization": "basic {}:{}".format(
283
+ Session._base64_encode(self._username),
284
+ Session._base64_encode(self._api_key),
285
+ ),
286
+ "X-Accsyn-Workspace": self._domain,
295
287
  }
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(
288
+ response = self._rest(
338
289
  "PUT",
339
290
  self._hostname,
340
- "/user/login/auth",
341
- d,
291
+ "/api/login",
292
+ payload,
342
293
  headers=headers,
343
294
  port=self._port,
344
295
  )
345
296
  # 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
297
+ assert "result" in response, "No result were provided!"
298
+ result = response["result"]
299
+ self._role = result["role"]
349
300
  self._uid = result["id"]
350
301
  return True
351
302
 
@@ -818,18 +769,15 @@ class Session(object):
818
769
  :param getsize: If True - file sizes will be returned.
819
770
  :param files_only: If True - only return files, no directories.
820
771
  :param directories_only: If True - only return directories, no files.
821
- :param include: Filter expression (string or list) dictating what to include in result: "word" - exact match,
822
- "*word" - ends with word, "word*" - starts with word, "*word*" - contains word and "re('...')" - regular
823
- expression. Has precedence over *exclude*.
824
- :param exclude: Filter expression (string or list) dictating what to exclude from result: "word" - exact match,
825
- "*word" - ends with word, "word*" - starts with word, "*word*" - contains word and "re('...')" - regular
826
- expression.
772
+ :param include: Filter expression (string or list) dictating what to include in result: "word" - exact match, "*word" - ends with word, "word*" - starts with word, "*word*" - contains word, "start*end" - starts & ends with word and "re('...')" - regular expression. Has precedence over *exclude*.
773
+ :param exclude: Filter expression (string or list) dictating what to exclude from result: "word" - exact match, "*word" - ends with word, "word*" - starts with word, "*word*" - contains word, "start*end" - starts & ends with word and "re('...')" - regular expression.
827
774
  :return: A dictionary containing result of file listing.
828
775
 
829
776
  Include and exclude filters are case-insensitive, to make regular expression case-sensitive, use the following
830
777
  syntax: "re('...', 'I')".
831
778
 
832
- .. versionadded:: 2.6-20
779
+ .. versionadded:: 2.2.0 (app/daemon: 2.6-20)
780
+
833
781
  """
834
782
  assert 0 < len(path or "") and (
835
783
  Session._is_str(path) or isinstance(path, dict) or isinstance(path, list)
@@ -860,17 +808,14 @@ class Session(object):
860
808
  Get size of a file or directory.
861
809
 
862
810
  :param path: The accsyn path, on the form 'share=<the share>/<path>/<somewhere>'.
863
- :param include: Filter expression (string or list) dictating what to include in result: "word" - exact match,
864
- "*word" - ends with word, "word*" - starts with word, "*word*" - contains word and "re('...')" - regular
865
- expression. Has precedence over *exclude*.
866
- :param exclude: Filter expression (string or list) dictating what to exclude from result: "word" - exact match,
867
- "*word" - ends with word, "word*" - starts with word, "*word*" - contains word and "re('...')" - regular
868
- expression.
869
-
870
- :return: A number representing the file size.
811
+ :param include: Filter expression (string or list) dictating what to include in result: "word" - exact match, "*word" - ends with word, "word*" - starts with word, "*word*" - contains word, "start*end" - starts & ends with word and "re('...')" - regular expression. Has precedence over *exclude*.
812
+ :param exclude: Filter expression (string or list) dictating what to exclude from result: "word" - exact match, "*word" - ends with word, "word*" - starts with word, "*word*" - contains word, "start*end" - starts & ends with word and "re('...')" - regular expression.
813
+ :return: A dictionary containing result of file listing.
871
814
 
872
815
  Include and exclude filters are case-insensitive, to make regular expression case-sensitive, use the following
873
816
  syntax: "re('...', 'I')".
817
+
818
+ .. versionadded:: 2.2.0 (app/daemon: 2.6-20)
874
819
  """
875
820
  assert 0 < len(path or "") and (
876
821
  Session._is_str(path) or isinstance(path, dict) or isinstance(path, list)
@@ -1052,19 +997,6 @@ class Session(object):
1052
997
  """Fetch API key, by default disabled in backend."""
1053
998
  return self._event("GET", "user/api_key", {})["api_key"]
1054
999
 
1055
- def get_session_key(self):
1056
- """Return the current API session key."""
1057
- return self._session_key
1058
-
1059
- def generate_session_key(self, lifetime=None):
1060
- """Generate a new API session key, with the given *lifetime*."""
1061
- return self._event(
1062
- "POST",
1063
- "user/generate_session_key",
1064
- {"lifetime": lifetime},
1065
- query=self._username,
1066
- )["session_key"]
1067
-
1068
1000
  def gui_is_running(self):
1069
1001
  """
1070
1002
  Check if a GUI is running on the same machine (hostname match) and with same username.
@@ -1174,7 +1106,7 @@ class Session(object):
1174
1106
  if port is None:
1175
1107
  port = self._port or ACCSYN_PORT
1176
1108
  if hostname is None:
1177
- hostname = "%s.%s" % (self._domain, ACCSYN_CLOUD_DOMAIN)
1109
+ hostname = "{}.{}".format(self._domain, ACCSYN_BACKEND_DOMAIN)
1178
1110
  # Proxy set?
1179
1111
  proxy_type = None
1180
1112
  proxy_hostname = None
@@ -1202,12 +1134,12 @@ class Session(object):
1202
1134
  if proxy_type == "accsyn":
1203
1135
  if proxy_port == -1:
1204
1136
  proxy_port = 80
1205
- self._verbose("Using accsyn proxy @ %s:%s" % (proxy_hostname, proxy_port))
1137
+ self._verbose("Using accsyn proxy @ {}:{}".format(proxy_hostname, proxy_port))
1206
1138
  hostname = proxy_hostname
1207
1139
  port = proxy_port
1208
1140
  elif proxy_type in ["socks", "socks5"]:
1209
1141
  try:
1210
- self._verbose("Using SOCKS5 proxy @ %s:%s" % (proxy_hostname, proxy_port))
1142
+ self._verbose("Using SOCKS5 proxy @ {}:{}".format(proxy_hostname, proxy_port))
1211
1143
  import socks
1212
1144
 
1213
1145
  socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, proxy_hostname, proxy_port)
@@ -1217,7 +1149,7 @@ class Session(object):
1217
1149
  raise ie
1218
1150
  elif proxy_type is not None:
1219
1151
  raise accsynException('Unknown proxy type "{}"!'.format(proxy_type))
1220
- url = "http{}://{}:{}/api/v1.0{}".format(
1152
+ url = "http{}://{}:{}/api/v3{}".format(
1221
1153
  "s" if ssl else "",
1222
1154
  hostname,
1223
1155
  port,
@@ -1230,155 +1162,118 @@ class Session(object):
1230
1162
  # Wait 10s to reach machine, 2min for it to send back data
1231
1163
  CONNECT_TO, READ_TO = (self.connect_timeout, timeout)
1232
1164
  r = None
1233
- for iteration in range(0, 2):
1234
- if headers:
1235
- headers_effective = copy.deepcopy(headers)
1236
- else:
1237
- if uri.find("registry/") != 0:
1238
- assert self._session_key is not None, "Need to be authenticated when communicating with " "accsyn!"
1239
- header_data = '{"domain":"%s","username":"%s","session_key":"%s"}' % (
1240
- self._domain,
1241
- self._username,
1242
- self._session_key,
1243
- )
1244
- headers_effective = {"Authorization": "ASSession {}".format(Session._base64_encode(header_data))}
1245
- else:
1246
- headers_effective = {}
1247
- headers_effective["ASDevice"] = "PythonAPI v%s @ %s %s(%s)" % (
1248
- __version__,
1249
- sys.platform,
1250
- Session.get_hostname(),
1251
- os.name,
1165
+ retval = None
1166
+
1167
+ if headers:
1168
+ headers_effective = copy.deepcopy(headers)
1169
+ else:
1170
+ headers_effective = {
1171
+ "Authorization": "basic {}:{}".format(
1172
+ Session._base64_encode(self._username),
1173
+ Session._base64_encode(self._api_key)
1174
+ ),
1175
+ "X-Accsyn-Workspace": self._domain,
1176
+ }
1177
+ headers_effective["X-Accsyn-Device"] = "PythonAPI v%s @ %s %s(%s)" % (
1178
+ __version__,
1179
+ sys.platform,
1180
+ Session.get_hostname(),
1181
+ os.name,
1182
+ )
1183
+ if 3 <= sys.version_info.major:
1184
+ t_start = int(round(time.time() * 1000))
1185
+ else:
1186
+ t_start = long(round(time.time() * 1000))
1187
+ try:
1188
+ self._verbose(
1189
+ "REST %s %s, data: %s"
1190
+ % (
1191
+ method,
1192
+ url,
1193
+ data if not self._pretty_json else Session.str(data),
1194
+ )
1252
1195
  )
1253
- if 3 <= sys.version_info.major:
1254
- t_start = int(round(time.time() * 1000))
1255
- else:
1256
- t_start = long(round(time.time() * 1000))
1257
- try:
1258
- self._verbose(
1259
- "REST %s %s, data: %s"
1260
- % (
1261
- method,
1262
- url,
1263
- data if not self._pretty_json else Session.str(data),
1264
- )
1196
+ if method.lower() == "get":
1197
+ r = requests.get(
1198
+ url,
1199
+ params=Session._url_quote(data),
1200
+ timeout=(CONNECT_TO, READ_TO),
1201
+ verify=False,
1202
+ headers=headers_effective,
1265
1203
  )
1266
- if method.lower() == "get":
1267
- r = requests.get(
1268
- url,
1269
- params=Session._url_quote(data),
1270
- timeout=(CONNECT_TO, READ_TO),
1271
- verify=False,
1272
- headers=headers_effective,
1273
- )
1274
- elif method.lower() == "put":
1275
- r = requests.put(
1276
- url,
1277
- Session._safe_dumps(data),
1278
- timeout=(CONNECT_TO, READ_TO),
1279
- verify=False,
1280
- headers=headers_effective,
1281
- )
1282
- elif method.lower() == "post":
1283
- r = requests.post(
1284
- url,
1285
- Session._safe_dumps(data),
1286
- timeout=(CONNECT_TO, READ_TO),
1287
- verify=False,
1288
- headers=headers_effective,
1289
- )
1290
- elif method.lower() == "delete":
1291
- r = requests.delete(
1292
- url,
1293
- params=Session._url_quote(data),
1294
- timeout=(CONNECT_TO, READ_TO),
1295
- verify=False,
1296
- headers=headers_effective,
1297
- )
1298
- t_end = int(round(time.time() * 1000))
1299
- # break
1300
- except BaseException:
1301
- # if timeout <= 0:
1302
- raise accsynException(
1303
- "Could not reach {}:{}! Make sure cloud server({}) can"
1304
- " be reached from you location and no firewall is "
1305
- "blocking outgoing TCP traffic at port {}. "
1306
- "Details: {}".format(
1307
- hostname,
1308
- port,
1309
- hostname,
1310
- port,
1311
- traceback.format_exc() if not quiet else "(quiet)",
1312
- )
1204
+ elif method.lower() == "put":
1205
+ r = requests.put(
1206
+ url,
1207
+ Session._safe_dumps(data),
1208
+ timeout=(CONNECT_TO, READ_TO),
1209
+ verify=False,
1210
+ headers=headers_effective,
1313
1211
  )
1314
- # sleep_time = 2
1315
- # t_end = int(round(time.time() * 1000))
1316
- # timeout -= int((t_end - t_start) / 1000)
1317
- # timeout -= sleep_time
1318
- #
1319
- # Session._warning(
1320
- # "Could not reach {}:{}! Waited {}s/{}, will try again in "
1321
- # "{}s... Details: {}".format(
1322
- # hostname,
1323
- # port,
1324
- # initial_timeout - timeout,
1325
- # "%ss" % initial_timeout if initial_timeout < 99999999 else "INF",
1326
- # sleep_time,
1327
- # traceback.format_exc(),
1328
- # )
1329
- # )
1330
- # time.sleep(sleep_time)
1331
-
1332
- try:
1333
- retval = json.loads(r.text, cls=JSONDecoder)
1334
- if not quiet:
1335
- self._verbose(
1336
- "{}/{} REST {} result: {} (~{}ms)".format(
1337
- hostname,
1338
- uri,
1339
- method,
1340
- Session._obscure_dict_string(
1341
- Session._safely_printable(
1342
- str(retval) if not self._pretty_json else Session.str(retval)
1343
- ).replace("'", '"')
1344
- ),
1345
- t_start - t_end + 1,
1346
- )
1347
- )
1348
- do_retry = False
1349
- if not retval.get("message") is None:
1350
- # Something went wrong
1351
- if retval.get("session_expired") is True:
1352
- if self._api_key is not None:
1353
- # We should be able to get a new session and retry
1354
- revive_session_key = self._session_key
1355
- self._session_key = None
1356
- self.login(revive_session_key=revive_session_key)
1357
- self._info('Authenticated using API KEY and reused expired session...')
1358
- do_retry = True
1359
- if not do_retry:
1360
- self._last_message = retval["message"]
1361
- if not do_retry:
1362
- break
1363
- except BaseException:
1364
- sys.stderr.write(traceback.format_exc())
1365
- message = 'The {}:{}/{} REST {} {} operation failed! Details: '
1366
- '{} {}'.format(
1212
+ elif method.lower() == "post":
1213
+ r = requests.post(
1214
+ url,
1215
+ Session._safe_dumps(data),
1216
+ timeout=(CONNECT_TO, READ_TO),
1217
+ verify=False,
1218
+ headers=headers_effective,
1219
+ )
1220
+ elif method.lower() == "delete":
1221
+ r = requests.delete(
1222
+ url,
1223
+ params=Session._url_quote(data),
1224
+ timeout=(CONNECT_TO, READ_TO),
1225
+ verify=False,
1226
+ headers=headers_effective,
1227
+ )
1228
+ t_end = int(round(time.time() * 1000))
1229
+ # break
1230
+ except BaseException:
1231
+ # if timeout <= 0:
1232
+ raise accsynException(
1233
+ "Could not reach {}:{}! Make sure backend({}) can"
1234
+ " be reached from you location and no firewall is "
1235
+ "blocking outgoing TCP traffic at port {}. "
1236
+ "Details: {}".format(
1367
1237
  hostname,
1368
1238
  port,
1369
- uri,
1370
- method,
1371
- Session._obscure_dict_string(Session._safely_printable(str(data)).replace("'", '"')),
1372
- r.text,
1373
- traceback.format_exc(),
1239
+ hostname,
1240
+ port,
1241
+ traceback.format_exc() if not quiet else "(quiet)",
1374
1242
  )
1375
- Session._warning(message)
1376
- raise accsynException(message)
1243
+ )
1244
+ try:
1245
+ retval = json.loads(r.text, cls=JSONDecoder)
1246
+ if not quiet:
1247
+ self._verbose(
1248
+ "{}/{} REST {} result: {} (~{}ms)".format(
1249
+ hostname,
1250
+ uri,
1251
+ method,
1252
+ Session._obscure_dict_string(
1253
+ Session._safely_printable(
1254
+ str(retval) if not self._pretty_json else Session.str(retval)
1255
+ ).replace("'", '"')
1256
+ ),
1257
+ t_start - t_end + 1,
1258
+ )
1259
+ )
1260
+ except BaseException:
1261
+ sys.stderr.write(traceback.format_exc())
1262
+ message = 'The {} REST {} {} operation failed! Details: {} {}'.format(
1263
+ url,
1264
+ method,
1265
+ Session._obscure_dict_string(Session._safely_printable(str(data)).replace("'", '"')),
1266
+ r.text,
1267
+ traceback.format_exc(),
1268
+ )
1269
+ Session._warning(message)
1270
+ raise accsynException(message)
1271
+
1377
1272
  if "exception" in retval:
1378
1273
  message = "{} caused an exception! Please contact {} admin for more"
1379
1274
  " further support.".format(uri, self._domain)
1380
1275
  Session._warning(message)
1381
- if self._clearance in [CLEARANCE_ADMIN, CLEARANCE_CLOUDADMIN]:
1276
+ if self._role in [CLEARANCE_ADMIN, CLEARANCE_SUPPORT]:
1382
1277
  Session._warning(retval["exception"])
1383
1278
  raise accsynException(message)
1384
1279
  elif "message" in retval:
@@ -1401,7 +1296,7 @@ class Session(object):
1401
1296
  quiet=False,
1402
1297
  ):
1403
1298
  """Utility; Construct an event and send using REST to accsyn backend."""
1404
- assert self._session_key, "Login before posting event!"
1299
+ assert self._uid, "Login before posting event!"
1405
1300
  event = {
1406
1301
  "audience": "api",
1407
1302
  "domain": self._domain,
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: accsyn-python-api
3
+ Version: 3.0.0
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,32 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: accsyn-python-api
3
- Version: 2.2.0
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
- Henrik Norin, HDR AB, 2022
22
- accsyn(r) - secure data delivery and workflow sync
23
- https://accsyn.com
24
- https://support.accsyn.com
25
-
26
-
27
- Platform: UNKNOWN
28
- Classifier: Programming Language :: Python :: 3
29
- Classifier: License :: OSI Approved :: MIT License
30
- Classifier: Operating System :: OS Independent
31
- Requires-Python: >=2.7.9, <4.0
32
- Description-Content-Type: text/markdown
@@ -1,17 +0,0 @@
1
- # accsyn-python-api
2
- Official accsyn fast film delivery Python API
3
-
4
- Complete Python API reference can be found [here](https://support.accsyn.com/python-api).
5
-
6
-
7
- Changelog:
8
- ----------
9
-
10
- See doc/release_notes.rst
11
-
12
-
13
- Henrik Norin, HDR AB, 2022
14
- accsyn(r) - secure data delivery and workflow sync
15
- https://accsyn.com
16
- https://support.accsyn.com
17
-
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: accsyn-python-api
3
- Version: 2.2.0
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
- Henrik Norin, HDR AB, 2022
22
- accsyn(r) - secure data delivery and workflow sync
23
- https://accsyn.com
24
- https://support.accsyn.com
25
-
26
-
27
- Platform: UNKNOWN
28
- Classifier: Programming Language :: Python :: 3
29
- Classifier: License :: OSI Approved :: MIT License
30
- Classifier: Operating System :: OS Independent
31
- Requires-Python: >=2.7.9, <4.0
32
- Description-Content-Type: text/markdown