shotgun-api3 3.9.0__py2.py3-none-any.whl → 3.9.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shotgun_api3/__init__.py +34 -0
- shotgun_api3/lib/mockgun/mockgun.py +3 -2
- shotgun_api3/lib/mockgun/schema.py +1 -1
- shotgun_api3/py.typed +0 -0
- shotgun_api3/shotgun.py +425 -280
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.2.dist-info}/METADATA +4 -4
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.2.dist-info}/RECORD +10 -9
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.2.dist-info}/WHEEL +0 -0
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.2.dist-info}/licenses/LICENSE +0 -0
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.2.dist-info}/top_level.txt +0 -0
shotgun_api3/shotgun.py
CHANGED
|
@@ -29,6 +29,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
29
29
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
|
+
from __future__ import annotations # Requried for 3.7
|
|
33
|
+
|
|
32
34
|
import base64
|
|
33
35
|
import copy
|
|
34
36
|
import datetime
|
|
@@ -50,6 +52,17 @@ import urllib.parse
|
|
|
50
52
|
import urllib.request
|
|
51
53
|
import uuid # used for attachment upload
|
|
52
54
|
import xml.etree.ElementTree
|
|
55
|
+
from typing import (
|
|
56
|
+
Any,
|
|
57
|
+
BinaryIO,
|
|
58
|
+
Dict,
|
|
59
|
+
Iterable,
|
|
60
|
+
List,
|
|
61
|
+
Optional,
|
|
62
|
+
Tuple,
|
|
63
|
+
TypeVar,
|
|
64
|
+
Union,
|
|
65
|
+
)
|
|
53
66
|
|
|
54
67
|
# Import Error and ResponseError (even though they're unused in this file) since they need
|
|
55
68
|
# to be exposed as part of the API.
|
|
@@ -81,7 +94,35 @@ SHOTGUN_API_DISABLE_ENTITY_OPTIMIZATION = False
|
|
|
81
94
|
|
|
82
95
|
# ----------------------------------------------------------------------------
|
|
83
96
|
# Version
|
|
84
|
-
__version__ = "3.9.
|
|
97
|
+
__version__ = "3.9.2"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# ----------------------------------------------------------------------------
|
|
101
|
+
# Types
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
T = TypeVar("T")
|
|
105
|
+
|
|
106
|
+
if sys.version_info < (3, 9):
|
|
107
|
+
OrderItem = Dict
|
|
108
|
+
GroupingItem = Dict
|
|
109
|
+
BaseEntity = Dict
|
|
110
|
+
else:
|
|
111
|
+
from typing import TypedDict
|
|
112
|
+
|
|
113
|
+
class OrderItem(TypedDict):
|
|
114
|
+
field_name: str
|
|
115
|
+
direction: str
|
|
116
|
+
|
|
117
|
+
class GroupingItem(TypedDict):
|
|
118
|
+
field: str
|
|
119
|
+
type: str
|
|
120
|
+
direction: str
|
|
121
|
+
|
|
122
|
+
class BaseEntity(TypedDict, total=False):
|
|
123
|
+
id: int
|
|
124
|
+
type: str
|
|
125
|
+
|
|
85
126
|
|
|
86
127
|
# ----------------------------------------------------------------------------
|
|
87
128
|
# Errors
|
|
@@ -168,7 +209,7 @@ class ServerCapabilities(object):
|
|
|
168
209
|
the future. Therefore, usage of this class is discouraged.
|
|
169
210
|
"""
|
|
170
211
|
|
|
171
|
-
def __init__(self, host, meta):
|
|
212
|
+
def __init__(self, host: str, meta: Dict[str, Any]) -> None:
|
|
172
213
|
"""
|
|
173
214
|
ServerCapabilities.__init__
|
|
174
215
|
|
|
@@ -181,7 +222,6 @@ class ServerCapabilities(object):
|
|
|
181
222
|
:ivar bool is_dev: ``True`` if server is running a development version of the Shotgun
|
|
182
223
|
codebase.
|
|
183
224
|
"""
|
|
184
|
-
self._ensure_python_version_supported()
|
|
185
225
|
# Server host name
|
|
186
226
|
self.host = host
|
|
187
227
|
self.server_info = meta
|
|
@@ -208,14 +248,7 @@ class ServerCapabilities(object):
|
|
|
208
248
|
self.version = tuple(self.version[:3])
|
|
209
249
|
self._ensure_json_supported()
|
|
210
250
|
|
|
211
|
-
def
|
|
212
|
-
"""
|
|
213
|
-
Checks the if current Python version is supported.
|
|
214
|
-
"""
|
|
215
|
-
if sys.version_info < (3, 7):
|
|
216
|
-
raise ShotgunError("This module requires Python version 3.7 or higher.")
|
|
217
|
-
|
|
218
|
-
def _ensure_support(self, feature, raise_hell=True):
|
|
251
|
+
def _ensure_support(self, feature: Dict[str, Any], raise_hell: bool = True) -> bool:
|
|
219
252
|
"""
|
|
220
253
|
Checks the server version supports a given feature, raises an exception if it does not.
|
|
221
254
|
|
|
@@ -243,13 +276,13 @@ class ServerCapabilities(object):
|
|
|
243
276
|
else:
|
|
244
277
|
return True
|
|
245
278
|
|
|
246
|
-
def _ensure_json_supported(self):
|
|
279
|
+
def _ensure_json_supported(self) -> None:
|
|
247
280
|
"""
|
|
248
281
|
Ensures server has support for JSON API endpoint added in v2.4.0.
|
|
249
282
|
"""
|
|
250
283
|
self._ensure_support({"version": (2, 4, 0), "label": "JSON API"})
|
|
251
284
|
|
|
252
|
-
def ensure_include_archived_projects(self):
|
|
285
|
+
def ensure_include_archived_projects(self) -> None:
|
|
253
286
|
"""
|
|
254
287
|
Ensures server has support for archived Projects feature added in v5.3.14.
|
|
255
288
|
"""
|
|
@@ -257,7 +290,7 @@ class ServerCapabilities(object):
|
|
|
257
290
|
{"version": (5, 3, 14), "label": "include_archived_projects parameter"}
|
|
258
291
|
)
|
|
259
292
|
|
|
260
|
-
def ensure_per_project_customization(self):
|
|
293
|
+
def ensure_per_project_customization(self) -> bool:
|
|
261
294
|
"""
|
|
262
295
|
Ensures server has support for per-project customization feature added in v5.4.4.
|
|
263
296
|
"""
|
|
@@ -265,7 +298,7 @@ class ServerCapabilities(object):
|
|
|
265
298
|
{"version": (5, 4, 4), "label": "project parameter"}, True
|
|
266
299
|
)
|
|
267
300
|
|
|
268
|
-
def ensure_support_for_additional_filter_presets(self):
|
|
301
|
+
def ensure_support_for_additional_filter_presets(self) -> bool:
|
|
269
302
|
"""
|
|
270
303
|
Ensures server has support for additional filter presets feature added in v7.0.0.
|
|
271
304
|
"""
|
|
@@ -273,7 +306,7 @@ class ServerCapabilities(object):
|
|
|
273
306
|
{"version": (7, 0, 0), "label": "additional_filter_presets parameter"}, True
|
|
274
307
|
)
|
|
275
308
|
|
|
276
|
-
def ensure_user_following_support(self):
|
|
309
|
+
def ensure_user_following_support(self) -> bool:
|
|
277
310
|
"""
|
|
278
311
|
Ensures server has support for listing items a user is following, added in v7.0.12.
|
|
279
312
|
"""
|
|
@@ -281,7 +314,7 @@ class ServerCapabilities(object):
|
|
|
281
314
|
{"version": (7, 0, 12), "label": "user_following parameter"}, True
|
|
282
315
|
)
|
|
283
316
|
|
|
284
|
-
def ensure_paging_info_without_counts_support(self):
|
|
317
|
+
def ensure_paging_info_without_counts_support(self) -> bool:
|
|
285
318
|
"""
|
|
286
319
|
Ensures server has support for optimized pagination, added in v7.4.0.
|
|
287
320
|
"""
|
|
@@ -289,7 +322,7 @@ class ServerCapabilities(object):
|
|
|
289
322
|
{"version": (7, 4, 0), "label": "optimized pagination"}, False
|
|
290
323
|
)
|
|
291
324
|
|
|
292
|
-
def ensure_return_image_urls_support(self):
|
|
325
|
+
def ensure_return_image_urls_support(self) -> bool:
|
|
293
326
|
"""
|
|
294
327
|
Ensures server has support for returning thumbnail URLs without additional round-trips, added in v3.3.0.
|
|
295
328
|
"""
|
|
@@ -297,7 +330,7 @@ class ServerCapabilities(object):
|
|
|
297
330
|
{"version": (3, 3, 0), "label": "return thumbnail URLs"}, False
|
|
298
331
|
)
|
|
299
332
|
|
|
300
|
-
def __str__(self):
|
|
333
|
+
def __str__(self) -> str:
|
|
301
334
|
return "ServerCapabilities: host %s, version %s, is_dev %s" % (
|
|
302
335
|
self.host,
|
|
303
336
|
self.version,
|
|
@@ -355,7 +388,7 @@ class _Config(object):
|
|
|
355
388
|
Container for the client configuration.
|
|
356
389
|
"""
|
|
357
390
|
|
|
358
|
-
def __init__(self, sg):
|
|
391
|
+
def __init__(self, sg: "Shotgun"):
|
|
359
392
|
"""
|
|
360
393
|
:param sg: Shotgun connection.
|
|
361
394
|
"""
|
|
@@ -376,41 +409,41 @@ class _Config(object):
|
|
|
376
409
|
# If the optional timeout parameter is given, blocking operations
|
|
377
410
|
# (like connection attempts) will timeout after that many seconds
|
|
378
411
|
# (if it is not given, the global default timeout setting is used)
|
|
379
|
-
self.timeout_secs = None
|
|
412
|
+
self.timeout_secs: Optional[float] = None
|
|
380
413
|
self.api_ver = "api3"
|
|
381
414
|
self.convert_datetimes_to_utc = True
|
|
382
|
-
self._records_per_page = None
|
|
383
|
-
self.api_key = None
|
|
384
|
-
self.script_name = None
|
|
385
|
-
self.user_login = None
|
|
386
|
-
self.user_password = None
|
|
387
|
-
self.auth_token = None
|
|
388
|
-
self.sudo_as_login = None
|
|
415
|
+
self._records_per_page: Optional[int] = None
|
|
416
|
+
self.api_key: Optional[str] = None
|
|
417
|
+
self.script_name: Optional[str] = None
|
|
418
|
+
self.user_login: Optional[str] = None
|
|
419
|
+
self.user_password: Optional[str] = None
|
|
420
|
+
self.auth_token: Optional[str] = None
|
|
421
|
+
self.sudo_as_login: Optional[str] = None
|
|
389
422
|
# Authentication parameters to be folded into final auth_params dict
|
|
390
|
-
self.extra_auth_params = None
|
|
423
|
+
self.extra_auth_params: Optional[Dict[str, Any]] = None
|
|
391
424
|
# uuid as a string
|
|
392
|
-
self.session_uuid = None
|
|
393
|
-
self.scheme = None
|
|
394
|
-
self.server = None
|
|
395
|
-
self.api_path = None
|
|
425
|
+
self.session_uuid: Optional[str] = None
|
|
426
|
+
self.scheme: Optional[str] = None
|
|
427
|
+
self.server: Optional[str] = None
|
|
428
|
+
self.api_path: Optional[str] = None
|
|
396
429
|
# The raw_http_proxy reflects the exact string passed in
|
|
397
430
|
# to the Shotgun constructor. This can be useful if you
|
|
398
431
|
# need to construct a Shotgun API instance based on
|
|
399
432
|
# another Shotgun API instance.
|
|
400
|
-
self.raw_http_proxy = None
|
|
433
|
+
self.raw_http_proxy: Optional[str] = None
|
|
401
434
|
# if a proxy server is being used, the proxy_handler
|
|
402
435
|
# below will contain a urllib2.ProxyHandler instance
|
|
403
436
|
# which can be used whenever a request needs to be made.
|
|
404
|
-
self.proxy_handler = None
|
|
405
|
-
self.proxy_server = None
|
|
437
|
+
self.proxy_handler: Optional["urllib.request.ProxyHandler"] = None
|
|
438
|
+
self.proxy_server: Optional[str] = None
|
|
406
439
|
self.proxy_port = 8080
|
|
407
|
-
self.proxy_user = None
|
|
408
|
-
self.proxy_pass = None
|
|
409
|
-
self.session_token = None
|
|
410
|
-
self.authorization = None
|
|
440
|
+
self.proxy_user: Optional[str] = None
|
|
441
|
+
self.proxy_pass: Optional[str] = None
|
|
442
|
+
self.session_token: Optional[str] = None
|
|
443
|
+
self.authorization: Optional[str] = None
|
|
411
444
|
self.localized = False
|
|
412
445
|
|
|
413
|
-
def set_server_params(self, base_url):
|
|
446
|
+
def set_server_params(self, base_url: str) -> None:
|
|
414
447
|
"""
|
|
415
448
|
Set the different server related fields based on the passed in URL.
|
|
416
449
|
|
|
@@ -432,7 +465,7 @@ class _Config(object):
|
|
|
432
465
|
)
|
|
433
466
|
|
|
434
467
|
@property
|
|
435
|
-
def records_per_page(self):
|
|
468
|
+
def records_per_page(self) -> int:
|
|
436
469
|
"""
|
|
437
470
|
The records per page value from the server.
|
|
438
471
|
"""
|
|
@@ -465,19 +498,19 @@ class Shotgun(object):
|
|
|
465
498
|
|
|
466
499
|
def __init__(
|
|
467
500
|
self,
|
|
468
|
-
base_url,
|
|
469
|
-
script_name=None,
|
|
470
|
-
api_key=None,
|
|
471
|
-
convert_datetimes_to_utc=True,
|
|
472
|
-
http_proxy=None,
|
|
473
|
-
connect=True,
|
|
474
|
-
ca_certs=None,
|
|
475
|
-
login=None,
|
|
476
|
-
password=None,
|
|
477
|
-
sudo_as_login=None,
|
|
478
|
-
session_token=None,
|
|
479
|
-
auth_token=None,
|
|
480
|
-
):
|
|
501
|
+
base_url: str,
|
|
502
|
+
script_name: Optional[str] = None,
|
|
503
|
+
api_key: Optional[str] = None,
|
|
504
|
+
convert_datetimes_to_utc: bool = True,
|
|
505
|
+
http_proxy: Optional[str] = None,
|
|
506
|
+
connect: bool = True,
|
|
507
|
+
ca_certs: Optional[str] = None,
|
|
508
|
+
login: Optional[str] = None,
|
|
509
|
+
password: Optional[str] = None,
|
|
510
|
+
sudo_as_login: Optional[str] = None,
|
|
511
|
+
session_token: Optional[str] = None,
|
|
512
|
+
auth_token: Optional[str] = None,
|
|
513
|
+
) -> None:
|
|
481
514
|
"""
|
|
482
515
|
Initializes a new instance of the Shotgun client.
|
|
483
516
|
|
|
@@ -589,7 +622,7 @@ class Shotgun(object):
|
|
|
589
622
|
"must provide login/password, session_token or script_name/api_key"
|
|
590
623
|
)
|
|
591
624
|
|
|
592
|
-
self.config = _Config(self)
|
|
625
|
+
self.config: _Config = _Config(self)
|
|
593
626
|
self.config.api_key = api_key
|
|
594
627
|
self.config.script_name = script_name
|
|
595
628
|
self.config.user_login = login
|
|
@@ -625,7 +658,7 @@ class Shotgun(object):
|
|
|
625
658
|
):
|
|
626
659
|
SHOTGUN_API_DISABLE_ENTITY_OPTIMIZATION = True
|
|
627
660
|
|
|
628
|
-
self._connection = None
|
|
661
|
+
self._connection: Optional[Http] = None
|
|
629
662
|
|
|
630
663
|
self.__ca_certs = self._get_certs_file(ca_certs)
|
|
631
664
|
|
|
@@ -690,7 +723,7 @@ class Shotgun(object):
|
|
|
690
723
|
# this relies on self.client_caps being set first
|
|
691
724
|
self.reset_user_agent()
|
|
692
725
|
|
|
693
|
-
self._server_caps = None
|
|
726
|
+
self._server_caps: Optional[ServerCapabilities] = None
|
|
694
727
|
# test to ensure the the server supports the json API
|
|
695
728
|
# call to server will only be made once and will raise error
|
|
696
729
|
if connect:
|
|
@@ -704,7 +737,7 @@ class Shotgun(object):
|
|
|
704
737
|
self.config.user_password = None
|
|
705
738
|
self.config.auth_token = None
|
|
706
739
|
|
|
707
|
-
def _split_url(self, base_url):
|
|
740
|
+
def _split_url(self, base_url: str) -> Tuple[Optional[str], Optional[str]]:
|
|
708
741
|
"""
|
|
709
742
|
Extract the hostname:port and username/password/token from base_url
|
|
710
743
|
sent when connect to the API.
|
|
@@ -736,7 +769,7 @@ class Shotgun(object):
|
|
|
736
769
|
# API Functions
|
|
737
770
|
|
|
738
771
|
@property
|
|
739
|
-
def server_info(self):
|
|
772
|
+
def server_info(self) -> Dict[str, Any]:
|
|
740
773
|
"""
|
|
741
774
|
Property containing server information.
|
|
742
775
|
|
|
@@ -754,7 +787,7 @@ class Shotgun(object):
|
|
|
754
787
|
return self.server_caps.server_info
|
|
755
788
|
|
|
756
789
|
@property
|
|
757
|
-
def server_caps(self):
|
|
790
|
+
def server_caps(self) -> ServerCapabilities:
|
|
758
791
|
"""
|
|
759
792
|
Property containing :class:`ServerCapabilities` object.
|
|
760
793
|
|
|
@@ -769,7 +802,7 @@ class Shotgun(object):
|
|
|
769
802
|
self._server_caps = ServerCapabilities(self.config.server, self.info())
|
|
770
803
|
return self._server_caps
|
|
771
804
|
|
|
772
|
-
def connect(self):
|
|
805
|
+
def connect(self) -> None:
|
|
773
806
|
"""
|
|
774
807
|
Connect client to the server if it is not already connected.
|
|
775
808
|
|
|
@@ -780,7 +813,7 @@ class Shotgun(object):
|
|
|
780
813
|
self.info()
|
|
781
814
|
return
|
|
782
815
|
|
|
783
|
-
def close(self):
|
|
816
|
+
def close(self) -> None:
|
|
784
817
|
"""
|
|
785
818
|
Close the current connection to the server.
|
|
786
819
|
|
|
@@ -789,7 +822,7 @@ class Shotgun(object):
|
|
|
789
822
|
self._close_connection()
|
|
790
823
|
return
|
|
791
824
|
|
|
792
|
-
def info(self):
|
|
825
|
+
def info(self) -> Dict[str, Any]:
|
|
793
826
|
"""
|
|
794
827
|
Get API-related metadata from the Shotgun server.
|
|
795
828
|
|
|
@@ -822,15 +855,15 @@ class Shotgun(object):
|
|
|
822
855
|
|
|
823
856
|
def find_one(
|
|
824
857
|
self,
|
|
825
|
-
entity_type,
|
|
826
|
-
filters,
|
|
827
|
-
fields=None,
|
|
828
|
-
order=None,
|
|
829
|
-
filter_operator=None,
|
|
830
|
-
retired_only=False,
|
|
831
|
-
include_archived_projects=True,
|
|
832
|
-
additional_filter_presets=None,
|
|
833
|
-
):
|
|
858
|
+
entity_type: str,
|
|
859
|
+
filters: Union[List, Tuple, Dict[str, Any]],
|
|
860
|
+
fields: Optional[List[str]] = None,
|
|
861
|
+
order: Optional[List[OrderItem]] = None,
|
|
862
|
+
filter_operator: Optional[str] = None,
|
|
863
|
+
retired_only: bool = False,
|
|
864
|
+
include_archived_projects: bool = True,
|
|
865
|
+
additional_filter_presets: Optional[List[Dict[str, Any]]] = None,
|
|
866
|
+
) -> Optional[BaseEntity]:
|
|
834
867
|
"""
|
|
835
868
|
Shortcut for :meth:`~shotgun_api3.Shotgun.find` with ``limit=1`` so it returns a single
|
|
836
869
|
result.
|
|
@@ -845,7 +878,7 @@ class Shotgun(object):
|
|
|
845
878
|
|
|
846
879
|
:param list fields: Optional list of fields to include in each entity record returned.
|
|
847
880
|
Defaults to ``["id"]``.
|
|
848
|
-
:param
|
|
881
|
+
:param list order: Optional list of fields to order the results by. List has the format::
|
|
849
882
|
|
|
850
883
|
[
|
|
851
884
|
{'field_name':'foo', 'direction':'asc'},
|
|
@@ -862,7 +895,7 @@ class Shotgun(object):
|
|
|
862
895
|
same query.
|
|
863
896
|
:param bool include_archived_projects: Optional boolean flag to include entities whose projects
|
|
864
897
|
have been archived. Defaults to ``True``.
|
|
865
|
-
:param additional_filter_presets: Optional list of presets to further filter the result
|
|
898
|
+
:param list additional_filter_presets: Optional list of presets to further filter the result
|
|
866
899
|
set, list has the form::
|
|
867
900
|
|
|
868
901
|
[{
|
|
@@ -902,17 +935,17 @@ class Shotgun(object):
|
|
|
902
935
|
|
|
903
936
|
def find(
|
|
904
937
|
self,
|
|
905
|
-
entity_type,
|
|
906
|
-
filters,
|
|
907
|
-
fields=None,
|
|
908
|
-
order=None,
|
|
909
|
-
filter_operator=None,
|
|
910
|
-
limit=0,
|
|
911
|
-
retired_only=False,
|
|
912
|
-
page=0,
|
|
913
|
-
include_archived_projects=True,
|
|
914
|
-
additional_filter_presets=None,
|
|
915
|
-
):
|
|
938
|
+
entity_type: str,
|
|
939
|
+
filters: Union[List, Tuple, Dict[str, Any]],
|
|
940
|
+
fields: Optional[List[str]] = None,
|
|
941
|
+
order: Optional[List[OrderItem]] = None,
|
|
942
|
+
filter_operator: Optional[str] = None,
|
|
943
|
+
limit: int = 0,
|
|
944
|
+
retired_only: bool = False,
|
|
945
|
+
page: int = 0,
|
|
946
|
+
include_archived_projects: bool = True,
|
|
947
|
+
additional_filter_presets: Optional[List[Dict[str, Any]]] = None,
|
|
948
|
+
) -> List[BaseEntity]:
|
|
916
949
|
"""
|
|
917
950
|
Find entities matching the given filters.
|
|
918
951
|
|
|
@@ -990,7 +1023,7 @@ class Shotgun(object):
|
|
|
990
1023
|
same query.
|
|
991
1024
|
:param bool include_archived_projects: Optional boolean flag to include entities whose projects
|
|
992
1025
|
have been archived. Defaults to ``True``.
|
|
993
|
-
:param additional_filter_presets: Optional list of presets to further filter the result
|
|
1026
|
+
:param list additional_filter_presets: Optional list of presets to further filter the result
|
|
994
1027
|
set, list has the form::
|
|
995
1028
|
|
|
996
1029
|
[{
|
|
@@ -1101,15 +1134,15 @@ class Shotgun(object):
|
|
|
1101
1134
|
|
|
1102
1135
|
def _construct_read_parameters(
|
|
1103
1136
|
self,
|
|
1104
|
-
entity_type,
|
|
1105
|
-
fields,
|
|
1106
|
-
filters,
|
|
1107
|
-
retired_only,
|
|
1108
|
-
order,
|
|
1109
|
-
include_archived_projects,
|
|
1110
|
-
additional_filter_presets,
|
|
1111
|
-
):
|
|
1112
|
-
params = {}
|
|
1137
|
+
entity_type: str,
|
|
1138
|
+
fields: Optional[List[str]],
|
|
1139
|
+
filters: Dict[str, Any],
|
|
1140
|
+
retired_only: bool,
|
|
1141
|
+
order: Optional[List[Dict[str, Any]]],
|
|
1142
|
+
include_archived_projects: bool,
|
|
1143
|
+
additional_filter_presets: Optional[List[Dict[str, Any]]],
|
|
1144
|
+
) -> Dict[str, Any]:
|
|
1145
|
+
params: Dict[str, Any] = {}
|
|
1113
1146
|
params["type"] = entity_type
|
|
1114
1147
|
params["return_fields"] = fields or ["id"]
|
|
1115
1148
|
params["filters"] = filters
|
|
@@ -1139,7 +1172,9 @@ class Shotgun(object):
|
|
|
1139
1172
|
params["sorts"] = sort_list
|
|
1140
1173
|
return params
|
|
1141
1174
|
|
|
1142
|
-
def _add_project_param(
|
|
1175
|
+
def _add_project_param(
|
|
1176
|
+
self, params: Dict[str, Any], project_entity
|
|
1177
|
+
) -> Dict[str, Any]:
|
|
1143
1178
|
|
|
1144
1179
|
if project_entity and self.server_caps.ensure_per_project_customization():
|
|
1145
1180
|
params["project"] = project_entity
|
|
@@ -1147,14 +1182,18 @@ class Shotgun(object):
|
|
|
1147
1182
|
return params
|
|
1148
1183
|
|
|
1149
1184
|
def _translate_update_params(
|
|
1150
|
-
self,
|
|
1151
|
-
|
|
1185
|
+
self,
|
|
1186
|
+
entity_type: str,
|
|
1187
|
+
entity_id: int,
|
|
1188
|
+
data: Dict,
|
|
1189
|
+
multi_entity_update_modes: Optional[Dict],
|
|
1190
|
+
) -> Dict[str, Any]:
|
|
1152
1191
|
global SHOTGUN_API_DISABLE_ENTITY_OPTIMIZATION
|
|
1153
1192
|
|
|
1154
1193
|
def optimize_field(field_dict):
|
|
1155
1194
|
if SHOTGUN_API_DISABLE_ENTITY_OPTIMIZATION:
|
|
1156
1195
|
return field_dict
|
|
1157
|
-
return {k:
|
|
1196
|
+
return {k: _optimize_filter_field(v) for k, v in field_dict.items()}
|
|
1158
1197
|
|
|
1159
1198
|
full_fields = self._dict_to_list(
|
|
1160
1199
|
data,
|
|
@@ -1170,13 +1209,13 @@ class Shotgun(object):
|
|
|
1170
1209
|
|
|
1171
1210
|
def summarize(
|
|
1172
1211
|
self,
|
|
1173
|
-
entity_type,
|
|
1174
|
-
filters,
|
|
1175
|
-
summary_fields,
|
|
1176
|
-
filter_operator=None,
|
|
1177
|
-
grouping=None,
|
|
1178
|
-
include_archived_projects=True,
|
|
1179
|
-
):
|
|
1212
|
+
entity_type: str,
|
|
1213
|
+
filters: Union[List, Dict[str, Any]],
|
|
1214
|
+
summary_fields: List[Dict[str, str]],
|
|
1215
|
+
filter_operator: Optional[str] = None,
|
|
1216
|
+
grouping: Optional[List[GroupingItem]] = None,
|
|
1217
|
+
include_archived_projects: bool = True,
|
|
1218
|
+
) -> Dict[str, Any]:
|
|
1180
1219
|
"""
|
|
1181
1220
|
Summarize field data returned by a query.
|
|
1182
1221
|
|
|
@@ -1376,7 +1415,12 @@ class Shotgun(object):
|
|
|
1376
1415
|
records = self._call_rpc("summarize", params)
|
|
1377
1416
|
return records
|
|
1378
1417
|
|
|
1379
|
-
def create(
|
|
1418
|
+
def create(
|
|
1419
|
+
self,
|
|
1420
|
+
entity_type: str,
|
|
1421
|
+
data: Dict[str, Any],
|
|
1422
|
+
return_fields: Optional[List[str]] = None,
|
|
1423
|
+
) -> Dict[str, Any]:
|
|
1380
1424
|
"""
|
|
1381
1425
|
Create a new entity of the specified ``entity_type``.
|
|
1382
1426
|
|
|
@@ -1459,7 +1503,13 @@ class Shotgun(object):
|
|
|
1459
1503
|
|
|
1460
1504
|
return result
|
|
1461
1505
|
|
|
1462
|
-
def update(
|
|
1506
|
+
def update(
|
|
1507
|
+
self,
|
|
1508
|
+
entity_type: str,
|
|
1509
|
+
entity_id: int,
|
|
1510
|
+
data: Dict[str, Any],
|
|
1511
|
+
multi_entity_update_modes: Optional[Dict[str, Any]] = None,
|
|
1512
|
+
) -> BaseEntity:
|
|
1463
1513
|
"""
|
|
1464
1514
|
Update the specified entity with the supplied data.
|
|
1465
1515
|
|
|
@@ -1538,7 +1588,7 @@ class Shotgun(object):
|
|
|
1538
1588
|
|
|
1539
1589
|
return result
|
|
1540
1590
|
|
|
1541
|
-
def delete(self, entity_type, entity_id):
|
|
1591
|
+
def delete(self, entity_type: str, entity_id: int) -> bool:
|
|
1542
1592
|
"""
|
|
1543
1593
|
Retire the specified entity.
|
|
1544
1594
|
|
|
@@ -1562,7 +1612,7 @@ class Shotgun(object):
|
|
|
1562
1612
|
|
|
1563
1613
|
return self._call_rpc("delete", params)
|
|
1564
1614
|
|
|
1565
|
-
def revive(self, entity_type, entity_id):
|
|
1615
|
+
def revive(self, entity_type: str, entity_id: int) -> bool:
|
|
1566
1616
|
"""
|
|
1567
1617
|
Revive an entity that has previously been deleted.
|
|
1568
1618
|
|
|
@@ -1580,7 +1630,7 @@ class Shotgun(object):
|
|
|
1580
1630
|
|
|
1581
1631
|
return self._call_rpc("revive", params)
|
|
1582
1632
|
|
|
1583
|
-
def batch(self, requests):
|
|
1633
|
+
def batch(self, requests: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
1584
1634
|
"""
|
|
1585
1635
|
Make a batch request of several :meth:`~shotgun_api3.Shotgun.create`,
|
|
1586
1636
|
:meth:`~shotgun_api3.Shotgun.update`, and :meth:`~shotgun_api3.Shotgun.delete` calls.
|
|
@@ -1695,7 +1745,13 @@ class Shotgun(object):
|
|
|
1695
1745
|
records = self._call_rpc("batch", calls)
|
|
1696
1746
|
return self._parse_records(records)
|
|
1697
1747
|
|
|
1698
|
-
def work_schedule_read(
|
|
1748
|
+
def work_schedule_read(
|
|
1749
|
+
self,
|
|
1750
|
+
start_date: str,
|
|
1751
|
+
end_date: str,
|
|
1752
|
+
project: Optional[Dict[str, Any]] = None,
|
|
1753
|
+
user: Optional[Dict[str, Any]] = None,
|
|
1754
|
+
) -> Dict[str, Any]:
|
|
1699
1755
|
"""
|
|
1700
1756
|
Return the work day rules for a given date range.
|
|
1701
1757
|
|
|
@@ -1766,13 +1822,13 @@ class Shotgun(object):
|
|
|
1766
1822
|
|
|
1767
1823
|
def work_schedule_update(
|
|
1768
1824
|
self,
|
|
1769
|
-
date,
|
|
1770
|
-
working,
|
|
1771
|
-
description=None,
|
|
1772
|
-
project=None,
|
|
1773
|
-
user=None,
|
|
1774
|
-
recalculate_field=None,
|
|
1775
|
-
):
|
|
1825
|
+
date: str,
|
|
1826
|
+
working: bool,
|
|
1827
|
+
description: Optional[str] = None,
|
|
1828
|
+
project: Optional[Dict[str, Any]] = None,
|
|
1829
|
+
user: Optional[Dict[str, Any]] = None,
|
|
1830
|
+
recalculate_field: Optional[str] = None,
|
|
1831
|
+
) -> Dict[str, Any]:
|
|
1776
1832
|
"""
|
|
1777
1833
|
Update the work schedule for a given date.
|
|
1778
1834
|
|
|
@@ -1826,7 +1882,30 @@ class Shotgun(object):
|
|
|
1826
1882
|
|
|
1827
1883
|
return self._call_rpc("work_schedule_update", params)
|
|
1828
1884
|
|
|
1829
|
-
def
|
|
1885
|
+
def export_page(self, page_id, format, layout_name=None):
|
|
1886
|
+
"""
|
|
1887
|
+
Export the specified page to the given format.
|
|
1888
|
+
This method allows you to export a page to CSV.
|
|
1889
|
+
Respective layout or page should be marked as API Exportable in the Flow Production Tracking UI.
|
|
1890
|
+
For more information, see documentation_.
|
|
1891
|
+
.. _documentation: https://help.autodesk.com/view/SGSUB/ENU/?guid=SG_Tutorials_tu_export_csv_html#enable-api-export-for-a-page
|
|
1892
|
+
If ``layout_name`` is not passed in, the default layout name will be used.
|
|
1893
|
+
>>> sg.export_page(12345, "csv", layout_name="My Layout")
|
|
1894
|
+
"ID,Name,Status\\n1,Shot 001,ip\\n2, Shot 002,rev\\n"
|
|
1895
|
+
>>> sg.export_page(12345, "csv")
|
|
1896
|
+
"ID,Name,Status\\n1,Shot 001,ip\\n2,Shot 002,rev\\n"
|
|
1897
|
+
:param int page_id: The ID of the page to export.
|
|
1898
|
+
:param str format: The format to export the page to. Supported format is ``"csv"``.
|
|
1899
|
+
:param str layout_name: Optional layout name. This should be the name of the layout seen in the Flow Production Tracking UI.
|
|
1900
|
+
:returns: string containing data of the given page.
|
|
1901
|
+
:rtype: string
|
|
1902
|
+
"""
|
|
1903
|
+
|
|
1904
|
+
params = dict(format=format, page_id=page_id, layout_name=layout_name)
|
|
1905
|
+
|
|
1906
|
+
return self._call_rpc("export_page", params)
|
|
1907
|
+
|
|
1908
|
+
def follow(self, user: Dict[str, Any], entity: Dict[str, Any]) -> Dict[str, Any]:
|
|
1830
1909
|
"""
|
|
1831
1910
|
Add the entity to the user's followed entities.
|
|
1832
1911
|
|
|
@@ -1854,7 +1933,7 @@ class Shotgun(object):
|
|
|
1854
1933
|
|
|
1855
1934
|
return self._call_rpc("follow", params)
|
|
1856
1935
|
|
|
1857
|
-
def unfollow(self, user, entity):
|
|
1936
|
+
def unfollow(self, user: Dict[str, Any], entity: Dict[str, Any]) -> Dict[str, Any]:
|
|
1858
1937
|
"""
|
|
1859
1938
|
Remove entity from the user's followed entities.
|
|
1860
1939
|
|
|
@@ -1881,7 +1960,7 @@ class Shotgun(object):
|
|
|
1881
1960
|
|
|
1882
1961
|
return self._call_rpc("unfollow", params)
|
|
1883
1962
|
|
|
1884
|
-
def followers(self, entity):
|
|
1963
|
+
def followers(self, entity: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
1885
1964
|
"""
|
|
1886
1965
|
Return all followers for an entity.
|
|
1887
1966
|
|
|
@@ -1909,7 +1988,12 @@ class Shotgun(object):
|
|
|
1909
1988
|
|
|
1910
1989
|
return self._call_rpc("followers", params)
|
|
1911
1990
|
|
|
1912
|
-
def following(
|
|
1991
|
+
def following(
|
|
1992
|
+
self,
|
|
1993
|
+
user: Dict[str, Any],
|
|
1994
|
+
project: Optional[Dict[str, Any]] = None,
|
|
1995
|
+
entity_type: Optional[str] = None,
|
|
1996
|
+
) -> List[BaseEntity]:
|
|
1913
1997
|
"""
|
|
1914
1998
|
Return all entity instances a user is following.
|
|
1915
1999
|
|
|
@@ -1940,7 +2024,9 @@ class Shotgun(object):
|
|
|
1940
2024
|
|
|
1941
2025
|
return self._call_rpc("following", params)
|
|
1942
2026
|
|
|
1943
|
-
def schema_entity_read(
|
|
2027
|
+
def schema_entity_read(
|
|
2028
|
+
self, project_entity: Optional[BaseEntity] = None
|
|
2029
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
1944
2030
|
"""
|
|
1945
2031
|
Return all active entity types, their display names, and their visibility.
|
|
1946
2032
|
|
|
@@ -1975,7 +2061,7 @@ class Shotgun(object):
|
|
|
1975
2061
|
The returned display names for this method will be localized when the ``localize`` Shotgun config property is set to ``True``. See :ref:`localization` for more information.
|
|
1976
2062
|
"""
|
|
1977
2063
|
|
|
1978
|
-
params = {}
|
|
2064
|
+
params: Dict[str, Any] = {}
|
|
1979
2065
|
|
|
1980
2066
|
params = self._add_project_param(params, project_entity)
|
|
1981
2067
|
|
|
@@ -1984,7 +2070,9 @@ class Shotgun(object):
|
|
|
1984
2070
|
else:
|
|
1985
2071
|
return self._call_rpc("schema_entity_read", None)
|
|
1986
2072
|
|
|
1987
|
-
def schema_read(
|
|
2073
|
+
def schema_read(
|
|
2074
|
+
self, project_entity: Optional[BaseEntity] = None
|
|
2075
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
1988
2076
|
"""
|
|
1989
2077
|
Get the schema for all fields on all entities.
|
|
1990
2078
|
|
|
@@ -2047,7 +2135,7 @@ class Shotgun(object):
|
|
|
2047
2135
|
The returned display names for this method will be localized when the ``localize`` Shotgun config property is set to ``True``. See :ref:`localization` for more information.
|
|
2048
2136
|
"""
|
|
2049
2137
|
|
|
2050
|
-
params = {}
|
|
2138
|
+
params: Dict[str, Any] = {}
|
|
2051
2139
|
|
|
2052
2140
|
params = self._add_project_param(params, project_entity)
|
|
2053
2141
|
|
|
@@ -2056,7 +2144,12 @@ class Shotgun(object):
|
|
|
2056
2144
|
else:
|
|
2057
2145
|
return self._call_rpc("schema_read", None)
|
|
2058
2146
|
|
|
2059
|
-
def schema_field_read(
|
|
2147
|
+
def schema_field_read(
|
|
2148
|
+
self,
|
|
2149
|
+
entity_type: str,
|
|
2150
|
+
field_name: Optional[str] = None,
|
|
2151
|
+
project_entity: Optional[BaseEntity] = None,
|
|
2152
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
2060
2153
|
"""
|
|
2061
2154
|
Get schema for all fields on the specified entity type or just the field name specified
|
|
2062
2155
|
if provided.
|
|
@@ -2121,8 +2214,12 @@ class Shotgun(object):
|
|
|
2121
2214
|
return self._call_rpc("schema_field_read", params)
|
|
2122
2215
|
|
|
2123
2216
|
def schema_field_create(
|
|
2124
|
-
self,
|
|
2125
|
-
|
|
2217
|
+
self,
|
|
2218
|
+
entity_type: str,
|
|
2219
|
+
data_type: str,
|
|
2220
|
+
display_name: str,
|
|
2221
|
+
properties: Optional[Dict[str, Any]] = None,
|
|
2222
|
+
) -> str:
|
|
2126
2223
|
"""
|
|
2127
2224
|
Create a field for the specified entity type.
|
|
2128
2225
|
|
|
@@ -2160,8 +2257,12 @@ class Shotgun(object):
|
|
|
2160
2257
|
return self._call_rpc("schema_field_create", params)
|
|
2161
2258
|
|
|
2162
2259
|
def schema_field_update(
|
|
2163
|
-
self,
|
|
2164
|
-
|
|
2260
|
+
self,
|
|
2261
|
+
entity_type: str,
|
|
2262
|
+
field_name: str,
|
|
2263
|
+
properties: Dict[str, Any],
|
|
2264
|
+
project_entity: Optional[BaseEntity] = None,
|
|
2265
|
+
) -> bool:
|
|
2165
2266
|
"""
|
|
2166
2267
|
Update the properties for the specified field on an entity.
|
|
2167
2268
|
|
|
@@ -2175,9 +2276,9 @@ class Shotgun(object):
|
|
|
2175
2276
|
>>> sg.schema_field_update("Asset", "sg_test_number", properties)
|
|
2176
2277
|
True
|
|
2177
2278
|
|
|
2178
|
-
:param entity_type: Entity type of field to update.
|
|
2179
|
-
:param field_name: Internal Shotgun name of the field to update.
|
|
2180
|
-
:param properties: Dictionary with key/value pairs where the key is the property to be
|
|
2279
|
+
:param str entity_type: Entity type of field to update.
|
|
2280
|
+
:param str field_name: Internal Shotgun name of the field to update.
|
|
2281
|
+
:param dict properties: Dictionary with key/value pairs where the key is the property to be
|
|
2181
2282
|
updated and the value is the new value.
|
|
2182
2283
|
:param dict project_entity: Optional Project entity specifying which project to modify the
|
|
2183
2284
|
``visible`` property for. If ``visible`` is present in ``properties`` and
|
|
@@ -2202,7 +2303,7 @@ class Shotgun(object):
|
|
|
2202
2303
|
params = self._add_project_param(params, project_entity)
|
|
2203
2304
|
return self._call_rpc("schema_field_update", params)
|
|
2204
2305
|
|
|
2205
|
-
def schema_field_delete(self, entity_type, field_name):
|
|
2306
|
+
def schema_field_delete(self, entity_type: str, field_name: str) -> bool:
|
|
2206
2307
|
"""
|
|
2207
2308
|
Delete the specified field from the entity type.
|
|
2208
2309
|
|
|
@@ -2219,7 +2320,7 @@ class Shotgun(object):
|
|
|
2219
2320
|
|
|
2220
2321
|
return self._call_rpc("schema_field_delete", params)
|
|
2221
2322
|
|
|
2222
|
-
def add_user_agent(self, agent):
|
|
2323
|
+
def add_user_agent(self, agent: str) -> None:
|
|
2223
2324
|
"""
|
|
2224
2325
|
Add agent to the user-agent header.
|
|
2225
2326
|
|
|
@@ -2231,7 +2332,7 @@ class Shotgun(object):
|
|
|
2231
2332
|
"""
|
|
2232
2333
|
self._user_agents.append(agent)
|
|
2233
2334
|
|
|
2234
|
-
def reset_user_agent(self):
|
|
2335
|
+
def reset_user_agent(self) -> None:
|
|
2235
2336
|
"""
|
|
2236
2337
|
Reset user agent to the default value.
|
|
2237
2338
|
|
|
@@ -2251,7 +2352,7 @@ class Shotgun(object):
|
|
|
2251
2352
|
"ssl %s" % (self.client_caps.ssl_version),
|
|
2252
2353
|
]
|
|
2253
2354
|
|
|
2254
|
-
def set_session_uuid(self, session_uuid):
|
|
2355
|
+
def set_session_uuid(self, session_uuid: str) -> None:
|
|
2255
2356
|
"""
|
|
2256
2357
|
Set the browser session_uuid in the current Shotgun API instance.
|
|
2257
2358
|
|
|
@@ -2269,12 +2370,12 @@ class Shotgun(object):
|
|
|
2269
2370
|
|
|
2270
2371
|
def share_thumbnail(
|
|
2271
2372
|
self,
|
|
2272
|
-
entities,
|
|
2273
|
-
thumbnail_path=None,
|
|
2274
|
-
source_entity=None,
|
|
2275
|
-
filmstrip_thumbnail=False,
|
|
2276
|
-
**kwargs,
|
|
2277
|
-
):
|
|
2373
|
+
entities: List[Dict[str, Any]],
|
|
2374
|
+
thumbnail_path: Optional[str] = None,
|
|
2375
|
+
source_entity: Optional[BaseEntity] = None,
|
|
2376
|
+
filmstrip_thumbnail: bool = False,
|
|
2377
|
+
**kwargs: Any,
|
|
2378
|
+
) -> int:
|
|
2278
2379
|
"""
|
|
2279
2380
|
Associate a thumbnail with more than one Shotgun entity.
|
|
2280
2381
|
|
|
@@ -2413,7 +2514,9 @@ class Shotgun(object):
|
|
|
2413
2514
|
|
|
2414
2515
|
return attachment_id
|
|
2415
2516
|
|
|
2416
|
-
def upload_thumbnail(
|
|
2517
|
+
def upload_thumbnail(
|
|
2518
|
+
self, entity_type: str, entity_id: int, path: str, **kwargs: Any
|
|
2519
|
+
) -> int:
|
|
2417
2520
|
"""
|
|
2418
2521
|
Upload a file from a local path and assign it as the thumbnail for the specified entity.
|
|
2419
2522
|
|
|
@@ -2438,12 +2541,15 @@ class Shotgun(object):
|
|
|
2438
2541
|
:param int entity_id: Id of the entity to set the thumbnail for.
|
|
2439
2542
|
:param str path: Full path to the thumbnail file on disk.
|
|
2440
2543
|
:returns: Id of the new attachment
|
|
2544
|
+
:rtype: int
|
|
2441
2545
|
"""
|
|
2442
2546
|
return self.upload(
|
|
2443
2547
|
entity_type, entity_id, path, field_name="thumb_image", **kwargs
|
|
2444
2548
|
)
|
|
2445
2549
|
|
|
2446
|
-
def upload_filmstrip_thumbnail(
|
|
2550
|
+
def upload_filmstrip_thumbnail(
|
|
2551
|
+
self, entity_type: str, entity_id: int, path: str, **kwargs: Any
|
|
2552
|
+
) -> int:
|
|
2447
2553
|
"""
|
|
2448
2554
|
Upload filmstrip thumbnail to specified entity.
|
|
2449
2555
|
|
|
@@ -2494,13 +2600,13 @@ class Shotgun(object):
|
|
|
2494
2600
|
|
|
2495
2601
|
def upload(
|
|
2496
2602
|
self,
|
|
2497
|
-
entity_type,
|
|
2498
|
-
entity_id,
|
|
2499
|
-
path,
|
|
2500
|
-
field_name=None,
|
|
2501
|
-
display_name=None,
|
|
2502
|
-
tag_list=None,
|
|
2503
|
-
):
|
|
2603
|
+
entity_type: str,
|
|
2604
|
+
entity_id: int,
|
|
2605
|
+
path: str,
|
|
2606
|
+
field_name: Optional[str] = None,
|
|
2607
|
+
display_name: Optional[str] = None,
|
|
2608
|
+
tag_list: Optional[str] = None,
|
|
2609
|
+
) -> int:
|
|
2504
2610
|
"""
|
|
2505
2611
|
Upload a file to the specified entity.
|
|
2506
2612
|
|
|
@@ -2583,14 +2689,14 @@ class Shotgun(object):
|
|
|
2583
2689
|
|
|
2584
2690
|
def _upload_to_storage(
|
|
2585
2691
|
self,
|
|
2586
|
-
entity_type,
|
|
2587
|
-
entity_id,
|
|
2588
|
-
path,
|
|
2589
|
-
field_name,
|
|
2590
|
-
display_name,
|
|
2591
|
-
tag_list,
|
|
2592
|
-
is_thumbnail,
|
|
2593
|
-
):
|
|
2692
|
+
entity_type: str,
|
|
2693
|
+
entity_id: int,
|
|
2694
|
+
path: str,
|
|
2695
|
+
field_name: Optional[str],
|
|
2696
|
+
display_name: Optional[str],
|
|
2697
|
+
tag_list: Optional[str],
|
|
2698
|
+
is_thumbnail: bool,
|
|
2699
|
+
) -> int:
|
|
2594
2700
|
"""
|
|
2595
2701
|
Internal function to upload a file to the Cloud storage and link it to the specified entity.
|
|
2596
2702
|
|
|
@@ -2673,14 +2779,14 @@ class Shotgun(object):
|
|
|
2673
2779
|
|
|
2674
2780
|
def _upload_to_sg(
|
|
2675
2781
|
self,
|
|
2676
|
-
entity_type,
|
|
2677
|
-
entity_id,
|
|
2678
|
-
path,
|
|
2679
|
-
field_name,
|
|
2680
|
-
display_name,
|
|
2681
|
-
tag_list,
|
|
2682
|
-
is_thumbnail,
|
|
2683
|
-
):
|
|
2782
|
+
entity_type: str,
|
|
2783
|
+
entity_id: int,
|
|
2784
|
+
path: str,
|
|
2785
|
+
field_name: Optional[str],
|
|
2786
|
+
display_name: Optional[str],
|
|
2787
|
+
tag_list: Optional[str],
|
|
2788
|
+
is_thumbnail: bool,
|
|
2789
|
+
) -> int:
|
|
2684
2790
|
"""
|
|
2685
2791
|
Internal function to upload a file to Shotgun and link it to the specified entity.
|
|
2686
2792
|
|
|
@@ -2752,7 +2858,9 @@ class Shotgun(object):
|
|
|
2752
2858
|
attachment_id = int(result.split(":", 2)[1].split("\n", 1)[0])
|
|
2753
2859
|
return attachment_id
|
|
2754
2860
|
|
|
2755
|
-
def _get_attachment_upload_info(
|
|
2861
|
+
def _get_attachment_upload_info(
|
|
2862
|
+
self, is_thumbnail: bool, filename: str, is_multipart_upload: bool
|
|
2863
|
+
) -> Dict[str, Any]:
|
|
2756
2864
|
"""
|
|
2757
2865
|
Internal function to get the information needed to upload a file to Cloud storage.
|
|
2758
2866
|
|
|
@@ -2799,7 +2907,12 @@ class Shotgun(object):
|
|
|
2799
2907
|
"upload_info": upload_info,
|
|
2800
2908
|
}
|
|
2801
2909
|
|
|
2802
|
-
def download_attachment(
|
|
2910
|
+
def download_attachment(
|
|
2911
|
+
self,
|
|
2912
|
+
attachment: Union[Dict[str, Any], bool] = False,
|
|
2913
|
+
file_path: Optional[str] = None,
|
|
2914
|
+
attachment_id: Optional[int] = None,
|
|
2915
|
+
) -> Union[str, bytes, None]:
|
|
2803
2916
|
"""
|
|
2804
2917
|
Download the file associated with a Shotgun Attachment.
|
|
2805
2918
|
|
|
@@ -2915,7 +3028,7 @@ class Shotgun(object):
|
|
|
2915
3028
|
else:
|
|
2916
3029
|
return attachment
|
|
2917
3030
|
|
|
2918
|
-
def get_auth_cookie_handler(self):
|
|
3031
|
+
def get_auth_cookie_handler(self) -> urllib.request.HTTPCookieProcessor:
|
|
2919
3032
|
"""
|
|
2920
3033
|
Return an urllib cookie handler containing a cookie for FPTR
|
|
2921
3034
|
authentication.
|
|
@@ -2947,7 +3060,9 @@ class Shotgun(object):
|
|
|
2947
3060
|
cj.set_cookie(c)
|
|
2948
3061
|
return urllib.request.HTTPCookieProcessor(cj)
|
|
2949
3062
|
|
|
2950
|
-
def get_attachment_download_url(
|
|
3063
|
+
def get_attachment_download_url(
|
|
3064
|
+
self, attachment: Optional[Union[int, dict[str, Any]]]
|
|
3065
|
+
) -> str:
|
|
2951
3066
|
"""
|
|
2952
3067
|
Return the URL for downloading provided Attachment.
|
|
2953
3068
|
|
|
@@ -3005,7 +3120,9 @@ class Shotgun(object):
|
|
|
3005
3120
|
)
|
|
3006
3121
|
return url
|
|
3007
3122
|
|
|
3008
|
-
def authenticate_human_user(
|
|
3123
|
+
def authenticate_human_user(
|
|
3124
|
+
self, user_login: str, user_password: str, auth_token: Optional[str] = None
|
|
3125
|
+
) -> Union[Dict[str, Any], None]:
|
|
3009
3126
|
"""
|
|
3010
3127
|
Authenticate Shotgun HumanUser.
|
|
3011
3128
|
|
|
@@ -3064,7 +3181,9 @@ class Shotgun(object):
|
|
|
3064
3181
|
self.config.auth_token = original_auth_token
|
|
3065
3182
|
raise
|
|
3066
3183
|
|
|
3067
|
-
def update_project_last_accessed(
|
|
3184
|
+
def update_project_last_accessed(
|
|
3185
|
+
self, project: Dict[str, Any], user: Optional[Dict[str, Any]] = None
|
|
3186
|
+
) -> None:
|
|
3068
3187
|
"""
|
|
3069
3188
|
Update a Project's ``last_accessed_by_current_user`` field to the current timestamp.
|
|
3070
3189
|
|
|
@@ -3110,7 +3229,9 @@ class Shotgun(object):
|
|
|
3110
3229
|
record = self._call_rpc("update_project_last_accessed_by_current_user", params)
|
|
3111
3230
|
self._parse_records(record)[0]
|
|
3112
3231
|
|
|
3113
|
-
def note_thread_read(
|
|
3232
|
+
def note_thread_read(
|
|
3233
|
+
self, note_id: int, entity_fields: Optional[Dict[str, Any]] = None
|
|
3234
|
+
) -> List[Dict[str, Any]]:
|
|
3114
3235
|
"""
|
|
3115
3236
|
Return the full conversation for a given note, including Replies and Attachments.
|
|
3116
3237
|
|
|
@@ -3185,7 +3306,13 @@ class Shotgun(object):
|
|
|
3185
3306
|
result = self._parse_records(record)
|
|
3186
3307
|
return result
|
|
3187
3308
|
|
|
3188
|
-
def text_search(
|
|
3309
|
+
def text_search(
|
|
3310
|
+
self,
|
|
3311
|
+
text: str,
|
|
3312
|
+
entity_types: Dict[str, Any],
|
|
3313
|
+
project_ids: Optional[List] = None,
|
|
3314
|
+
limit: Optional[int] = None,
|
|
3315
|
+
) -> Dict[str, Any]:
|
|
3189
3316
|
"""
|
|
3190
3317
|
Search across the specified entity types for the given text.
|
|
3191
3318
|
|
|
@@ -3279,13 +3406,13 @@ class Shotgun(object):
|
|
|
3279
3406
|
|
|
3280
3407
|
def activity_stream_read(
|
|
3281
3408
|
self,
|
|
3282
|
-
entity_type,
|
|
3283
|
-
entity_id,
|
|
3284
|
-
entity_fields=None,
|
|
3285
|
-
min_id=None,
|
|
3286
|
-
max_id=None,
|
|
3287
|
-
limit=None,
|
|
3288
|
-
):
|
|
3409
|
+
entity_type: str,
|
|
3410
|
+
entity_id: int,
|
|
3411
|
+
entity_fields: Optional[Dict[str, Any]] = None,
|
|
3412
|
+
min_id: Optional[int] = None,
|
|
3413
|
+
max_id: Optional[int] = None,
|
|
3414
|
+
limit: Optional[int] = None,
|
|
3415
|
+
) -> Dict[str, Any]:
|
|
3289
3416
|
"""
|
|
3290
3417
|
Retrieve activity stream data from Shotgun.
|
|
3291
3418
|
|
|
@@ -3375,7 +3502,7 @@ class Shotgun(object):
|
|
|
3375
3502
|
result = self._parse_records(record)[0]
|
|
3376
3503
|
return result
|
|
3377
3504
|
|
|
3378
|
-
def nav_expand(self, path, seed_entity_field=None, entity_fields=None):
|
|
3505
|
+
def nav_expand(self, path: str, seed_entity_field=None, entity_fields=None):
|
|
3379
3506
|
"""
|
|
3380
3507
|
Expand the navigation hierarchy for the supplied path.
|
|
3381
3508
|
|
|
@@ -3395,7 +3522,9 @@ class Shotgun(object):
|
|
|
3395
3522
|
},
|
|
3396
3523
|
)
|
|
3397
3524
|
|
|
3398
|
-
def nav_search_string(
|
|
3525
|
+
def nav_search_string(
|
|
3526
|
+
self, root_path: str, search_string: str, seed_entity_field=None
|
|
3527
|
+
):
|
|
3399
3528
|
"""
|
|
3400
3529
|
Search function adapted to work with the navigation hierarchy.
|
|
3401
3530
|
|
|
@@ -3414,7 +3543,12 @@ class Shotgun(object):
|
|
|
3414
3543
|
},
|
|
3415
3544
|
)
|
|
3416
3545
|
|
|
3417
|
-
def nav_search_entity(
|
|
3546
|
+
def nav_search_entity(
|
|
3547
|
+
self,
|
|
3548
|
+
root_path: str,
|
|
3549
|
+
entity: Dict[str, Any],
|
|
3550
|
+
seed_entity_field: Optional[Dict[str, Any]] = None,
|
|
3551
|
+
):
|
|
3418
3552
|
"""
|
|
3419
3553
|
Search function adapted to work with the navigation hierarchy.
|
|
3420
3554
|
|
|
@@ -3434,7 +3568,7 @@ class Shotgun(object):
|
|
|
3434
3568
|
},
|
|
3435
3569
|
)
|
|
3436
3570
|
|
|
3437
|
-
def get_session_token(self):
|
|
3571
|
+
def get_session_token(self) -> str:
|
|
3438
3572
|
"""
|
|
3439
3573
|
Get the session token associated with the current session.
|
|
3440
3574
|
|
|
@@ -3458,7 +3592,7 @@ class Shotgun(object):
|
|
|
3458
3592
|
|
|
3459
3593
|
return session_token
|
|
3460
3594
|
|
|
3461
|
-
def preferences_read(self, prefs=None):
|
|
3595
|
+
def preferences_read(self, prefs: Optional[List] = None) -> Dict[str, Any]:
|
|
3462
3596
|
"""
|
|
3463
3597
|
Get a subset of the site preferences.
|
|
3464
3598
|
|
|
@@ -3481,7 +3615,7 @@ class Shotgun(object):
|
|
|
3481
3615
|
|
|
3482
3616
|
return self._call_rpc("preferences_read", {"prefs": prefs})
|
|
3483
3617
|
|
|
3484
|
-
def user_subscriptions_read(self):
|
|
3618
|
+
def user_subscriptions_read(self) -> List:
|
|
3485
3619
|
"""
|
|
3486
3620
|
Get the list of user subscriptions.
|
|
3487
3621
|
|
|
@@ -3493,8 +3627,9 @@ class Shotgun(object):
|
|
|
3493
3627
|
|
|
3494
3628
|
return self._call_rpc("user_subscriptions_read", None)
|
|
3495
3629
|
|
|
3496
|
-
def user_subscriptions_create(
|
|
3497
|
-
|
|
3630
|
+
def user_subscriptions_create(
|
|
3631
|
+
self, users: List[Dict[str, Union[str, List[str], None]]]
|
|
3632
|
+
) -> bool:
|
|
3498
3633
|
"""
|
|
3499
3634
|
Assign subscriptions to users.
|
|
3500
3635
|
|
|
@@ -3515,7 +3650,7 @@ class Shotgun(object):
|
|
|
3515
3650
|
|
|
3516
3651
|
return response.get("status") == "success"
|
|
3517
3652
|
|
|
3518
|
-
def _build_opener(self, handler):
|
|
3653
|
+
def _build_opener(self, handler) -> urllib.request.OpenerDirector:
|
|
3519
3654
|
"""
|
|
3520
3655
|
Build urllib2 opener with appropriate proxy handler.
|
|
3521
3656
|
"""
|
|
@@ -3616,7 +3751,13 @@ class Shotgun(object):
|
|
|
3616
3751
|
# ========================================================================
|
|
3617
3752
|
# RPC Functions
|
|
3618
3753
|
|
|
3619
|
-
def _call_rpc(
|
|
3754
|
+
def _call_rpc(
|
|
3755
|
+
self,
|
|
3756
|
+
method: str,
|
|
3757
|
+
params: Any,
|
|
3758
|
+
include_auth_params: bool = True,
|
|
3759
|
+
first: bool = False,
|
|
3760
|
+
) -> Any:
|
|
3620
3761
|
"""
|
|
3621
3762
|
Call the specified method on the Shotgun Server sending the supplied payload.
|
|
3622
3763
|
"""
|
|
@@ -3680,7 +3821,7 @@ class Shotgun(object):
|
|
|
3680
3821
|
return results[0]
|
|
3681
3822
|
return results
|
|
3682
3823
|
|
|
3683
|
-
def _auth_params(self):
|
|
3824
|
+
def _auth_params(self) -> Dict[str, Any]:
|
|
3684
3825
|
"""
|
|
3685
3826
|
Return a dictionary of the authentication parameters being used.
|
|
3686
3827
|
"""
|
|
@@ -3735,7 +3876,7 @@ class Shotgun(object):
|
|
|
3735
3876
|
|
|
3736
3877
|
return auth_params
|
|
3737
3878
|
|
|
3738
|
-
def _sanitize_auth_params(self, params):
|
|
3879
|
+
def _sanitize_auth_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
3739
3880
|
"""
|
|
3740
3881
|
Given an authentication parameter dictionary, sanitize any sensitive
|
|
3741
3882
|
information and return the sanitized dict copy.
|
|
@@ -3746,7 +3887,9 @@ class Shotgun(object):
|
|
|
3746
3887
|
sanitized_params[k] = "********"
|
|
3747
3888
|
return sanitized_params
|
|
3748
3889
|
|
|
3749
|
-
def _build_payload(
|
|
3890
|
+
def _build_payload(
|
|
3891
|
+
self, method: str, params, include_auth_params: bool = True
|
|
3892
|
+
) -> Dict[str, Any]:
|
|
3750
3893
|
"""
|
|
3751
3894
|
Build the payload to be send to the rpc endpoint.
|
|
3752
3895
|
"""
|
|
@@ -3764,7 +3907,7 @@ class Shotgun(object):
|
|
|
3764
3907
|
|
|
3765
3908
|
return {"method_name": method, "params": call_params}
|
|
3766
3909
|
|
|
3767
|
-
def _encode_payload(self, payload):
|
|
3910
|
+
def _encode_payload(self, payload) -> bytes:
|
|
3768
3911
|
"""
|
|
3769
3912
|
Encode the payload to a string to be passed to the rpc endpoint.
|
|
3770
3913
|
|
|
@@ -3775,7 +3918,9 @@ class Shotgun(object):
|
|
|
3775
3918
|
|
|
3776
3919
|
return json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
|
3777
3920
|
|
|
3778
|
-
def _make_call(
|
|
3921
|
+
def _make_call(
|
|
3922
|
+
self, verb: str, path: str, body, headers: Optional[Dict[str, Any]]
|
|
3923
|
+
) -> Tuple[Tuple[int, str], Dict[str, Any], str]:
|
|
3779
3924
|
"""
|
|
3780
3925
|
Make an HTTP call to the server.
|
|
3781
3926
|
|
|
@@ -3825,7 +3970,9 @@ class Shotgun(object):
|
|
|
3825
3970
|
)
|
|
3826
3971
|
time.sleep(rpc_attempt_interval)
|
|
3827
3972
|
|
|
3828
|
-
def _http_request(
|
|
3973
|
+
def _http_request(
|
|
3974
|
+
self, verb: str, path: str, body, headers: Dict[str, Any]
|
|
3975
|
+
) -> Tuple[Tuple[int, str], Dict[str, Any], str]:
|
|
3829
3976
|
"""
|
|
3830
3977
|
Make the actual HTTP request.
|
|
3831
3978
|
"""
|
|
@@ -3849,7 +3996,9 @@ class Shotgun(object):
|
|
|
3849
3996
|
|
|
3850
3997
|
return (http_status, resp_headers, resp_body)
|
|
3851
3998
|
|
|
3852
|
-
def _make_upload_request(
|
|
3999
|
+
def _make_upload_request(
|
|
4000
|
+
self, request, opener: "urllib.request.OpenerDirector"
|
|
4001
|
+
) -> "urllib.request._UrlopenRet":
|
|
3853
4002
|
"""
|
|
3854
4003
|
Open the given request object, return the
|
|
3855
4004
|
response, raises URLError on protocol errors.
|
|
@@ -3861,7 +4010,7 @@ class Shotgun(object):
|
|
|
3861
4010
|
raise
|
|
3862
4011
|
return result
|
|
3863
4012
|
|
|
3864
|
-
def _parse_http_status(self, status):
|
|
4013
|
+
def _parse_http_status(self, status: Tuple) -> None:
|
|
3865
4014
|
"""
|
|
3866
4015
|
Parse the status returned from the http request.
|
|
3867
4016
|
|
|
@@ -3879,7 +4028,9 @@ class Shotgun(object):
|
|
|
3879
4028
|
|
|
3880
4029
|
return
|
|
3881
4030
|
|
|
3882
|
-
def _decode_response(
|
|
4031
|
+
def _decode_response(
|
|
4032
|
+
self, headers: Dict[str, Any], body: str
|
|
4033
|
+
) -> Union[str, Dict[str, Any]]:
|
|
3883
4034
|
"""
|
|
3884
4035
|
Decode the response from the server from the wire format to
|
|
3885
4036
|
a python data structure.
|
|
@@ -3900,7 +4051,7 @@ class Shotgun(object):
|
|
|
3900
4051
|
return self._json_loads(body)
|
|
3901
4052
|
return body
|
|
3902
4053
|
|
|
3903
|
-
def _json_loads(self, body):
|
|
4054
|
+
def _json_loads(self, body: str) -> Any:
|
|
3904
4055
|
return json.loads(body)
|
|
3905
4056
|
|
|
3906
4057
|
def _response_errors(self, sg_response):
|
|
@@ -3949,7 +4100,7 @@ class Shotgun(object):
|
|
|
3949
4100
|
raise Fault(sg_response.get("message", "Unknown Error"))
|
|
3950
4101
|
return
|
|
3951
4102
|
|
|
3952
|
-
def _visit_data(self, data, visitor):
|
|
4103
|
+
def _visit_data(self, data: T, visitor) -> T:
|
|
3953
4104
|
"""
|
|
3954
4105
|
Walk the data (simple python types) and call the visitor.
|
|
3955
4106
|
"""
|
|
@@ -3959,17 +4110,17 @@ class Shotgun(object):
|
|
|
3959
4110
|
|
|
3960
4111
|
recursive = self._visit_data
|
|
3961
4112
|
if isinstance(data, list):
|
|
3962
|
-
return [recursive(i, visitor) for i in data]
|
|
4113
|
+
return [recursive(i, visitor) for i in data] # type: ignore[return-value]
|
|
3963
4114
|
|
|
3964
4115
|
if isinstance(data, tuple):
|
|
3965
|
-
return tuple(recursive(i, visitor) for i in data)
|
|
4116
|
+
return tuple(recursive(i, visitor) for i in data) # type: ignore[return-value]
|
|
3966
4117
|
|
|
3967
4118
|
if isinstance(data, dict):
|
|
3968
|
-
return dict((k, recursive(v, visitor)) for k, v in data.items())
|
|
4119
|
+
return dict((k, recursive(v, visitor)) for k, v in data.items()) # type: ignore[return-value]
|
|
3969
4120
|
|
|
3970
4121
|
return visitor(data)
|
|
3971
4122
|
|
|
3972
|
-
def _transform_outbound(self, data):
|
|
4123
|
+
def _transform_outbound(self, data: T) -> T:
|
|
3973
4124
|
"""
|
|
3974
4125
|
Transform data types or values before they are sent by the client.
|
|
3975
4126
|
|
|
@@ -4016,7 +4167,7 @@ class Shotgun(object):
|
|
|
4016
4167
|
|
|
4017
4168
|
return self._visit_data(data, _outbound_visitor)
|
|
4018
4169
|
|
|
4019
|
-
def _transform_inbound(self, data):
|
|
4170
|
+
def _transform_inbound(self, data: T) -> T:
|
|
4020
4171
|
"""
|
|
4021
4172
|
Transforms data types or values after they are received from the server.
|
|
4022
4173
|
"""
|
|
@@ -4052,7 +4203,7 @@ class Shotgun(object):
|
|
|
4052
4203
|
# ========================================================================
|
|
4053
4204
|
# Connection Functions
|
|
4054
4205
|
|
|
4055
|
-
def _get_connection(self):
|
|
4206
|
+
def _get_connection(self) -> Http:
|
|
4056
4207
|
"""
|
|
4057
4208
|
Return the current connection or creates a new connection to the current server.
|
|
4058
4209
|
"""
|
|
@@ -4081,7 +4232,7 @@ class Shotgun(object):
|
|
|
4081
4232
|
|
|
4082
4233
|
return self._connection
|
|
4083
4234
|
|
|
4084
|
-
def _close_connection(self):
|
|
4235
|
+
def _close_connection(self) -> None:
|
|
4085
4236
|
"""
|
|
4086
4237
|
Close the current connection.
|
|
4087
4238
|
"""
|
|
@@ -4100,7 +4251,7 @@ class Shotgun(object):
|
|
|
4100
4251
|
# ========================================================================
|
|
4101
4252
|
# Utility
|
|
4102
4253
|
|
|
4103
|
-
def _parse_records(self, records):
|
|
4254
|
+
def _parse_records(self, records: List) -> List:
|
|
4104
4255
|
"""
|
|
4105
4256
|
Parse 'records' returned from the api to do local modifications:
|
|
4106
4257
|
|
|
@@ -4156,7 +4307,7 @@ class Shotgun(object):
|
|
|
4156
4307
|
|
|
4157
4308
|
return records
|
|
4158
4309
|
|
|
4159
|
-
def _build_thumb_url(self, entity_type, entity_id):
|
|
4310
|
+
def _build_thumb_url(self, entity_type: str, entity_id: int) -> str:
|
|
4160
4311
|
"""
|
|
4161
4312
|
Return the URL for the thumbnail of an entity given the entity type and the entity id.
|
|
4162
4313
|
|
|
@@ -4204,8 +4355,12 @@ class Shotgun(object):
|
|
|
4204
4355
|
raise RuntimeError("Unknown code %s %s" % (code, thumb_url))
|
|
4205
4356
|
|
|
4206
4357
|
def _dict_to_list(
|
|
4207
|
-
self,
|
|
4208
|
-
|
|
4358
|
+
self,
|
|
4359
|
+
d: Optional[Dict[str, Any]],
|
|
4360
|
+
key_name: str = "field_name",
|
|
4361
|
+
value_name: str = "value",
|
|
4362
|
+
extra_data=None,
|
|
4363
|
+
) -> List[Dict[str, Any]]:
|
|
4209
4364
|
"""
|
|
4210
4365
|
Utility function to convert a dict into a list dicts using the key_name and value_name keys.
|
|
4211
4366
|
|
|
@@ -4222,7 +4377,9 @@ class Shotgun(object):
|
|
|
4222
4377
|
ret.append(d)
|
|
4223
4378
|
return ret
|
|
4224
4379
|
|
|
4225
|
-
def _dict_to_extra_data(
|
|
4380
|
+
def _dict_to_extra_data(
|
|
4381
|
+
self, d: Optional[Dict[str, Any]], key_name="value"
|
|
4382
|
+
) -> Dict[str, Any]:
|
|
4226
4383
|
"""
|
|
4227
4384
|
Utility function to convert a dict into a dict compatible with the extra_data arg
|
|
4228
4385
|
of _dict_to_list.
|
|
@@ -4231,7 +4388,7 @@ class Shotgun(object):
|
|
|
4231
4388
|
"""
|
|
4232
4389
|
return dict([(k, {key_name: v}) for (k, v) in (d or {}).items()])
|
|
4233
4390
|
|
|
4234
|
-
def _upload_file_to_storage(self, path, storage_url):
|
|
4391
|
+
def _upload_file_to_storage(self, path: str, storage_url: str) -> None:
|
|
4235
4392
|
"""
|
|
4236
4393
|
Internal function to upload an entire file to the Cloud storage.
|
|
4237
4394
|
|
|
@@ -4251,7 +4408,9 @@ class Shotgun(object):
|
|
|
4251
4408
|
|
|
4252
4409
|
LOG.debug("File uploaded to Cloud storage: %s", filename)
|
|
4253
4410
|
|
|
4254
|
-
def _multipart_upload_file_to_storage(
|
|
4411
|
+
def _multipart_upload_file_to_storage(
|
|
4412
|
+
self, path: str, upload_info: Dict[str, Any]
|
|
4413
|
+
) -> None:
|
|
4255
4414
|
"""
|
|
4256
4415
|
Internal function to upload a file to the Cloud storage in multiple parts.
|
|
4257
4416
|
|
|
@@ -4293,7 +4452,9 @@ class Shotgun(object):
|
|
|
4293
4452
|
|
|
4294
4453
|
LOG.debug("File uploaded in multiple parts to Cloud storage: %s", path)
|
|
4295
4454
|
|
|
4296
|
-
def _get_upload_part_link(
|
|
4455
|
+
def _get_upload_part_link(
|
|
4456
|
+
self, upload_info: Dict[str, Any], filename: str, part_number: int
|
|
4457
|
+
) -> str:
|
|
4297
4458
|
"""
|
|
4298
4459
|
Internal function to get the url to upload the next part of a file to the
|
|
4299
4460
|
Cloud storage, in a multi-part upload process.
|
|
@@ -4333,7 +4494,9 @@ class Shotgun(object):
|
|
|
4333
4494
|
LOG.debug("Got next upload link from server for multipart upload.")
|
|
4334
4495
|
return result.split("\n", 2)[1]
|
|
4335
4496
|
|
|
4336
|
-
def _upload_data_to_storage(
|
|
4497
|
+
def _upload_data_to_storage(
|
|
4498
|
+
self, data: BinaryIO, content_type: str, size: int, storage_url: str
|
|
4499
|
+
) -> str:
|
|
4337
4500
|
"""
|
|
4338
4501
|
Internal function to upload data to Cloud storage.
|
|
4339
4502
|
|
|
@@ -4382,19 +4545,21 @@ class Shotgun(object):
|
|
|
4382
4545
|
else:
|
|
4383
4546
|
break
|
|
4384
4547
|
else:
|
|
4385
|
-
raise ShotgunError("Max
|
|
4548
|
+
raise ShotgunError("Max attempts limit reached.")
|
|
4386
4549
|
|
|
4387
4550
|
etag = result.info()["Etag"]
|
|
4388
4551
|
LOG.debug("Part upload completed successfully.")
|
|
4389
4552
|
return etag
|
|
4390
4553
|
|
|
4391
|
-
def _complete_multipart_upload(
|
|
4554
|
+
def _complete_multipart_upload(
|
|
4555
|
+
self, upload_info: Dict[str, Any], filename: str, etags: Iterable[str]
|
|
4556
|
+
) -> None:
|
|
4392
4557
|
"""
|
|
4393
4558
|
Internal function to complete a multi-part upload to the Cloud storage.
|
|
4394
4559
|
|
|
4395
4560
|
:param dict upload_info: Contains details received from the server, about the upload.
|
|
4396
4561
|
:param str filename: Name of the file for which we want to complete the upload.
|
|
4397
|
-
:param
|
|
4562
|
+
:param tuple etags: Contains the etag of each uploaded file part.
|
|
4398
4563
|
"""
|
|
4399
4564
|
|
|
4400
4565
|
params = {
|
|
@@ -4421,7 +4586,9 @@ class Shotgun(object):
|
|
|
4421
4586
|
if not result.startswith("1"):
|
|
4422
4587
|
raise ShotgunError("Unable get upload part link: %s" % result)
|
|
4423
4588
|
|
|
4424
|
-
def _requires_direct_s3_upload(
|
|
4589
|
+
def _requires_direct_s3_upload(
|
|
4590
|
+
self, entity_type: str, field_name: Optional[str]
|
|
4591
|
+
) -> bool:
|
|
4425
4592
|
"""
|
|
4426
4593
|
Internal function that determines if an entity_type + field_name combination
|
|
4427
4594
|
should be uploaded to cloud storage.
|
|
@@ -4462,7 +4629,7 @@ class Shotgun(object):
|
|
|
4462
4629
|
else:
|
|
4463
4630
|
return False
|
|
4464
4631
|
|
|
4465
|
-
def _send_form(self, url, params):
|
|
4632
|
+
def _send_form(self, url: str, params: Dict[str, Any]) -> str:
|
|
4466
4633
|
"""
|
|
4467
4634
|
Utility function to send a Form to Shotgun and process any HTTP errors that
|
|
4468
4635
|
could occur.
|
|
@@ -4502,42 +4669,7 @@ class Shotgun(object):
|
|
|
4502
4669
|
|
|
4503
4670
|
return result
|
|
4504
4671
|
else:
|
|
4505
|
-
raise ShotgunError("Max
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
class CACertsHTTPSConnection(http.client.HTTPConnection):
|
|
4509
|
-
""" "
|
|
4510
|
-
This class allows to create an HTTPS connection that uses the custom certificates
|
|
4511
|
-
passed in.
|
|
4512
|
-
"""
|
|
4513
|
-
|
|
4514
|
-
default_port = http.client.HTTPS_PORT
|
|
4515
|
-
|
|
4516
|
-
def __init__(self, *args, **kwargs):
|
|
4517
|
-
"""
|
|
4518
|
-
:param args: Positional arguments passed down to the base class.
|
|
4519
|
-
:param ca_certs: Path to the custom CA certs file.
|
|
4520
|
-
:param kwargs: Keyword arguments passed down to the bas class
|
|
4521
|
-
"""
|
|
4522
|
-
# Pop that argument,
|
|
4523
|
-
self.__ca_certs = kwargs.pop("ca_certs")
|
|
4524
|
-
super().__init__(self, *args, **kwargs)
|
|
4525
|
-
|
|
4526
|
-
def connect(self):
|
|
4527
|
-
"Connect to a host on a given (SSL) port."
|
|
4528
|
-
super().connect(self)
|
|
4529
|
-
# Now that the regular HTTP socket has been created, wrap it with our SSL certs.
|
|
4530
|
-
if (sys.version_info.major, sys.version_info.minor) >= (3, 8):
|
|
4531
|
-
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
4532
|
-
context.verify_mode = ssl.CERT_REQUIRED
|
|
4533
|
-
context.check_hostname = False
|
|
4534
|
-
if self.__ca_certs:
|
|
4535
|
-
context.load_verify_locations(self.__ca_certs)
|
|
4536
|
-
self.sock = context.wrap_socket(self.sock)
|
|
4537
|
-
else:
|
|
4538
|
-
self.sock = ssl.wrap_socket(
|
|
4539
|
-
self.sock, ca_certs=self.__ca_certs, cert_reqs=ssl.CERT_REQUIRED
|
|
4540
|
-
)
|
|
4672
|
+
raise ShotgunError("Max attempts limit reached.")
|
|
4541
4673
|
|
|
4542
4674
|
|
|
4543
4675
|
# Helpers from the previous API, left as is.
|
|
@@ -4629,7 +4761,7 @@ class FormPostHandler(urllib.request.BaseHandler):
|
|
|
4629
4761
|
return self.http_request(request)
|
|
4630
4762
|
|
|
4631
4763
|
|
|
4632
|
-
def _translate_filters(filters, filter_operator):
|
|
4764
|
+
def _translate_filters(filters: Union[List, Tuple], filter_operator) -> Dict[str, Any]:
|
|
4633
4765
|
"""
|
|
4634
4766
|
Translate filters params into data structure expected by rpc call.
|
|
4635
4767
|
"""
|
|
@@ -4638,7 +4770,7 @@ def _translate_filters(filters, filter_operator):
|
|
|
4638
4770
|
return _translate_filters_dict(wrapped_filters)
|
|
4639
4771
|
|
|
4640
4772
|
|
|
4641
|
-
def _translate_filters_dict(sg_filter):
|
|
4773
|
+
def _translate_filters_dict(sg_filter: Dict[str, Any]) -> Dict[str, Any]:
|
|
4642
4774
|
new_filters = {}
|
|
4643
4775
|
filter_operator = sg_filter.get("filter_operator")
|
|
4644
4776
|
|
|
@@ -4691,31 +4823,44 @@ def _translate_filters_simple(sg_filter):
|
|
|
4691
4823
|
and condition["relation"] in ["is", "is_not", "in", "not_in"]
|
|
4692
4824
|
and isinstance(values[0], dict)
|
|
4693
4825
|
):
|
|
4694
|
-
values = [
|
|
4826
|
+
values = [_optimize_filter_field(v) for v in values]
|
|
4695
4827
|
|
|
4696
4828
|
condition["values"] = values
|
|
4697
4829
|
|
|
4698
4830
|
return condition
|
|
4699
4831
|
|
|
4700
4832
|
|
|
4701
|
-
def _version_str(version):
|
|
4833
|
+
def _version_str(version) -> str:
|
|
4702
4834
|
"""
|
|
4703
4835
|
Convert a tuple of int's to a '.' separated str.
|
|
4704
4836
|
"""
|
|
4705
4837
|
return ".".join(map(str, version))
|
|
4706
4838
|
|
|
4707
4839
|
|
|
4708
|
-
def
|
|
4840
|
+
def _optimize_filter_field(
|
|
4841
|
+
field_value: Union[Dict[str, Any], List], recursive: bool = True
|
|
4842
|
+
) -> Union[Dict, List]:
|
|
4709
4843
|
"""
|
|
4710
|
-
For an entity
|
|
4711
|
-
|
|
4844
|
+
For an FPT entity, returns a new dictionary with only the type,
|
|
4845
|
+
id, and other allowed keys.
|
|
4846
|
+
If case of any processing error, the original dictionary is returned.
|
|
4847
|
+
|
|
4848
|
+
At least `type` and `id` keys are required to do the optimization
|
|
4712
4849
|
"""
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4850
|
+
allowed_keys = {
|
|
4851
|
+
"id",
|
|
4852
|
+
"type",
|
|
4853
|
+
"url",
|
|
4854
|
+
"name",
|
|
4855
|
+
"content_type",
|
|
4856
|
+
"local_path",
|
|
4857
|
+
"storage",
|
|
4858
|
+
"relative_path",
|
|
4859
|
+
}
|
|
4860
|
+
if isinstance(field_value, dict) and "id" in field_value and "type" in field_value:
|
|
4861
|
+
return {key: field_value[key] for key in allowed_keys if key in field_value}
|
|
4862
|
+
|
|
4863
|
+
elif recursive and isinstance(field_value, list):
|
|
4864
|
+
return [_optimize_filter_field(fv, recursive=False) for fv in field_value]
|
|
4865
|
+
|
|
4866
|
+
return field_value
|