Ayon-Python-Api 0.1.7__tar.gz → 0.1.8__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.
- {ayon-python-api-0.1.7/ayon_python_api.egg-info → ayon-python-api-0.1.8}/PKG-INFO +1 -1
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/__init__.py +17 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/exceptions.py +4 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/server.py +154 -27
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/server_api.py +112 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/utils.py +76 -17
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/version.py +1 -1
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8/ayon_python_api.egg-info}/PKG-INFO +1 -1
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/pyproject.toml +2 -1
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/LICENSE +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/README.md +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/constants.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/entity_hub.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/events.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/graphql.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/graphql_queries.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/operations.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_api/thumbnails.py +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_python_api.egg-info/SOURCES.txt +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_python_api.egg-info/dependency_links.txt +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_python_api.egg-info/requires.txt +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_python_api.egg-info/top_level.txt +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/setup.cfg +0 -0
- {ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/setup.py +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .utils import (
|
|
2
2
|
TransferProgress,
|
|
3
|
+
slugify_string,
|
|
3
4
|
)
|
|
4
5
|
from .server import (
|
|
5
6
|
ServerAPIBase,
|
|
@@ -7,6 +8,9 @@ from .server import (
|
|
|
7
8
|
|
|
8
9
|
from .server_api import (
|
|
9
10
|
ServerAPI,
|
|
11
|
+
ServiceContext,
|
|
12
|
+
|
|
13
|
+
init_service,
|
|
10
14
|
|
|
11
15
|
get_server_api_connection,
|
|
12
16
|
|
|
@@ -25,6 +29,11 @@ from .server_api import (
|
|
|
25
29
|
patch,
|
|
26
30
|
delete,
|
|
27
31
|
|
|
32
|
+
get_event,
|
|
33
|
+
dispatch_event,
|
|
34
|
+
update_event,
|
|
35
|
+
enroll_event_job,
|
|
36
|
+
|
|
28
37
|
download_file,
|
|
29
38
|
upload_file,
|
|
30
39
|
|
|
@@ -99,10 +108,13 @@ from .server_api import (
|
|
|
99
108
|
|
|
100
109
|
__all__ = (
|
|
101
110
|
"TransferProgress",
|
|
111
|
+
"slugify_string",
|
|
102
112
|
|
|
103
113
|
"ServerAPIBase",
|
|
104
114
|
|
|
105
115
|
"ServerAPI",
|
|
116
|
+
"ServiceContext",
|
|
117
|
+
"init_service",
|
|
106
118
|
|
|
107
119
|
"get_server_api_connection",
|
|
108
120
|
|
|
@@ -121,6 +133,11 @@ __all__ = (
|
|
|
121
133
|
"patch",
|
|
122
134
|
"delete",
|
|
123
135
|
|
|
136
|
+
"get_event",
|
|
137
|
+
"dispatch_event",
|
|
138
|
+
"update_event",
|
|
139
|
+
"enroll_event_job",
|
|
140
|
+
|
|
124
141
|
"download_file",
|
|
125
142
|
"upload_file",
|
|
126
143
|
|
|
@@ -75,13 +75,32 @@ class RequestTypes:
|
|
|
75
75
|
class RestApiResponse(object):
|
|
76
76
|
"""API Response."""
|
|
77
77
|
|
|
78
|
-
def __init__(self,
|
|
79
|
-
if
|
|
80
|
-
|
|
78
|
+
def __init__(self, response, data=None):
|
|
79
|
+
if response is None:
|
|
80
|
+
status_code = 500
|
|
81
|
+
else:
|
|
82
|
+
status_code = response.status_code
|
|
83
|
+
self._response = response
|
|
81
84
|
self.status = status_code
|
|
82
|
-
self.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
self._data = data
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def orig_response(self):
|
|
89
|
+
return self._response
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def headers(self):
|
|
93
|
+
return self._response.headers
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def data(self):
|
|
97
|
+
if self._data is None:
|
|
98
|
+
self._data = self._response.json()
|
|
99
|
+
return self._data
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def content(self):
|
|
103
|
+
return self._response.content
|
|
85
104
|
|
|
86
105
|
@property
|
|
87
106
|
def content_type(self):
|
|
@@ -95,6 +114,12 @@ class RestApiResponse(object):
|
|
|
95
114
|
def status_code(self):
|
|
96
115
|
return self.status
|
|
97
116
|
|
|
117
|
+
def raise_for_status(self):
|
|
118
|
+
self._response.raise_for_status()
|
|
119
|
+
|
|
120
|
+
def __enter__(self, *args, **kwargs):
|
|
121
|
+
return self._response.__enter__(*args, **kwargs)
|
|
122
|
+
|
|
98
123
|
def __contains__(self, key):
|
|
99
124
|
return key in self.data
|
|
100
125
|
|
|
@@ -448,26 +473,22 @@ class ServerAPIBase(object):
|
|
|
448
473
|
|
|
449
474
|
except ConnectionRefusedError:
|
|
450
475
|
new_response = RestApiResponse(
|
|
451
|
-
|
|
476
|
+
None,
|
|
452
477
|
{"detail": "Unable to connect the server. Connection refused"}
|
|
453
478
|
)
|
|
454
479
|
except requests.exceptions.ConnectionError:
|
|
455
480
|
new_response = RestApiResponse(
|
|
456
|
-
|
|
481
|
+
None,
|
|
457
482
|
{"detail": "Unable to connect the server. Connection error"}
|
|
458
483
|
)
|
|
459
484
|
else:
|
|
460
485
|
content_type = response.headers.get("Content-Type")
|
|
461
486
|
if content_type == "application/json":
|
|
462
487
|
try:
|
|
463
|
-
new_response = RestApiResponse(
|
|
464
|
-
response.status_code,
|
|
465
|
-
response.json(),
|
|
466
|
-
headers=response.headers,
|
|
467
|
-
)
|
|
488
|
+
new_response = RestApiResponse(response)
|
|
468
489
|
except JSONDecodeError:
|
|
469
490
|
new_response = RestApiResponse(
|
|
470
|
-
|
|
491
|
+
None,
|
|
471
492
|
{
|
|
472
493
|
"detail": "The response is not a JSON: {}".format(
|
|
473
494
|
response.text)
|
|
@@ -475,17 +496,10 @@ class ServerAPIBase(object):
|
|
|
475
496
|
)
|
|
476
497
|
|
|
477
498
|
elif content_type in ("image/jpeg", "image/png"):
|
|
478
|
-
new_response = RestApiResponse(
|
|
479
|
-
response.status_code,
|
|
480
|
-
headers=response.headers,
|
|
481
|
-
content=response.content
|
|
482
|
-
)
|
|
499
|
+
new_response = RestApiResponse(response)
|
|
483
500
|
|
|
484
501
|
else:
|
|
485
|
-
new_response = RestApiResponse(
|
|
486
|
-
response.status_code,
|
|
487
|
-
headers=response.headers,
|
|
488
|
-
)
|
|
502
|
+
new_response = RestApiResponse(response)
|
|
489
503
|
|
|
490
504
|
self.log.debug("Response {}".format(str(new_response)))
|
|
491
505
|
return new_response
|
|
@@ -555,6 +569,119 @@ class ServerAPIBase(object):
|
|
|
555
569
|
def delete(self, entrypoint, **kwargs):
|
|
556
570
|
return self.raw_delete(entrypoint, params=kwargs)
|
|
557
571
|
|
|
572
|
+
def get_event(self, event_id):
|
|
573
|
+
"""Receive full event data by id.
|
|
574
|
+
|
|
575
|
+
Events received using event server do not contain full information. To
|
|
576
|
+
get the full event information is required to receive it explicitly.
|
|
577
|
+
|
|
578
|
+
Args:
|
|
579
|
+
event_id (str): Id of event.
|
|
580
|
+
|
|
581
|
+
Returns:
|
|
582
|
+
Dict[str, Any]: Full event data.
|
|
583
|
+
"""
|
|
584
|
+
|
|
585
|
+
response = self.get("events/{}".format(event_id))
|
|
586
|
+
response.raise_for_status()
|
|
587
|
+
return response.data
|
|
588
|
+
|
|
589
|
+
def update_event(
|
|
590
|
+
self,
|
|
591
|
+
event_id,
|
|
592
|
+
sender=None,
|
|
593
|
+
project_name=None,
|
|
594
|
+
status=None,
|
|
595
|
+
description=None,
|
|
596
|
+
summary=None,
|
|
597
|
+
payload=None
|
|
598
|
+
):
|
|
599
|
+
kwargs = {}
|
|
600
|
+
for key, value in (
|
|
601
|
+
("sender", sender),
|
|
602
|
+
("projectName", project_name),
|
|
603
|
+
("status", status),
|
|
604
|
+
("description", description),
|
|
605
|
+
("summary", summary),
|
|
606
|
+
("payload", payload),
|
|
607
|
+
):
|
|
608
|
+
if value is not None:
|
|
609
|
+
kwargs[key] = value
|
|
610
|
+
response = self.put(
|
|
611
|
+
"events/{}".format(event_id),
|
|
612
|
+
**kwargs
|
|
613
|
+
)
|
|
614
|
+
response.raise_for_status()
|
|
615
|
+
|
|
616
|
+
def dispatch_event(
|
|
617
|
+
self,
|
|
618
|
+
topic,
|
|
619
|
+
sender=None,
|
|
620
|
+
event_hash=None,
|
|
621
|
+
project_name=None,
|
|
622
|
+
username=None,
|
|
623
|
+
dependencies=None,
|
|
624
|
+
description=None,
|
|
625
|
+
summary=None,
|
|
626
|
+
payload=None,
|
|
627
|
+
finished=True,
|
|
628
|
+
store=True,
|
|
629
|
+
):
|
|
630
|
+
if summary is None:
|
|
631
|
+
summary = {}
|
|
632
|
+
if payload is None:
|
|
633
|
+
payload = {}
|
|
634
|
+
event_data = {
|
|
635
|
+
"topic": topic,
|
|
636
|
+
"sender": sender,
|
|
637
|
+
"hash": event_hash,
|
|
638
|
+
"project": project_name,
|
|
639
|
+
"user": username,
|
|
640
|
+
"dependencies": dependencies,
|
|
641
|
+
"description": description,
|
|
642
|
+
"summary": summary,
|
|
643
|
+
"payload": payload,
|
|
644
|
+
"finished": finished,
|
|
645
|
+
"store": store,
|
|
646
|
+
}
|
|
647
|
+
if self.post("events", **event_data):
|
|
648
|
+
self.log.debug("Dispatched event {}".format(topic))
|
|
649
|
+
return True
|
|
650
|
+
self.log.error("Unable to dispatch event {}".format(topic))
|
|
651
|
+
return False
|
|
652
|
+
|
|
653
|
+
def enroll_event_job(
|
|
654
|
+
self,
|
|
655
|
+
source_topic,
|
|
656
|
+
target_topic,
|
|
657
|
+
sender,
|
|
658
|
+
description=None,
|
|
659
|
+
sequential=None
|
|
660
|
+
):
|
|
661
|
+
"""Enroll job based on events.
|
|
662
|
+
|
|
663
|
+
Args:
|
|
664
|
+
source_topic (str): Topic
|
|
665
|
+
"""
|
|
666
|
+
|
|
667
|
+
kwargs = {
|
|
668
|
+
"sourceTopic": source_topic,
|
|
669
|
+
"targetTopic": target_topic,
|
|
670
|
+
"sender": sender,
|
|
671
|
+
}
|
|
672
|
+
if sequential is not None:
|
|
673
|
+
kwargs["sequential"] = sequential
|
|
674
|
+
if description is not None:
|
|
675
|
+
kwargs["description"] = description
|
|
676
|
+
response = self.post("enroll", **kwargs)
|
|
677
|
+
if response.status_code == 204:
|
|
678
|
+
return None
|
|
679
|
+
elif response.status_code >= 400:
|
|
680
|
+
self.log.error(response.text)
|
|
681
|
+
return None
|
|
682
|
+
|
|
683
|
+
return response.data
|
|
684
|
+
|
|
558
685
|
def _download_file(self, url, filepath, chunk_size, progress):
|
|
559
686
|
dst_directory = os.path.dirname(filepath)
|
|
560
687
|
if not os.path.exists(dst_directory):
|
|
@@ -573,7 +700,7 @@ class ServerAPIBase(object):
|
|
|
573
700
|
progress.set_content_size(response.headers["Content-length"])
|
|
574
701
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
575
702
|
f_stream.write(chunk)
|
|
576
|
-
progress.
|
|
703
|
+
progress.add_transferred_chunk(len(chunk))
|
|
577
704
|
|
|
578
705
|
def download_file(self, endpoint, filepath, chunk_size=None, progress=None):
|
|
579
706
|
"""Download file from AYON server.
|
|
@@ -618,7 +745,7 @@ class ServerAPIBase(object):
|
|
|
618
745
|
raise
|
|
619
746
|
|
|
620
747
|
finally:
|
|
621
|
-
progress.
|
|
748
|
+
progress.set_transfer_done()
|
|
622
749
|
|
|
623
750
|
def _upload_file(self, url, filepath, progress):
|
|
624
751
|
kwargs = {}
|
|
@@ -635,7 +762,7 @@ class ServerAPIBase(object):
|
|
|
635
762
|
progress.set_content_size(size)
|
|
636
763
|
response = post_func(url, data=stream, **kwargs)
|
|
637
764
|
response.raise_for_status()
|
|
638
|
-
progress.
|
|
765
|
+
progress.set_transferred_size(size)
|
|
639
766
|
|
|
640
767
|
def upload_file(self, endpoint, filepath, progress=None):
|
|
641
768
|
"""Upload file to server.
|
|
@@ -673,7 +800,7 @@ class ServerAPIBase(object):
|
|
|
673
800
|
raise
|
|
674
801
|
|
|
675
802
|
finally:
|
|
676
|
-
progress.
|
|
803
|
+
progress.set_transfer_done()
|
|
677
804
|
|
|
678
805
|
def trigger_server_restart(self):
|
|
679
806
|
result = self.post("system/restart")
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import socket
|
|
3
|
+
|
|
2
4
|
from .constants import (
|
|
3
5
|
SERVER_URL_ENV_KEY,
|
|
4
6
|
SERVER_TOKEN_ENV_KEY,
|
|
5
7
|
)
|
|
6
8
|
from .server import ServerAPIBase
|
|
9
|
+
from .exceptions import FailedServiceInit
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class ServerAPI(ServerAPIBase):
|
|
@@ -72,6 +75,95 @@ class GlobalContext:
|
|
|
72
75
|
return cls._connection
|
|
73
76
|
|
|
74
77
|
|
|
78
|
+
class ServiceContext:
|
|
79
|
+
"""Helper for services running under server.
|
|
80
|
+
|
|
81
|
+
When service is running from server the process receives information about
|
|
82
|
+
connection from environment variables. This class helps to initialize the
|
|
83
|
+
values without knowing environment variables (that may change over time).
|
|
84
|
+
|
|
85
|
+
All what must be done is to call 'init_service' function/method. The
|
|
86
|
+
arguments are for cases when the service is running in specific environment
|
|
87
|
+
and their values are e.g. loaded from private file or for testing purposes.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
token = None
|
|
91
|
+
server_url = None
|
|
92
|
+
addon_name = None
|
|
93
|
+
addon_version = None
|
|
94
|
+
service_name = None
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def get_value_from_envs(env_keys, value=None):
|
|
98
|
+
if value:
|
|
99
|
+
return value
|
|
100
|
+
|
|
101
|
+
for env_key in env_keys:
|
|
102
|
+
value = os.environ.get(env_key)
|
|
103
|
+
if value:
|
|
104
|
+
break
|
|
105
|
+
return value
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def init_service(
|
|
109
|
+
cls,
|
|
110
|
+
token=None,
|
|
111
|
+
server_url=None,
|
|
112
|
+
addon_name=None,
|
|
113
|
+
addon_version=None,
|
|
114
|
+
service_name=None,
|
|
115
|
+
connect=True
|
|
116
|
+
):
|
|
117
|
+
token = cls.get_value_from_envs(
|
|
118
|
+
("AY_API_KEY", "AYON_TOKEN"),
|
|
119
|
+
token
|
|
120
|
+
)
|
|
121
|
+
server_url = cls.get_value_from_envs(
|
|
122
|
+
("AY_SERVER_URL", "AYON_SERVER_URL"),
|
|
123
|
+
server_url
|
|
124
|
+
)
|
|
125
|
+
if not server_url:
|
|
126
|
+
raise FailedServiceInit("URL to server is not set")
|
|
127
|
+
|
|
128
|
+
if not token:
|
|
129
|
+
raise FailedServiceInit(
|
|
130
|
+
"Token to server {} is not set".format(server_url)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
addon_name = cls.get_value_from_envs(
|
|
134
|
+
("AY_ADDON_NAME", "AYON_ADDON_NAME"),
|
|
135
|
+
addon_name
|
|
136
|
+
)
|
|
137
|
+
addon_version = cls.get_value_from_envs(
|
|
138
|
+
("AY_ADDON_VERSION", "AYON_ADDON_VERSION"),
|
|
139
|
+
addon_version
|
|
140
|
+
)
|
|
141
|
+
service_name = cls.get_value_from_envs(
|
|
142
|
+
("AY_SERVICE_NAME", "AYON_SERVICE_NAME"),
|
|
143
|
+
service_name
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
cls.token = token
|
|
147
|
+
cls.server_url = server_url
|
|
148
|
+
cls.addon_name = addon_name
|
|
149
|
+
cls.addon_version = addon_version
|
|
150
|
+
cls.service_name = service_name or socket.gethostname()
|
|
151
|
+
|
|
152
|
+
# Make sure required environments for ServerAPI are set
|
|
153
|
+
os.environ["AYON_SERVER_URL"] = cls.server_url
|
|
154
|
+
os.environ["AYON_TOKEN"] = cls.token
|
|
155
|
+
|
|
156
|
+
if connect:
|
|
157
|
+
print("Connecting to server \"{}\"".format(server_url))
|
|
158
|
+
con = GlobalContext.get_server_api_connection()
|
|
159
|
+
user = con.get_user()
|
|
160
|
+
print("Logged in as user \"{}\"".format(user["name"]))
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def init_service(*args, **kwargs):
|
|
164
|
+
ServiceContext.init_service(*args, **kwargs)
|
|
165
|
+
|
|
166
|
+
|
|
75
167
|
def get_server_api_connection():
|
|
76
168
|
"""Access to global scope object of ServerAPI.
|
|
77
169
|
|
|
@@ -145,6 +237,26 @@ def delete(*args, **kwargs):
|
|
|
145
237
|
return con.delete(*args, **kwargs)
|
|
146
238
|
|
|
147
239
|
|
|
240
|
+
def get_event(*args, **kwargs):
|
|
241
|
+
con = get_server_api_connection()
|
|
242
|
+
return con.get_event(*args, **kwargs)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def dispatch_event(*args, **kwargs):
|
|
246
|
+
con = get_server_api_connection()
|
|
247
|
+
return con.get_event(*args, **kwargs)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def update_event(*args, **kwargs):
|
|
251
|
+
con = get_server_api_connection()
|
|
252
|
+
return con.update_event(*args, **kwargs)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def enroll_event_job(*args, **kwargs):
|
|
256
|
+
con = get_server_api_connection()
|
|
257
|
+
return con.enroll_event_job(*args, **kwargs)
|
|
258
|
+
|
|
259
|
+
|
|
148
260
|
def download_file(*args, **kwargs):
|
|
149
261
|
con = get_server_api_connection()
|
|
150
262
|
return con.download_file(*args, **kwargs)
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import re
|
|
1
2
|
import datetime
|
|
2
3
|
import uuid
|
|
4
|
+
import string
|
|
3
5
|
try:
|
|
4
6
|
from urlparse import urlparse
|
|
5
7
|
except ImportError:
|
|
6
8
|
from urllib.parse import urlparse
|
|
7
9
|
|
|
8
10
|
import requests
|
|
11
|
+
import unidecode
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
from .exceptions import UrlError
|
|
11
15
|
|
|
12
16
|
REMOVED_VALUE = object()
|
|
17
|
+
SLUGIFY_WHITELIST = string.ascii_letters + string.digits
|
|
18
|
+
SLUGIFY_SEP_WHITELIST = " ,./\\;:!|*^#@~+-_="
|
|
13
19
|
|
|
14
20
|
|
|
15
21
|
def create_entity_id():
|
|
@@ -47,6 +53,59 @@ def entity_data_json_default(value):
|
|
|
47
53
|
)
|
|
48
54
|
|
|
49
55
|
|
|
56
|
+
def slugify_string(
|
|
57
|
+
input_string,
|
|
58
|
+
separator="_",
|
|
59
|
+
slug_whitelist=SLUGIFY_WHITELIST,
|
|
60
|
+
split_chars=SLUGIFY_SEP_WHITELIST,
|
|
61
|
+
min_length=1,
|
|
62
|
+
lower=False,
|
|
63
|
+
make_set=False,
|
|
64
|
+
):
|
|
65
|
+
"""Slugify a text string.
|
|
66
|
+
|
|
67
|
+
This function removes transliterates input string to ASCII, removes
|
|
68
|
+
special characters and use join resulting elements using
|
|
69
|
+
specified separator.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
input_string (str): Input string to slugify
|
|
73
|
+
separator (str): A string used to separate returned elements
|
|
74
|
+
(default: "_")
|
|
75
|
+
slug_whitelist (str): Characters allowed in the output
|
|
76
|
+
(default: ascii letters, digits and the separator)
|
|
77
|
+
split_chars (str): Set of characters used for word splitting
|
|
78
|
+
(there is a sane default)
|
|
79
|
+
lower (bool): Convert to lower-case (default: False)
|
|
80
|
+
make_set (bool): Return "set" object instead of string.
|
|
81
|
+
min_length (int): Minimal length of an element (word).
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Union[str, Set[str]]: Based on 'make_set' value returns slugified
|
|
85
|
+
string.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
tmp_string = unidecode.unidecode(input_string)
|
|
89
|
+
if lower:
|
|
90
|
+
tmp_string = tmp_string.lower()
|
|
91
|
+
|
|
92
|
+
parts = [
|
|
93
|
+
# Remove all characters that are not in whitelist
|
|
94
|
+
re.sub("[^{}]".format(re.escape(slug_whitelist)), "", part)
|
|
95
|
+
# Split text into part by split characters
|
|
96
|
+
for part in re.split("[{}]".format(re.escape(split_chars)), tmp_string)
|
|
97
|
+
]
|
|
98
|
+
# Filter text parts by length
|
|
99
|
+
filtered_parts = [
|
|
100
|
+
part
|
|
101
|
+
for part in parts
|
|
102
|
+
if len(part) >= min_length
|
|
103
|
+
]
|
|
104
|
+
if make_set:
|
|
105
|
+
return set(filtered_parts)
|
|
106
|
+
return separator.join(filtered_parts)
|
|
107
|
+
|
|
108
|
+
|
|
50
109
|
def failed_json_default(value):
|
|
51
110
|
return "< Failed value {} > {}".format(type(value), str(value))
|
|
52
111
|
|
|
@@ -272,8 +331,8 @@ class TransferProgress:
|
|
|
272
331
|
|
|
273
332
|
def __init__(self):
|
|
274
333
|
self._started = False
|
|
275
|
-
self.
|
|
276
|
-
self.
|
|
334
|
+
self._transfer_done = False
|
|
335
|
+
self._transfered = 0
|
|
277
336
|
self._content_size = None
|
|
278
337
|
|
|
279
338
|
self._failed = False
|
|
@@ -298,15 +357,15 @@ class TransferProgress:
|
|
|
298
357
|
raise ValueError("Progress already started")
|
|
299
358
|
self._started = True
|
|
300
359
|
|
|
301
|
-
def
|
|
302
|
-
return self.
|
|
360
|
+
def get_transfer_done(self):
|
|
361
|
+
return self._transfer_done
|
|
303
362
|
|
|
304
|
-
def
|
|
305
|
-
if self.
|
|
363
|
+
def set_transfer_done(self):
|
|
364
|
+
if self._transfer_done:
|
|
306
365
|
raise ValueError("Progress was already marked as done")
|
|
307
366
|
if not self._started:
|
|
308
367
|
raise ValueError("Progress didn't start yet")
|
|
309
|
-
self.
|
|
368
|
+
self._transfer_done = True
|
|
310
369
|
|
|
311
370
|
def get_failed(self):
|
|
312
371
|
return self._failed
|
|
@@ -318,14 +377,14 @@ class TransferProgress:
|
|
|
318
377
|
self._fail_reason = reason
|
|
319
378
|
self._failed = True
|
|
320
379
|
|
|
321
|
-
def
|
|
322
|
-
return self.
|
|
380
|
+
def get_transferred_size(self):
|
|
381
|
+
return self._transfered
|
|
323
382
|
|
|
324
|
-
def
|
|
325
|
-
self.
|
|
383
|
+
def set_transferred_size(self, transfered):
|
|
384
|
+
self._transfered = transfered
|
|
326
385
|
|
|
327
|
-
def
|
|
328
|
-
self.
|
|
386
|
+
def add_transferred_chunk(self, chunk_size):
|
|
387
|
+
self._transfered += chunk_size
|
|
329
388
|
|
|
330
389
|
def get_source_url(self):
|
|
331
390
|
return self._source_url
|
|
@@ -350,17 +409,17 @@ class TransferProgress:
|
|
|
350
409
|
return True
|
|
351
410
|
|
|
352
411
|
@property
|
|
353
|
-
def
|
|
412
|
+
def transfer_progress(self):
|
|
354
413
|
if self._content_size is None:
|
|
355
414
|
return None
|
|
356
|
-
return (self.
|
|
415
|
+
return (self._transfered * 100.0) / float(self._content_size)
|
|
357
416
|
|
|
358
417
|
content_size = property(get_content_size, set_content_size)
|
|
359
418
|
started = property(get_started)
|
|
360
|
-
|
|
419
|
+
transfer_done = property(get_transfer_done)
|
|
361
420
|
failed = property(get_failed)
|
|
362
421
|
fail_reason = property(get_fail_reason)
|
|
363
422
|
source_url = property(get_source_url, set_source_url)
|
|
364
423
|
destination_url = property(get_destination_url, set_destination_url)
|
|
365
424
|
content_size = property(get_content_size, set_content_size)
|
|
366
|
-
|
|
425
|
+
transferred_size = property(get_transferred_size, set_transferred_size)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Package declaring Python API for Ayon server."""
|
|
2
|
-
__version__ = "0.1.
|
|
2
|
+
__version__ = "0.1.8"
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ayon_api"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.8"
|
|
4
4
|
description = "Python api for AYON server"
|
|
5
5
|
authors = ["ynput.io <info@ynput.io>"]
|
|
6
6
|
|
|
7
7
|
[tool.poetry.dependencies]
|
|
8
8
|
requests = "^2.28.1"
|
|
9
9
|
six = "^1.15"
|
|
10
|
+
unidecode = "^1.3"
|
|
10
11
|
appdirs = { git = "https://github.com/ActiveState/appdirs.git", branch = "master" }
|
|
11
12
|
|
|
12
13
|
[tool.poetry.dev-dependencies]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ayon-python-api-0.1.7 → ayon-python-api-0.1.8}/ayon_python_api.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|