shotgun-api3 3.9.0__py2.py3-none-any.whl → 3.9.1__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 +402 -280
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.1.dist-info}/METADATA +4 -4
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.1.dist-info}/RECORD +10 -9
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.1.dist-info}/WHEEL +0 -0
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.1.dist-info}/licenses/LICENSE +0 -0
- {shotgun_api3-3.9.0.dist-info → shotgun_api3-3.9.1.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.1"
|
|
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,7 @@ class Shotgun(object):
|
|
|
1826
1882
|
|
|
1827
1883
|
return self._call_rpc("work_schedule_update", params)
|
|
1828
1884
|
|
|
1829
|
-
def follow(self, user, entity):
|
|
1885
|
+
def follow(self, user: Dict[str, Any], entity: Dict[str, Any]) -> Dict[str, Any]:
|
|
1830
1886
|
"""
|
|
1831
1887
|
Add the entity to the user's followed entities.
|
|
1832
1888
|
|
|
@@ -1854,7 +1910,7 @@ class Shotgun(object):
|
|
|
1854
1910
|
|
|
1855
1911
|
return self._call_rpc("follow", params)
|
|
1856
1912
|
|
|
1857
|
-
def unfollow(self, user, entity):
|
|
1913
|
+
def unfollow(self, user: Dict[str, Any], entity: Dict[str, Any]) -> Dict[str, Any]:
|
|
1858
1914
|
"""
|
|
1859
1915
|
Remove entity from the user's followed entities.
|
|
1860
1916
|
|
|
@@ -1881,7 +1937,7 @@ class Shotgun(object):
|
|
|
1881
1937
|
|
|
1882
1938
|
return self._call_rpc("unfollow", params)
|
|
1883
1939
|
|
|
1884
|
-
def followers(self, entity):
|
|
1940
|
+
def followers(self, entity: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
1885
1941
|
"""
|
|
1886
1942
|
Return all followers for an entity.
|
|
1887
1943
|
|
|
@@ -1909,7 +1965,12 @@ class Shotgun(object):
|
|
|
1909
1965
|
|
|
1910
1966
|
return self._call_rpc("followers", params)
|
|
1911
1967
|
|
|
1912
|
-
def following(
|
|
1968
|
+
def following(
|
|
1969
|
+
self,
|
|
1970
|
+
user: Dict[str, Any],
|
|
1971
|
+
project: Optional[Dict[str, Any]] = None,
|
|
1972
|
+
entity_type: Optional[str] = None,
|
|
1973
|
+
) -> List[BaseEntity]:
|
|
1913
1974
|
"""
|
|
1914
1975
|
Return all entity instances a user is following.
|
|
1915
1976
|
|
|
@@ -1940,7 +2001,9 @@ class Shotgun(object):
|
|
|
1940
2001
|
|
|
1941
2002
|
return self._call_rpc("following", params)
|
|
1942
2003
|
|
|
1943
|
-
def schema_entity_read(
|
|
2004
|
+
def schema_entity_read(
|
|
2005
|
+
self, project_entity: Optional[BaseEntity] = None
|
|
2006
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
1944
2007
|
"""
|
|
1945
2008
|
Return all active entity types, their display names, and their visibility.
|
|
1946
2009
|
|
|
@@ -1975,7 +2038,7 @@ class Shotgun(object):
|
|
|
1975
2038
|
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
2039
|
"""
|
|
1977
2040
|
|
|
1978
|
-
params = {}
|
|
2041
|
+
params: Dict[str, Any] = {}
|
|
1979
2042
|
|
|
1980
2043
|
params = self._add_project_param(params, project_entity)
|
|
1981
2044
|
|
|
@@ -1984,7 +2047,9 @@ class Shotgun(object):
|
|
|
1984
2047
|
else:
|
|
1985
2048
|
return self._call_rpc("schema_entity_read", None)
|
|
1986
2049
|
|
|
1987
|
-
def schema_read(
|
|
2050
|
+
def schema_read(
|
|
2051
|
+
self, project_entity: Optional[BaseEntity] = None
|
|
2052
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
1988
2053
|
"""
|
|
1989
2054
|
Get the schema for all fields on all entities.
|
|
1990
2055
|
|
|
@@ -2047,7 +2112,7 @@ class Shotgun(object):
|
|
|
2047
2112
|
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
2113
|
"""
|
|
2049
2114
|
|
|
2050
|
-
params = {}
|
|
2115
|
+
params: Dict[str, Any] = {}
|
|
2051
2116
|
|
|
2052
2117
|
params = self._add_project_param(params, project_entity)
|
|
2053
2118
|
|
|
@@ -2056,7 +2121,12 @@ class Shotgun(object):
|
|
|
2056
2121
|
else:
|
|
2057
2122
|
return self._call_rpc("schema_read", None)
|
|
2058
2123
|
|
|
2059
|
-
def schema_field_read(
|
|
2124
|
+
def schema_field_read(
|
|
2125
|
+
self,
|
|
2126
|
+
entity_type: str,
|
|
2127
|
+
field_name: Optional[str] = None,
|
|
2128
|
+
project_entity: Optional[BaseEntity] = None,
|
|
2129
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
2060
2130
|
"""
|
|
2061
2131
|
Get schema for all fields on the specified entity type or just the field name specified
|
|
2062
2132
|
if provided.
|
|
@@ -2121,8 +2191,12 @@ class Shotgun(object):
|
|
|
2121
2191
|
return self._call_rpc("schema_field_read", params)
|
|
2122
2192
|
|
|
2123
2193
|
def schema_field_create(
|
|
2124
|
-
self,
|
|
2125
|
-
|
|
2194
|
+
self,
|
|
2195
|
+
entity_type: str,
|
|
2196
|
+
data_type: str,
|
|
2197
|
+
display_name: str,
|
|
2198
|
+
properties: Optional[Dict[str, Any]] = None,
|
|
2199
|
+
) -> str:
|
|
2126
2200
|
"""
|
|
2127
2201
|
Create a field for the specified entity type.
|
|
2128
2202
|
|
|
@@ -2160,8 +2234,12 @@ class Shotgun(object):
|
|
|
2160
2234
|
return self._call_rpc("schema_field_create", params)
|
|
2161
2235
|
|
|
2162
2236
|
def schema_field_update(
|
|
2163
|
-
self,
|
|
2164
|
-
|
|
2237
|
+
self,
|
|
2238
|
+
entity_type: str,
|
|
2239
|
+
field_name: str,
|
|
2240
|
+
properties: Dict[str, Any],
|
|
2241
|
+
project_entity: Optional[BaseEntity] = None,
|
|
2242
|
+
) -> bool:
|
|
2165
2243
|
"""
|
|
2166
2244
|
Update the properties for the specified field on an entity.
|
|
2167
2245
|
|
|
@@ -2175,9 +2253,9 @@ class Shotgun(object):
|
|
|
2175
2253
|
>>> sg.schema_field_update("Asset", "sg_test_number", properties)
|
|
2176
2254
|
True
|
|
2177
2255
|
|
|
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
|
|
2256
|
+
:param str entity_type: Entity type of field to update.
|
|
2257
|
+
:param str field_name: Internal Shotgun name of the field to update.
|
|
2258
|
+
:param dict properties: Dictionary with key/value pairs where the key is the property to be
|
|
2181
2259
|
updated and the value is the new value.
|
|
2182
2260
|
:param dict project_entity: Optional Project entity specifying which project to modify the
|
|
2183
2261
|
``visible`` property for. If ``visible`` is present in ``properties`` and
|
|
@@ -2202,7 +2280,7 @@ class Shotgun(object):
|
|
|
2202
2280
|
params = self._add_project_param(params, project_entity)
|
|
2203
2281
|
return self._call_rpc("schema_field_update", params)
|
|
2204
2282
|
|
|
2205
|
-
def schema_field_delete(self, entity_type, field_name):
|
|
2283
|
+
def schema_field_delete(self, entity_type: str, field_name: str) -> bool:
|
|
2206
2284
|
"""
|
|
2207
2285
|
Delete the specified field from the entity type.
|
|
2208
2286
|
|
|
@@ -2219,7 +2297,7 @@ class Shotgun(object):
|
|
|
2219
2297
|
|
|
2220
2298
|
return self._call_rpc("schema_field_delete", params)
|
|
2221
2299
|
|
|
2222
|
-
def add_user_agent(self, agent):
|
|
2300
|
+
def add_user_agent(self, agent: str) -> None:
|
|
2223
2301
|
"""
|
|
2224
2302
|
Add agent to the user-agent header.
|
|
2225
2303
|
|
|
@@ -2231,7 +2309,7 @@ class Shotgun(object):
|
|
|
2231
2309
|
"""
|
|
2232
2310
|
self._user_agents.append(agent)
|
|
2233
2311
|
|
|
2234
|
-
def reset_user_agent(self):
|
|
2312
|
+
def reset_user_agent(self) -> None:
|
|
2235
2313
|
"""
|
|
2236
2314
|
Reset user agent to the default value.
|
|
2237
2315
|
|
|
@@ -2251,7 +2329,7 @@ class Shotgun(object):
|
|
|
2251
2329
|
"ssl %s" % (self.client_caps.ssl_version),
|
|
2252
2330
|
]
|
|
2253
2331
|
|
|
2254
|
-
def set_session_uuid(self, session_uuid):
|
|
2332
|
+
def set_session_uuid(self, session_uuid: str) -> None:
|
|
2255
2333
|
"""
|
|
2256
2334
|
Set the browser session_uuid in the current Shotgun API instance.
|
|
2257
2335
|
|
|
@@ -2269,12 +2347,12 @@ class Shotgun(object):
|
|
|
2269
2347
|
|
|
2270
2348
|
def share_thumbnail(
|
|
2271
2349
|
self,
|
|
2272
|
-
entities,
|
|
2273
|
-
thumbnail_path=None,
|
|
2274
|
-
source_entity=None,
|
|
2275
|
-
filmstrip_thumbnail=False,
|
|
2276
|
-
**kwargs,
|
|
2277
|
-
):
|
|
2350
|
+
entities: List[Dict[str, Any]],
|
|
2351
|
+
thumbnail_path: Optional[str] = None,
|
|
2352
|
+
source_entity: Optional[BaseEntity] = None,
|
|
2353
|
+
filmstrip_thumbnail: bool = False,
|
|
2354
|
+
**kwargs: Any,
|
|
2355
|
+
) -> int:
|
|
2278
2356
|
"""
|
|
2279
2357
|
Associate a thumbnail with more than one Shotgun entity.
|
|
2280
2358
|
|
|
@@ -2413,7 +2491,9 @@ class Shotgun(object):
|
|
|
2413
2491
|
|
|
2414
2492
|
return attachment_id
|
|
2415
2493
|
|
|
2416
|
-
def upload_thumbnail(
|
|
2494
|
+
def upload_thumbnail(
|
|
2495
|
+
self, entity_type: str, entity_id: int, path: str, **kwargs: Any
|
|
2496
|
+
) -> int:
|
|
2417
2497
|
"""
|
|
2418
2498
|
Upload a file from a local path and assign it as the thumbnail for the specified entity.
|
|
2419
2499
|
|
|
@@ -2438,12 +2518,15 @@ class Shotgun(object):
|
|
|
2438
2518
|
:param int entity_id: Id of the entity to set the thumbnail for.
|
|
2439
2519
|
:param str path: Full path to the thumbnail file on disk.
|
|
2440
2520
|
:returns: Id of the new attachment
|
|
2521
|
+
:rtype: int
|
|
2441
2522
|
"""
|
|
2442
2523
|
return self.upload(
|
|
2443
2524
|
entity_type, entity_id, path, field_name="thumb_image", **kwargs
|
|
2444
2525
|
)
|
|
2445
2526
|
|
|
2446
|
-
def upload_filmstrip_thumbnail(
|
|
2527
|
+
def upload_filmstrip_thumbnail(
|
|
2528
|
+
self, entity_type: str, entity_id: int, path: str, **kwargs: Any
|
|
2529
|
+
) -> int:
|
|
2447
2530
|
"""
|
|
2448
2531
|
Upload filmstrip thumbnail to specified entity.
|
|
2449
2532
|
|
|
@@ -2494,13 +2577,13 @@ class Shotgun(object):
|
|
|
2494
2577
|
|
|
2495
2578
|
def upload(
|
|
2496
2579
|
self,
|
|
2497
|
-
entity_type,
|
|
2498
|
-
entity_id,
|
|
2499
|
-
path,
|
|
2500
|
-
field_name=None,
|
|
2501
|
-
display_name=None,
|
|
2502
|
-
tag_list=None,
|
|
2503
|
-
):
|
|
2580
|
+
entity_type: str,
|
|
2581
|
+
entity_id: int,
|
|
2582
|
+
path: str,
|
|
2583
|
+
field_name: Optional[str] = None,
|
|
2584
|
+
display_name: Optional[str] = None,
|
|
2585
|
+
tag_list: Optional[str] = None,
|
|
2586
|
+
) -> int:
|
|
2504
2587
|
"""
|
|
2505
2588
|
Upload a file to the specified entity.
|
|
2506
2589
|
|
|
@@ -2583,14 +2666,14 @@ class Shotgun(object):
|
|
|
2583
2666
|
|
|
2584
2667
|
def _upload_to_storage(
|
|
2585
2668
|
self,
|
|
2586
|
-
entity_type,
|
|
2587
|
-
entity_id,
|
|
2588
|
-
path,
|
|
2589
|
-
field_name,
|
|
2590
|
-
display_name,
|
|
2591
|
-
tag_list,
|
|
2592
|
-
is_thumbnail,
|
|
2593
|
-
):
|
|
2669
|
+
entity_type: str,
|
|
2670
|
+
entity_id: int,
|
|
2671
|
+
path: str,
|
|
2672
|
+
field_name: Optional[str],
|
|
2673
|
+
display_name: Optional[str],
|
|
2674
|
+
tag_list: Optional[str],
|
|
2675
|
+
is_thumbnail: bool,
|
|
2676
|
+
) -> int:
|
|
2594
2677
|
"""
|
|
2595
2678
|
Internal function to upload a file to the Cloud storage and link it to the specified entity.
|
|
2596
2679
|
|
|
@@ -2673,14 +2756,14 @@ class Shotgun(object):
|
|
|
2673
2756
|
|
|
2674
2757
|
def _upload_to_sg(
|
|
2675
2758
|
self,
|
|
2676
|
-
entity_type,
|
|
2677
|
-
entity_id,
|
|
2678
|
-
path,
|
|
2679
|
-
field_name,
|
|
2680
|
-
display_name,
|
|
2681
|
-
tag_list,
|
|
2682
|
-
is_thumbnail,
|
|
2683
|
-
):
|
|
2759
|
+
entity_type: str,
|
|
2760
|
+
entity_id: int,
|
|
2761
|
+
path: str,
|
|
2762
|
+
field_name: Optional[str],
|
|
2763
|
+
display_name: Optional[str],
|
|
2764
|
+
tag_list: Optional[str],
|
|
2765
|
+
is_thumbnail: bool,
|
|
2766
|
+
) -> int:
|
|
2684
2767
|
"""
|
|
2685
2768
|
Internal function to upload a file to Shotgun and link it to the specified entity.
|
|
2686
2769
|
|
|
@@ -2752,7 +2835,9 @@ class Shotgun(object):
|
|
|
2752
2835
|
attachment_id = int(result.split(":", 2)[1].split("\n", 1)[0])
|
|
2753
2836
|
return attachment_id
|
|
2754
2837
|
|
|
2755
|
-
def _get_attachment_upload_info(
|
|
2838
|
+
def _get_attachment_upload_info(
|
|
2839
|
+
self, is_thumbnail: bool, filename: str, is_multipart_upload: bool
|
|
2840
|
+
) -> Dict[str, Any]:
|
|
2756
2841
|
"""
|
|
2757
2842
|
Internal function to get the information needed to upload a file to Cloud storage.
|
|
2758
2843
|
|
|
@@ -2799,7 +2884,12 @@ class Shotgun(object):
|
|
|
2799
2884
|
"upload_info": upload_info,
|
|
2800
2885
|
}
|
|
2801
2886
|
|
|
2802
|
-
def download_attachment(
|
|
2887
|
+
def download_attachment(
|
|
2888
|
+
self,
|
|
2889
|
+
attachment: Union[Dict[str, Any], bool] = False,
|
|
2890
|
+
file_path: Optional[str] = None,
|
|
2891
|
+
attachment_id: Optional[int] = None,
|
|
2892
|
+
) -> Union[str, bytes, None]:
|
|
2803
2893
|
"""
|
|
2804
2894
|
Download the file associated with a Shotgun Attachment.
|
|
2805
2895
|
|
|
@@ -2915,7 +3005,7 @@ class Shotgun(object):
|
|
|
2915
3005
|
else:
|
|
2916
3006
|
return attachment
|
|
2917
3007
|
|
|
2918
|
-
def get_auth_cookie_handler(self):
|
|
3008
|
+
def get_auth_cookie_handler(self) -> urllib.request.HTTPCookieProcessor:
|
|
2919
3009
|
"""
|
|
2920
3010
|
Return an urllib cookie handler containing a cookie for FPTR
|
|
2921
3011
|
authentication.
|
|
@@ -2947,7 +3037,9 @@ class Shotgun(object):
|
|
|
2947
3037
|
cj.set_cookie(c)
|
|
2948
3038
|
return urllib.request.HTTPCookieProcessor(cj)
|
|
2949
3039
|
|
|
2950
|
-
def get_attachment_download_url(
|
|
3040
|
+
def get_attachment_download_url(
|
|
3041
|
+
self, attachment: Optional[Union[int, dict[str, Any]]]
|
|
3042
|
+
) -> str:
|
|
2951
3043
|
"""
|
|
2952
3044
|
Return the URL for downloading provided Attachment.
|
|
2953
3045
|
|
|
@@ -3005,7 +3097,9 @@ class Shotgun(object):
|
|
|
3005
3097
|
)
|
|
3006
3098
|
return url
|
|
3007
3099
|
|
|
3008
|
-
def authenticate_human_user(
|
|
3100
|
+
def authenticate_human_user(
|
|
3101
|
+
self, user_login: str, user_password: str, auth_token: Optional[str] = None
|
|
3102
|
+
) -> Union[Dict[str, Any], None]:
|
|
3009
3103
|
"""
|
|
3010
3104
|
Authenticate Shotgun HumanUser.
|
|
3011
3105
|
|
|
@@ -3064,7 +3158,9 @@ class Shotgun(object):
|
|
|
3064
3158
|
self.config.auth_token = original_auth_token
|
|
3065
3159
|
raise
|
|
3066
3160
|
|
|
3067
|
-
def update_project_last_accessed(
|
|
3161
|
+
def update_project_last_accessed(
|
|
3162
|
+
self, project: Dict[str, Any], user: Optional[Dict[str, Any]] = None
|
|
3163
|
+
) -> None:
|
|
3068
3164
|
"""
|
|
3069
3165
|
Update a Project's ``last_accessed_by_current_user`` field to the current timestamp.
|
|
3070
3166
|
|
|
@@ -3110,7 +3206,9 @@ class Shotgun(object):
|
|
|
3110
3206
|
record = self._call_rpc("update_project_last_accessed_by_current_user", params)
|
|
3111
3207
|
self._parse_records(record)[0]
|
|
3112
3208
|
|
|
3113
|
-
def note_thread_read(
|
|
3209
|
+
def note_thread_read(
|
|
3210
|
+
self, note_id: int, entity_fields: Optional[Dict[str, Any]] = None
|
|
3211
|
+
) -> List[Dict[str, Any]]:
|
|
3114
3212
|
"""
|
|
3115
3213
|
Return the full conversation for a given note, including Replies and Attachments.
|
|
3116
3214
|
|
|
@@ -3185,7 +3283,13 @@ class Shotgun(object):
|
|
|
3185
3283
|
result = self._parse_records(record)
|
|
3186
3284
|
return result
|
|
3187
3285
|
|
|
3188
|
-
def text_search(
|
|
3286
|
+
def text_search(
|
|
3287
|
+
self,
|
|
3288
|
+
text: str,
|
|
3289
|
+
entity_types: Dict[str, Any],
|
|
3290
|
+
project_ids: Optional[List] = None,
|
|
3291
|
+
limit: Optional[int] = None,
|
|
3292
|
+
) -> Dict[str, Any]:
|
|
3189
3293
|
"""
|
|
3190
3294
|
Search across the specified entity types for the given text.
|
|
3191
3295
|
|
|
@@ -3279,13 +3383,13 @@ class Shotgun(object):
|
|
|
3279
3383
|
|
|
3280
3384
|
def activity_stream_read(
|
|
3281
3385
|
self,
|
|
3282
|
-
entity_type,
|
|
3283
|
-
entity_id,
|
|
3284
|
-
entity_fields=None,
|
|
3285
|
-
min_id=None,
|
|
3286
|
-
max_id=None,
|
|
3287
|
-
limit=None,
|
|
3288
|
-
):
|
|
3386
|
+
entity_type: str,
|
|
3387
|
+
entity_id: int,
|
|
3388
|
+
entity_fields: Optional[Dict[str, Any]] = None,
|
|
3389
|
+
min_id: Optional[int] = None,
|
|
3390
|
+
max_id: Optional[int] = None,
|
|
3391
|
+
limit: Optional[int] = None,
|
|
3392
|
+
) -> Dict[str, Any]:
|
|
3289
3393
|
"""
|
|
3290
3394
|
Retrieve activity stream data from Shotgun.
|
|
3291
3395
|
|
|
@@ -3375,7 +3479,7 @@ class Shotgun(object):
|
|
|
3375
3479
|
result = self._parse_records(record)[0]
|
|
3376
3480
|
return result
|
|
3377
3481
|
|
|
3378
|
-
def nav_expand(self, path, seed_entity_field=None, entity_fields=None):
|
|
3482
|
+
def nav_expand(self, path: str, seed_entity_field=None, entity_fields=None):
|
|
3379
3483
|
"""
|
|
3380
3484
|
Expand the navigation hierarchy for the supplied path.
|
|
3381
3485
|
|
|
@@ -3395,7 +3499,9 @@ class Shotgun(object):
|
|
|
3395
3499
|
},
|
|
3396
3500
|
)
|
|
3397
3501
|
|
|
3398
|
-
def nav_search_string(
|
|
3502
|
+
def nav_search_string(
|
|
3503
|
+
self, root_path: str, search_string: str, seed_entity_field=None
|
|
3504
|
+
):
|
|
3399
3505
|
"""
|
|
3400
3506
|
Search function adapted to work with the navigation hierarchy.
|
|
3401
3507
|
|
|
@@ -3414,7 +3520,12 @@ class Shotgun(object):
|
|
|
3414
3520
|
},
|
|
3415
3521
|
)
|
|
3416
3522
|
|
|
3417
|
-
def nav_search_entity(
|
|
3523
|
+
def nav_search_entity(
|
|
3524
|
+
self,
|
|
3525
|
+
root_path: str,
|
|
3526
|
+
entity: Dict[str, Any],
|
|
3527
|
+
seed_entity_field: Optional[Dict[str, Any]] = None,
|
|
3528
|
+
):
|
|
3418
3529
|
"""
|
|
3419
3530
|
Search function adapted to work with the navigation hierarchy.
|
|
3420
3531
|
|
|
@@ -3434,7 +3545,7 @@ class Shotgun(object):
|
|
|
3434
3545
|
},
|
|
3435
3546
|
)
|
|
3436
3547
|
|
|
3437
|
-
def get_session_token(self):
|
|
3548
|
+
def get_session_token(self) -> str:
|
|
3438
3549
|
"""
|
|
3439
3550
|
Get the session token associated with the current session.
|
|
3440
3551
|
|
|
@@ -3458,7 +3569,7 @@ class Shotgun(object):
|
|
|
3458
3569
|
|
|
3459
3570
|
return session_token
|
|
3460
3571
|
|
|
3461
|
-
def preferences_read(self, prefs=None):
|
|
3572
|
+
def preferences_read(self, prefs: Optional[List] = None) -> Dict[str, Any]:
|
|
3462
3573
|
"""
|
|
3463
3574
|
Get a subset of the site preferences.
|
|
3464
3575
|
|
|
@@ -3481,7 +3592,7 @@ class Shotgun(object):
|
|
|
3481
3592
|
|
|
3482
3593
|
return self._call_rpc("preferences_read", {"prefs": prefs})
|
|
3483
3594
|
|
|
3484
|
-
def user_subscriptions_read(self):
|
|
3595
|
+
def user_subscriptions_read(self) -> List:
|
|
3485
3596
|
"""
|
|
3486
3597
|
Get the list of user subscriptions.
|
|
3487
3598
|
|
|
@@ -3493,8 +3604,9 @@ class Shotgun(object):
|
|
|
3493
3604
|
|
|
3494
3605
|
return self._call_rpc("user_subscriptions_read", None)
|
|
3495
3606
|
|
|
3496
|
-
def user_subscriptions_create(
|
|
3497
|
-
|
|
3607
|
+
def user_subscriptions_create(
|
|
3608
|
+
self, users: List[Dict[str, Union[str, List[str], None]]]
|
|
3609
|
+
) -> bool:
|
|
3498
3610
|
"""
|
|
3499
3611
|
Assign subscriptions to users.
|
|
3500
3612
|
|
|
@@ -3515,7 +3627,7 @@ class Shotgun(object):
|
|
|
3515
3627
|
|
|
3516
3628
|
return response.get("status") == "success"
|
|
3517
3629
|
|
|
3518
|
-
def _build_opener(self, handler):
|
|
3630
|
+
def _build_opener(self, handler) -> urllib.request.OpenerDirector:
|
|
3519
3631
|
"""
|
|
3520
3632
|
Build urllib2 opener with appropriate proxy handler.
|
|
3521
3633
|
"""
|
|
@@ -3616,7 +3728,13 @@ class Shotgun(object):
|
|
|
3616
3728
|
# ========================================================================
|
|
3617
3729
|
# RPC Functions
|
|
3618
3730
|
|
|
3619
|
-
def _call_rpc(
|
|
3731
|
+
def _call_rpc(
|
|
3732
|
+
self,
|
|
3733
|
+
method: str,
|
|
3734
|
+
params: Any,
|
|
3735
|
+
include_auth_params: bool = True,
|
|
3736
|
+
first: bool = False,
|
|
3737
|
+
) -> Any:
|
|
3620
3738
|
"""
|
|
3621
3739
|
Call the specified method on the Shotgun Server sending the supplied payload.
|
|
3622
3740
|
"""
|
|
@@ -3680,7 +3798,7 @@ class Shotgun(object):
|
|
|
3680
3798
|
return results[0]
|
|
3681
3799
|
return results
|
|
3682
3800
|
|
|
3683
|
-
def _auth_params(self):
|
|
3801
|
+
def _auth_params(self) -> Dict[str, Any]:
|
|
3684
3802
|
"""
|
|
3685
3803
|
Return a dictionary of the authentication parameters being used.
|
|
3686
3804
|
"""
|
|
@@ -3735,7 +3853,7 @@ class Shotgun(object):
|
|
|
3735
3853
|
|
|
3736
3854
|
return auth_params
|
|
3737
3855
|
|
|
3738
|
-
def _sanitize_auth_params(self, params):
|
|
3856
|
+
def _sanitize_auth_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
3739
3857
|
"""
|
|
3740
3858
|
Given an authentication parameter dictionary, sanitize any sensitive
|
|
3741
3859
|
information and return the sanitized dict copy.
|
|
@@ -3746,7 +3864,9 @@ class Shotgun(object):
|
|
|
3746
3864
|
sanitized_params[k] = "********"
|
|
3747
3865
|
return sanitized_params
|
|
3748
3866
|
|
|
3749
|
-
def _build_payload(
|
|
3867
|
+
def _build_payload(
|
|
3868
|
+
self, method: str, params, include_auth_params: bool = True
|
|
3869
|
+
) -> Dict[str, Any]:
|
|
3750
3870
|
"""
|
|
3751
3871
|
Build the payload to be send to the rpc endpoint.
|
|
3752
3872
|
"""
|
|
@@ -3764,7 +3884,7 @@ class Shotgun(object):
|
|
|
3764
3884
|
|
|
3765
3885
|
return {"method_name": method, "params": call_params}
|
|
3766
3886
|
|
|
3767
|
-
def _encode_payload(self, payload):
|
|
3887
|
+
def _encode_payload(self, payload) -> bytes:
|
|
3768
3888
|
"""
|
|
3769
3889
|
Encode the payload to a string to be passed to the rpc endpoint.
|
|
3770
3890
|
|
|
@@ -3775,7 +3895,9 @@ class Shotgun(object):
|
|
|
3775
3895
|
|
|
3776
3896
|
return json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
|
3777
3897
|
|
|
3778
|
-
def _make_call(
|
|
3898
|
+
def _make_call(
|
|
3899
|
+
self, verb: str, path: str, body, headers: Optional[Dict[str, Any]]
|
|
3900
|
+
) -> Tuple[Tuple[int, str], Dict[str, Any], str]:
|
|
3779
3901
|
"""
|
|
3780
3902
|
Make an HTTP call to the server.
|
|
3781
3903
|
|
|
@@ -3825,7 +3947,9 @@ class Shotgun(object):
|
|
|
3825
3947
|
)
|
|
3826
3948
|
time.sleep(rpc_attempt_interval)
|
|
3827
3949
|
|
|
3828
|
-
def _http_request(
|
|
3950
|
+
def _http_request(
|
|
3951
|
+
self, verb: str, path: str, body, headers: Dict[str, Any]
|
|
3952
|
+
) -> Tuple[Tuple[int, str], Dict[str, Any], str]:
|
|
3829
3953
|
"""
|
|
3830
3954
|
Make the actual HTTP request.
|
|
3831
3955
|
"""
|
|
@@ -3849,7 +3973,9 @@ class Shotgun(object):
|
|
|
3849
3973
|
|
|
3850
3974
|
return (http_status, resp_headers, resp_body)
|
|
3851
3975
|
|
|
3852
|
-
def _make_upload_request(
|
|
3976
|
+
def _make_upload_request(
|
|
3977
|
+
self, request, opener: "urllib.request.OpenerDirector"
|
|
3978
|
+
) -> "urllib.request._UrlopenRet":
|
|
3853
3979
|
"""
|
|
3854
3980
|
Open the given request object, return the
|
|
3855
3981
|
response, raises URLError on protocol errors.
|
|
@@ -3861,7 +3987,7 @@ class Shotgun(object):
|
|
|
3861
3987
|
raise
|
|
3862
3988
|
return result
|
|
3863
3989
|
|
|
3864
|
-
def _parse_http_status(self, status):
|
|
3990
|
+
def _parse_http_status(self, status: Tuple) -> None:
|
|
3865
3991
|
"""
|
|
3866
3992
|
Parse the status returned from the http request.
|
|
3867
3993
|
|
|
@@ -3879,7 +4005,9 @@ class Shotgun(object):
|
|
|
3879
4005
|
|
|
3880
4006
|
return
|
|
3881
4007
|
|
|
3882
|
-
def _decode_response(
|
|
4008
|
+
def _decode_response(
|
|
4009
|
+
self, headers: Dict[str, Any], body: str
|
|
4010
|
+
) -> Union[str, Dict[str, Any]]:
|
|
3883
4011
|
"""
|
|
3884
4012
|
Decode the response from the server from the wire format to
|
|
3885
4013
|
a python data structure.
|
|
@@ -3900,7 +4028,7 @@ class Shotgun(object):
|
|
|
3900
4028
|
return self._json_loads(body)
|
|
3901
4029
|
return body
|
|
3902
4030
|
|
|
3903
|
-
def _json_loads(self, body):
|
|
4031
|
+
def _json_loads(self, body: str) -> Any:
|
|
3904
4032
|
return json.loads(body)
|
|
3905
4033
|
|
|
3906
4034
|
def _response_errors(self, sg_response):
|
|
@@ -3949,7 +4077,7 @@ class Shotgun(object):
|
|
|
3949
4077
|
raise Fault(sg_response.get("message", "Unknown Error"))
|
|
3950
4078
|
return
|
|
3951
4079
|
|
|
3952
|
-
def _visit_data(self, data, visitor):
|
|
4080
|
+
def _visit_data(self, data: T, visitor) -> T:
|
|
3953
4081
|
"""
|
|
3954
4082
|
Walk the data (simple python types) and call the visitor.
|
|
3955
4083
|
"""
|
|
@@ -3959,17 +4087,17 @@ class Shotgun(object):
|
|
|
3959
4087
|
|
|
3960
4088
|
recursive = self._visit_data
|
|
3961
4089
|
if isinstance(data, list):
|
|
3962
|
-
return [recursive(i, visitor) for i in data]
|
|
4090
|
+
return [recursive(i, visitor) for i in data] # type: ignore[return-value]
|
|
3963
4091
|
|
|
3964
4092
|
if isinstance(data, tuple):
|
|
3965
|
-
return tuple(recursive(i, visitor) for i in data)
|
|
4093
|
+
return tuple(recursive(i, visitor) for i in data) # type: ignore[return-value]
|
|
3966
4094
|
|
|
3967
4095
|
if isinstance(data, dict):
|
|
3968
|
-
return dict((k, recursive(v, visitor)) for k, v in data.items())
|
|
4096
|
+
return dict((k, recursive(v, visitor)) for k, v in data.items()) # type: ignore[return-value]
|
|
3969
4097
|
|
|
3970
4098
|
return visitor(data)
|
|
3971
4099
|
|
|
3972
|
-
def _transform_outbound(self, data):
|
|
4100
|
+
def _transform_outbound(self, data: T) -> T:
|
|
3973
4101
|
"""
|
|
3974
4102
|
Transform data types or values before they are sent by the client.
|
|
3975
4103
|
|
|
@@ -4016,7 +4144,7 @@ class Shotgun(object):
|
|
|
4016
4144
|
|
|
4017
4145
|
return self._visit_data(data, _outbound_visitor)
|
|
4018
4146
|
|
|
4019
|
-
def _transform_inbound(self, data):
|
|
4147
|
+
def _transform_inbound(self, data: T) -> T:
|
|
4020
4148
|
"""
|
|
4021
4149
|
Transforms data types or values after they are received from the server.
|
|
4022
4150
|
"""
|
|
@@ -4052,7 +4180,7 @@ class Shotgun(object):
|
|
|
4052
4180
|
# ========================================================================
|
|
4053
4181
|
# Connection Functions
|
|
4054
4182
|
|
|
4055
|
-
def _get_connection(self):
|
|
4183
|
+
def _get_connection(self) -> Http:
|
|
4056
4184
|
"""
|
|
4057
4185
|
Return the current connection or creates a new connection to the current server.
|
|
4058
4186
|
"""
|
|
@@ -4081,7 +4209,7 @@ class Shotgun(object):
|
|
|
4081
4209
|
|
|
4082
4210
|
return self._connection
|
|
4083
4211
|
|
|
4084
|
-
def _close_connection(self):
|
|
4212
|
+
def _close_connection(self) -> None:
|
|
4085
4213
|
"""
|
|
4086
4214
|
Close the current connection.
|
|
4087
4215
|
"""
|
|
@@ -4100,7 +4228,7 @@ class Shotgun(object):
|
|
|
4100
4228
|
# ========================================================================
|
|
4101
4229
|
# Utility
|
|
4102
4230
|
|
|
4103
|
-
def _parse_records(self, records):
|
|
4231
|
+
def _parse_records(self, records: List) -> List:
|
|
4104
4232
|
"""
|
|
4105
4233
|
Parse 'records' returned from the api to do local modifications:
|
|
4106
4234
|
|
|
@@ -4156,7 +4284,7 @@ class Shotgun(object):
|
|
|
4156
4284
|
|
|
4157
4285
|
return records
|
|
4158
4286
|
|
|
4159
|
-
def _build_thumb_url(self, entity_type, entity_id):
|
|
4287
|
+
def _build_thumb_url(self, entity_type: str, entity_id: int) -> str:
|
|
4160
4288
|
"""
|
|
4161
4289
|
Return the URL for the thumbnail of an entity given the entity type and the entity id.
|
|
4162
4290
|
|
|
@@ -4204,8 +4332,12 @@ class Shotgun(object):
|
|
|
4204
4332
|
raise RuntimeError("Unknown code %s %s" % (code, thumb_url))
|
|
4205
4333
|
|
|
4206
4334
|
def _dict_to_list(
|
|
4207
|
-
self,
|
|
4208
|
-
|
|
4335
|
+
self,
|
|
4336
|
+
d: Optional[Dict[str, Any]],
|
|
4337
|
+
key_name: str = "field_name",
|
|
4338
|
+
value_name: str = "value",
|
|
4339
|
+
extra_data=None,
|
|
4340
|
+
) -> List[Dict[str, Any]]:
|
|
4209
4341
|
"""
|
|
4210
4342
|
Utility function to convert a dict into a list dicts using the key_name and value_name keys.
|
|
4211
4343
|
|
|
@@ -4222,7 +4354,9 @@ class Shotgun(object):
|
|
|
4222
4354
|
ret.append(d)
|
|
4223
4355
|
return ret
|
|
4224
4356
|
|
|
4225
|
-
def _dict_to_extra_data(
|
|
4357
|
+
def _dict_to_extra_data(
|
|
4358
|
+
self, d: Optional[Dict[str, Any]], key_name="value"
|
|
4359
|
+
) -> Dict[str, Any]:
|
|
4226
4360
|
"""
|
|
4227
4361
|
Utility function to convert a dict into a dict compatible with the extra_data arg
|
|
4228
4362
|
of _dict_to_list.
|
|
@@ -4231,7 +4365,7 @@ class Shotgun(object):
|
|
|
4231
4365
|
"""
|
|
4232
4366
|
return dict([(k, {key_name: v}) for (k, v) in (d or {}).items()])
|
|
4233
4367
|
|
|
4234
|
-
def _upload_file_to_storage(self, path, storage_url):
|
|
4368
|
+
def _upload_file_to_storage(self, path: str, storage_url: str) -> None:
|
|
4235
4369
|
"""
|
|
4236
4370
|
Internal function to upload an entire file to the Cloud storage.
|
|
4237
4371
|
|
|
@@ -4251,7 +4385,9 @@ class Shotgun(object):
|
|
|
4251
4385
|
|
|
4252
4386
|
LOG.debug("File uploaded to Cloud storage: %s", filename)
|
|
4253
4387
|
|
|
4254
|
-
def _multipart_upload_file_to_storage(
|
|
4388
|
+
def _multipart_upload_file_to_storage(
|
|
4389
|
+
self, path: str, upload_info: Dict[str, Any]
|
|
4390
|
+
) -> None:
|
|
4255
4391
|
"""
|
|
4256
4392
|
Internal function to upload a file to the Cloud storage in multiple parts.
|
|
4257
4393
|
|
|
@@ -4293,7 +4429,9 @@ class Shotgun(object):
|
|
|
4293
4429
|
|
|
4294
4430
|
LOG.debug("File uploaded in multiple parts to Cloud storage: %s", path)
|
|
4295
4431
|
|
|
4296
|
-
def _get_upload_part_link(
|
|
4432
|
+
def _get_upload_part_link(
|
|
4433
|
+
self, upload_info: Dict[str, Any], filename: str, part_number: int
|
|
4434
|
+
) -> str:
|
|
4297
4435
|
"""
|
|
4298
4436
|
Internal function to get the url to upload the next part of a file to the
|
|
4299
4437
|
Cloud storage, in a multi-part upload process.
|
|
@@ -4333,7 +4471,9 @@ class Shotgun(object):
|
|
|
4333
4471
|
LOG.debug("Got next upload link from server for multipart upload.")
|
|
4334
4472
|
return result.split("\n", 2)[1]
|
|
4335
4473
|
|
|
4336
|
-
def _upload_data_to_storage(
|
|
4474
|
+
def _upload_data_to_storage(
|
|
4475
|
+
self, data: BinaryIO, content_type: str, size: int, storage_url: str
|
|
4476
|
+
) -> str:
|
|
4337
4477
|
"""
|
|
4338
4478
|
Internal function to upload data to Cloud storage.
|
|
4339
4479
|
|
|
@@ -4382,19 +4522,21 @@ class Shotgun(object):
|
|
|
4382
4522
|
else:
|
|
4383
4523
|
break
|
|
4384
4524
|
else:
|
|
4385
|
-
raise ShotgunError("Max
|
|
4525
|
+
raise ShotgunError("Max attempts limit reached.")
|
|
4386
4526
|
|
|
4387
4527
|
etag = result.info()["Etag"]
|
|
4388
4528
|
LOG.debug("Part upload completed successfully.")
|
|
4389
4529
|
return etag
|
|
4390
4530
|
|
|
4391
|
-
def _complete_multipart_upload(
|
|
4531
|
+
def _complete_multipart_upload(
|
|
4532
|
+
self, upload_info: Dict[str, Any], filename: str, etags: Iterable[str]
|
|
4533
|
+
) -> None:
|
|
4392
4534
|
"""
|
|
4393
4535
|
Internal function to complete a multi-part upload to the Cloud storage.
|
|
4394
4536
|
|
|
4395
4537
|
:param dict upload_info: Contains details received from the server, about the upload.
|
|
4396
4538
|
:param str filename: Name of the file for which we want to complete the upload.
|
|
4397
|
-
:param
|
|
4539
|
+
:param tuple etags: Contains the etag of each uploaded file part.
|
|
4398
4540
|
"""
|
|
4399
4541
|
|
|
4400
4542
|
params = {
|
|
@@ -4421,7 +4563,9 @@ class Shotgun(object):
|
|
|
4421
4563
|
if not result.startswith("1"):
|
|
4422
4564
|
raise ShotgunError("Unable get upload part link: %s" % result)
|
|
4423
4565
|
|
|
4424
|
-
def _requires_direct_s3_upload(
|
|
4566
|
+
def _requires_direct_s3_upload(
|
|
4567
|
+
self, entity_type: str, field_name: Optional[str]
|
|
4568
|
+
) -> bool:
|
|
4425
4569
|
"""
|
|
4426
4570
|
Internal function that determines if an entity_type + field_name combination
|
|
4427
4571
|
should be uploaded to cloud storage.
|
|
@@ -4462,7 +4606,7 @@ class Shotgun(object):
|
|
|
4462
4606
|
else:
|
|
4463
4607
|
return False
|
|
4464
4608
|
|
|
4465
|
-
def _send_form(self, url, params):
|
|
4609
|
+
def _send_form(self, url: str, params: Dict[str, Any]) -> str:
|
|
4466
4610
|
"""
|
|
4467
4611
|
Utility function to send a Form to Shotgun and process any HTTP errors that
|
|
4468
4612
|
could occur.
|
|
@@ -4502,42 +4646,7 @@ class Shotgun(object):
|
|
|
4502
4646
|
|
|
4503
4647
|
return result
|
|
4504
4648
|
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
|
-
)
|
|
4649
|
+
raise ShotgunError("Max attempts limit reached.")
|
|
4541
4650
|
|
|
4542
4651
|
|
|
4543
4652
|
# Helpers from the previous API, left as is.
|
|
@@ -4629,7 +4738,7 @@ class FormPostHandler(urllib.request.BaseHandler):
|
|
|
4629
4738
|
return self.http_request(request)
|
|
4630
4739
|
|
|
4631
4740
|
|
|
4632
|
-
def _translate_filters(filters, filter_operator):
|
|
4741
|
+
def _translate_filters(filters: Union[List, Tuple], filter_operator) -> Dict[str, Any]:
|
|
4633
4742
|
"""
|
|
4634
4743
|
Translate filters params into data structure expected by rpc call.
|
|
4635
4744
|
"""
|
|
@@ -4638,7 +4747,7 @@ def _translate_filters(filters, filter_operator):
|
|
|
4638
4747
|
return _translate_filters_dict(wrapped_filters)
|
|
4639
4748
|
|
|
4640
4749
|
|
|
4641
|
-
def _translate_filters_dict(sg_filter):
|
|
4750
|
+
def _translate_filters_dict(sg_filter: Dict[str, Any]) -> Dict[str, Any]:
|
|
4642
4751
|
new_filters = {}
|
|
4643
4752
|
filter_operator = sg_filter.get("filter_operator")
|
|
4644
4753
|
|
|
@@ -4691,31 +4800,44 @@ def _translate_filters_simple(sg_filter):
|
|
|
4691
4800
|
and condition["relation"] in ["is", "is_not", "in", "not_in"]
|
|
4692
4801
|
and isinstance(values[0], dict)
|
|
4693
4802
|
):
|
|
4694
|
-
values = [
|
|
4803
|
+
values = [_optimize_filter_field(v) for v in values]
|
|
4695
4804
|
|
|
4696
4805
|
condition["values"] = values
|
|
4697
4806
|
|
|
4698
4807
|
return condition
|
|
4699
4808
|
|
|
4700
4809
|
|
|
4701
|
-
def _version_str(version):
|
|
4810
|
+
def _version_str(version) -> str:
|
|
4702
4811
|
"""
|
|
4703
4812
|
Convert a tuple of int's to a '.' separated str.
|
|
4704
4813
|
"""
|
|
4705
4814
|
return ".".join(map(str, version))
|
|
4706
4815
|
|
|
4707
4816
|
|
|
4708
|
-
def
|
|
4817
|
+
def _optimize_filter_field(
|
|
4818
|
+
field_value: Union[Dict[str, Any], List], recursive: bool = True
|
|
4819
|
+
) -> Union[Dict, List]:
|
|
4709
4820
|
"""
|
|
4710
|
-
For an entity
|
|
4711
|
-
|
|
4821
|
+
For an FPT entity, returns a new dictionary with only the type,
|
|
4822
|
+
id, and other allowed keys.
|
|
4823
|
+
If case of any processing error, the original dictionary is returned.
|
|
4824
|
+
|
|
4825
|
+
At least `type` and `id` keys are required to do the optimization
|
|
4712
4826
|
"""
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4827
|
+
allowed_keys = {
|
|
4828
|
+
"id",
|
|
4829
|
+
"type",
|
|
4830
|
+
"url",
|
|
4831
|
+
"name",
|
|
4832
|
+
"content_type",
|
|
4833
|
+
"local_path",
|
|
4834
|
+
"storage",
|
|
4835
|
+
"relative_path",
|
|
4836
|
+
}
|
|
4837
|
+
if isinstance(field_value, dict) and "id" in field_value and "type" in field_value:
|
|
4838
|
+
return {key: field_value[key] for key in allowed_keys if key in field_value}
|
|
4839
|
+
|
|
4840
|
+
elif recursive and isinstance(field_value, list):
|
|
4841
|
+
return [_optimize_filter_field(fv, recursive=False) for fv in field_value]
|
|
4842
|
+
|
|
4843
|
+
return field_value
|