ayon-python-api 1.2.11__tar.gz → 1.2.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/PKG-INFO +1 -1
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/__init__.py +8 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api.py +145 -1
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/base.py +6 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/bundles_addons.py +15 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/folders.py +2 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/links.py +1 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/products.py +2 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/representations.py +2 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/tasks.py +4 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/versions.py +2 -1
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/workfiles.py +2 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/graphql_queries.py +25 -10
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/operations.py +2 -2
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/server_api.py +176 -19
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/utils.py +28 -11
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/version.py +1 -1
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_python_api.egg-info/PKG-INFO +1 -1
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/pyproject.toml +3 -3
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/LICENSE +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/README.md +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/__init__.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/actions.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/activities.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/attributes.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/dependency_packages.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/events.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/installers.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/lists.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/projects.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/secrets.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/thumbnails.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/constants.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/entity_hub.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/events.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/exceptions.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/graphql.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/typing.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_python_api.egg-info/SOURCES.txt +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_python_api.egg-info/dependency_links.txt +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_python_api.egg-info/requires.txt +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_python_api.egg-info/top_level.txt +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/setup.cfg +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/setup.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/tests/test_entity_hub.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/tests/test_folder_hierarchy.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/tests/test_get_events.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/tests/test_graphql_queries.py +0 -0
- {ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/tests/test_server.py +0 -0
|
@@ -55,6 +55,7 @@ from ._api import (
|
|
|
55
55
|
get_server_version,
|
|
56
56
|
get_server_version_tuple,
|
|
57
57
|
is_product_base_type_supported,
|
|
58
|
+
links_graphql_support_data,
|
|
58
59
|
get_users,
|
|
59
60
|
get_user_by_name,
|
|
60
61
|
get_user,
|
|
@@ -70,8 +71,11 @@ from ._api import (
|
|
|
70
71
|
delete,
|
|
71
72
|
download_file_to_stream,
|
|
72
73
|
download_file,
|
|
74
|
+
upload_project_file,
|
|
75
|
+
upload_project_file_from_stream,
|
|
73
76
|
download_project_file,
|
|
74
77
|
download_project_file_to_stream,
|
|
78
|
+
delete_project_file,
|
|
75
79
|
upload_file_from_stream,
|
|
76
80
|
upload_file,
|
|
77
81
|
upload_reviewable,
|
|
@@ -336,6 +340,7 @@ __all__ = (
|
|
|
336
340
|
"get_server_version",
|
|
337
341
|
"get_server_version_tuple",
|
|
338
342
|
"is_product_base_type_supported",
|
|
343
|
+
"links_graphql_support_data",
|
|
339
344
|
"get_users",
|
|
340
345
|
"get_user_by_name",
|
|
341
346
|
"get_user",
|
|
@@ -351,8 +356,11 @@ __all__ = (
|
|
|
351
356
|
"delete",
|
|
352
357
|
"download_file_to_stream",
|
|
353
358
|
"download_file",
|
|
359
|
+
"upload_project_file",
|
|
360
|
+
"upload_project_file_from_stream",
|
|
354
361
|
"download_project_file",
|
|
355
362
|
"download_project_file_to_stream",
|
|
363
|
+
"delete_project_file",
|
|
356
364
|
"upload_file_from_stream",
|
|
357
365
|
"upload_file",
|
|
358
366
|
"upload_reviewable",
|
|
@@ -729,6 +729,13 @@ def is_product_base_type_supported() -> bool:
|
|
|
729
729
|
return con.is_product_base_type_supported()
|
|
730
730
|
|
|
731
731
|
|
|
732
|
+
def links_graphql_support_data() -> bool:
|
|
733
|
+
"""Links data can be received by GraphQl.
|
|
734
|
+
"""
|
|
735
|
+
con = get_server_api_connection()
|
|
736
|
+
return con.links_graphql_support_data()
|
|
737
|
+
|
|
738
|
+
|
|
732
739
|
def get_users(
|
|
733
740
|
project_name: Optional[str] = None,
|
|
734
741
|
usernames: Optional[Iterable[str]] = None,
|
|
@@ -993,6 +1000,99 @@ def download_file(
|
|
|
993
1000
|
)
|
|
994
1001
|
|
|
995
1002
|
|
|
1003
|
+
def upload_project_file(
|
|
1004
|
+
project_name: str,
|
|
1005
|
+
filepath: str,
|
|
1006
|
+
*,
|
|
1007
|
+
content_type: Optional[str] = None,
|
|
1008
|
+
filename: Optional[str] = None,
|
|
1009
|
+
file_id: Optional[str] = None,
|
|
1010
|
+
activity_id: Optional[str] = None,
|
|
1011
|
+
chunk_size: Optional[int] = None,
|
|
1012
|
+
progress: Optional[TransferProgress] = None,
|
|
1013
|
+
) -> requests.Response:
|
|
1014
|
+
"""Upload project file from a filepath.
|
|
1015
|
+
|
|
1016
|
+
Project files are usually binary files, such as images, videos,
|
|
1017
|
+
or other media files that can be accessed via api endpoint
|
|
1018
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1019
|
+
|
|
1020
|
+
Args:
|
|
1021
|
+
project_name (str): Project name.
|
|
1022
|
+
filepath (str): Path where file will be downloaded.
|
|
1023
|
+
content_type (Optional[str]): MIME type of file.
|
|
1024
|
+
filename (Optional[str]): Server filename, filename from filepath
|
|
1025
|
+
is used if not passed.
|
|
1026
|
+
file_id (Optional[str]): File id.
|
|
1027
|
+
activity_id (Optional[str]): To which activity is file related.
|
|
1028
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1029
|
+
in single loop.
|
|
1030
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1031
|
+
to track download progress.
|
|
1032
|
+
|
|
1033
|
+
Returns:
|
|
1034
|
+
requests.Response: Requests response.
|
|
1035
|
+
|
|
1036
|
+
"""
|
|
1037
|
+
con = get_server_api_connection()
|
|
1038
|
+
return con.upload_project_file(
|
|
1039
|
+
project_name=project_name,
|
|
1040
|
+
filepath=filepath,
|
|
1041
|
+
content_type=content_type,
|
|
1042
|
+
filename=filename,
|
|
1043
|
+
file_id=file_id,
|
|
1044
|
+
activity_id=activity_id,
|
|
1045
|
+
chunk_size=chunk_size,
|
|
1046
|
+
progress=progress,
|
|
1047
|
+
)
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
def upload_project_file_from_stream(
|
|
1051
|
+
project_name: str,
|
|
1052
|
+
stream: StreamType,
|
|
1053
|
+
filename: str,
|
|
1054
|
+
*,
|
|
1055
|
+
content_type: Optional[str] = None,
|
|
1056
|
+
file_id: Optional[str] = None,
|
|
1057
|
+
activity_id: Optional[str] = None,
|
|
1058
|
+
chunk_size: Optional[int] = None,
|
|
1059
|
+
progress: Optional[TransferProgress] = None,
|
|
1060
|
+
) -> requests.Response:
|
|
1061
|
+
"""Upload project file from a filepath.
|
|
1062
|
+
|
|
1063
|
+
Project files are usually binary files, such as images, videos,
|
|
1064
|
+
or other media files that can be accessed via api endpoint
|
|
1065
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1066
|
+
|
|
1067
|
+
Args:
|
|
1068
|
+
project_name (str): Project name.
|
|
1069
|
+
stream (StreamType): Stream used as source for upload.
|
|
1070
|
+
filename (str): Name of file on server.
|
|
1071
|
+
content_type (Optional[str]): MIME type of file.
|
|
1072
|
+
file_id (Optional[str]): File id.
|
|
1073
|
+
activity_id (Optional[str]): To which activity is file related.
|
|
1074
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1075
|
+
in single loop.
|
|
1076
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1077
|
+
to track download progress.
|
|
1078
|
+
|
|
1079
|
+
Returns:
|
|
1080
|
+
requests.Response: Requests response.
|
|
1081
|
+
|
|
1082
|
+
"""
|
|
1083
|
+
con = get_server_api_connection()
|
|
1084
|
+
return con.upload_project_file_from_stream(
|
|
1085
|
+
project_name=project_name,
|
|
1086
|
+
stream=stream,
|
|
1087
|
+
filename=filename,
|
|
1088
|
+
content_type=content_type,
|
|
1089
|
+
file_id=file_id,
|
|
1090
|
+
activity_id=activity_id,
|
|
1091
|
+
chunk_size=chunk_size,
|
|
1092
|
+
progress=progress,
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
|
|
996
1096
|
def download_project_file(
|
|
997
1097
|
project_name: str,
|
|
998
1098
|
file_id: str,
|
|
@@ -1067,11 +1167,27 @@ def download_project_file_to_stream(
|
|
|
1067
1167
|
)
|
|
1068
1168
|
|
|
1069
1169
|
|
|
1170
|
+
def delete_project_file(
|
|
1171
|
+
project_name: str,
|
|
1172
|
+
file_id: str,
|
|
1173
|
+
) -> None:
|
|
1174
|
+
"""Delete project file.
|
|
1175
|
+
"""
|
|
1176
|
+
con = get_server_api_connection()
|
|
1177
|
+
return con.delete_project_file(
|
|
1178
|
+
project_name=project_name,
|
|
1179
|
+
file_id=file_id,
|
|
1180
|
+
)
|
|
1181
|
+
|
|
1182
|
+
|
|
1070
1183
|
def upload_file_from_stream(
|
|
1071
1184
|
endpoint: str,
|
|
1072
1185
|
stream: StreamType,
|
|
1073
1186
|
progress: Optional[TransferProgress] = None,
|
|
1074
1187
|
request_type: Optional[RequestType] = None,
|
|
1188
|
+
*,
|
|
1189
|
+
content_type: Optional[str] = None,
|
|
1190
|
+
filename: Optional[str] = None,
|
|
1075
1191
|
**kwargs,
|
|
1076
1192
|
) -> requests.Response:
|
|
1077
1193
|
"""Upload file to server from bytes.
|
|
@@ -1087,6 +1203,8 @@ def upload_file_from_stream(
|
|
|
1087
1203
|
to track upload progress.
|
|
1088
1204
|
request_type (Optional[RequestType]): Type of request that will
|
|
1089
1205
|
be used to upload file.
|
|
1206
|
+
content_type (Optional[str]): MIME type of the file.
|
|
1207
|
+
filename (Optional[str]): Filename of file on server.
|
|
1090
1208
|
**kwargs (Any): Additional arguments that will be passed
|
|
1091
1209
|
to request function.
|
|
1092
1210
|
|
|
@@ -1100,6 +1218,8 @@ def upload_file_from_stream(
|
|
|
1100
1218
|
stream=stream,
|
|
1101
1219
|
progress=progress,
|
|
1102
1220
|
request_type=request_type,
|
|
1221
|
+
content_type=content_type,
|
|
1222
|
+
filename=filename,
|
|
1103
1223
|
**kwargs,
|
|
1104
1224
|
)
|
|
1105
1225
|
|
|
@@ -1109,6 +1229,9 @@ def upload_file(
|
|
|
1109
1229
|
filepath: str,
|
|
1110
1230
|
progress: Optional[TransferProgress] = None,
|
|
1111
1231
|
request_type: Optional[RequestType] = None,
|
|
1232
|
+
*,
|
|
1233
|
+
content_type: Optional[str] = None,
|
|
1234
|
+
filename: Optional[str] = None,
|
|
1112
1235
|
**kwargs,
|
|
1113
1236
|
) -> requests.Response:
|
|
1114
1237
|
"""Upload file to server.
|
|
@@ -1124,6 +1247,8 @@ def upload_file(
|
|
|
1124
1247
|
to track upload progress.
|
|
1125
1248
|
request_type (Optional[RequestType]): Type of request that will
|
|
1126
1249
|
be used to upload file.
|
|
1250
|
+
content_type (Optional[str]): MIME type of the file.
|
|
1251
|
+
filename (Optional[str]): Filename of file on server.
|
|
1127
1252
|
**kwargs (Any): Additional arguments that will be passed
|
|
1128
1253
|
to request function.
|
|
1129
1254
|
|
|
@@ -1137,6 +1262,8 @@ def upload_file(
|
|
|
1137
1262
|
filepath=filepath,
|
|
1138
1263
|
progress=progress,
|
|
1139
1264
|
request_type=request_type,
|
|
1265
|
+
content_type=content_type,
|
|
1266
|
+
filename=filename,
|
|
1140
1267
|
**kwargs,
|
|
1141
1268
|
)
|
|
1142
1269
|
|
|
@@ -2889,6 +3016,7 @@ def get_addon_site_settings(
|
|
|
2889
3016
|
def get_bundle_settings(
|
|
2890
3017
|
bundle_name: Optional[str] = None,
|
|
2891
3018
|
project_name: Optional[str] = None,
|
|
3019
|
+
project_bundle_name: Optional[str] = None,
|
|
2892
3020
|
variant: Optional[str] = None,
|
|
2893
3021
|
site_id: Optional[str] = None,
|
|
2894
3022
|
use_site: bool = True,
|
|
@@ -2928,6 +3056,7 @@ def get_bundle_settings(
|
|
|
2928
3056
|
return con.get_bundle_settings(
|
|
2929
3057
|
bundle_name=bundle_name,
|
|
2930
3058
|
project_name=project_name,
|
|
3059
|
+
project_bundle_name=project_bundle_name,
|
|
2931
3060
|
variant=variant,
|
|
2932
3061
|
site_id=site_id,
|
|
2933
3062
|
use_site=use_site,
|
|
@@ -2936,6 +3065,7 @@ def get_bundle_settings(
|
|
|
2936
3065
|
|
|
2937
3066
|
def get_addons_studio_settings(
|
|
2938
3067
|
bundle_name: Optional[str] = None,
|
|
3068
|
+
project_bundle_name: Optional[str] = None,
|
|
2939
3069
|
variant: Optional[str] = None,
|
|
2940
3070
|
site_id: Optional[str] = None,
|
|
2941
3071
|
use_site: bool = True,
|
|
@@ -2951,6 +3081,8 @@ def get_addons_studio_settings(
|
|
|
2951
3081
|
Args:
|
|
2952
3082
|
bundle_name (Optional[str]): Name of bundle for which should be
|
|
2953
3083
|
settings received.
|
|
3084
|
+
project_bundle_name (Optional[str]): Project bundle name for
|
|
3085
|
+
which should be settings received.
|
|
2954
3086
|
variant (Optional[Literal['production', 'staging']]): Name of
|
|
2955
3087
|
settings variant. Used 'default_settings_variant' by default.
|
|
2956
3088
|
site_id (Optional[str]): Site id for which want to receive
|
|
@@ -2968,6 +3100,7 @@ def get_addons_studio_settings(
|
|
|
2968
3100
|
con = get_server_api_connection()
|
|
2969
3101
|
return con.get_addons_studio_settings(
|
|
2970
3102
|
bundle_name=bundle_name,
|
|
3103
|
+
project_bundle_name=project_bundle_name,
|
|
2971
3104
|
variant=variant,
|
|
2972
3105
|
site_id=site_id,
|
|
2973
3106
|
use_site=use_site,
|
|
@@ -2978,6 +3111,7 @@ def get_addons_studio_settings(
|
|
|
2978
3111
|
def get_addons_project_settings(
|
|
2979
3112
|
project_name: str,
|
|
2980
3113
|
bundle_name: Optional[str] = None,
|
|
3114
|
+
project_bundle_name: Optional[str] = None,
|
|
2981
3115
|
variant: Optional[str] = None,
|
|
2982
3116
|
site_id: Optional[str] = None,
|
|
2983
3117
|
use_site: bool = True,
|
|
@@ -3009,6 +3143,8 @@ def get_addons_project_settings(
|
|
|
3009
3143
|
received.
|
|
3010
3144
|
bundle_name (Optional[str]): Name of bundle for which should be
|
|
3011
3145
|
settings received.
|
|
3146
|
+
project_bundle_name (Optional[str]): Project bundle name for which
|
|
3147
|
+
should be settings received.
|
|
3012
3148
|
variant (Optional[Literal['production', 'staging']]): Name of
|
|
3013
3149
|
settings variant. Used 'default_settings_variant' by default.
|
|
3014
3150
|
site_id (Optional[str]): Site id for which want to receive
|
|
@@ -3028,6 +3164,7 @@ def get_addons_project_settings(
|
|
|
3028
3164
|
return con.get_addons_project_settings(
|
|
3029
3165
|
project_name=project_name,
|
|
3030
3166
|
bundle_name=bundle_name,
|
|
3167
|
+
project_bundle_name=project_bundle_name,
|
|
3031
3168
|
variant=variant,
|
|
3032
3169
|
site_id=site_id,
|
|
3033
3170
|
use_site=use_site,
|
|
@@ -3037,6 +3174,7 @@ def get_addons_project_settings(
|
|
|
3037
3174
|
|
|
3038
3175
|
def get_addons_settings(
|
|
3039
3176
|
bundle_name: Optional[str] = None,
|
|
3177
|
+
project_bundle_name: Optional[str] = None,
|
|
3040
3178
|
project_name: Optional[str] = None,
|
|
3041
3179
|
variant: Optional[str] = None,
|
|
3042
3180
|
site_id: Optional[str] = None,
|
|
@@ -3056,6 +3194,8 @@ def get_addons_settings(
|
|
|
3056
3194
|
Args:
|
|
3057
3195
|
bundle_name (Optional[str]): Name of bundle for which should be
|
|
3058
3196
|
settings received.
|
|
3197
|
+
project_bundle_name (Optional[str]): Name of project bundle
|
|
3198
|
+
for which should be settings received.
|
|
3059
3199
|
project_name (Optional[str]): Name of project for which should be
|
|
3060
3200
|
settings received.
|
|
3061
3201
|
variant (Optional[Literal['production', 'staging']]): Name of
|
|
@@ -3072,6 +3212,7 @@ def get_addons_settings(
|
|
|
3072
3212
|
con = get_server_api_connection()
|
|
3073
3213
|
return con.get_addons_settings(
|
|
3074
3214
|
bundle_name=bundle_name,
|
|
3215
|
+
project_bundle_name=project_bundle_name,
|
|
3075
3216
|
project_name=project_name,
|
|
3076
3217
|
variant=variant,
|
|
3077
3218
|
site_id=site_id,
|
|
@@ -6887,6 +7028,7 @@ def create_link(
|
|
|
6887
7028
|
output_id: str,
|
|
6888
7029
|
output_type: str,
|
|
6889
7030
|
link_name: Optional[str] = None,
|
|
7031
|
+
data: Optional[dict[str, Any]] = None,
|
|
6890
7032
|
) -> CreateLinkData:
|
|
6891
7033
|
"""Create link between 2 entities.
|
|
6892
7034
|
|
|
@@ -6906,7 +7048,8 @@ def create_link(
|
|
|
6906
7048
|
output_id (str): Output entity id.
|
|
6907
7049
|
output_type (str): Entity type of output entity.
|
|
6908
7050
|
link_name (Optional[str]): Name of link.
|
|
6909
|
-
|
|
7051
|
+
data (Optional[dict[str, Any]]): Additional data to be stored
|
|
7052
|
+
with the link.
|
|
6910
7053
|
|
|
6911
7054
|
Returns:
|
|
6912
7055
|
CreateLinkData: Information about link.
|
|
@@ -6924,6 +7067,7 @@ def create_link(
|
|
|
6924
7067
|
output_id=output_id,
|
|
6925
7068
|
output_type=output_type,
|
|
6926
7069
|
link_name=link_name,
|
|
7070
|
+
data=data,
|
|
6927
7071
|
)
|
|
6928
7072
|
|
|
6929
7073
|
|
|
@@ -28,6 +28,9 @@ class BaseServerAPI:
|
|
|
28
28
|
def is_product_base_type_supported(self) -> bool:
|
|
29
29
|
raise NotImplementedError()
|
|
30
30
|
|
|
31
|
+
def links_graphql_support_data(self) -> bool:
|
|
32
|
+
raise NotImplementedError()
|
|
33
|
+
|
|
31
34
|
def get_server_version(self) -> str:
|
|
32
35
|
raise NotImplementedError()
|
|
33
36
|
|
|
@@ -142,6 +145,9 @@ class BaseServerAPI:
|
|
|
142
145
|
):
|
|
143
146
|
raise NotImplementedError()
|
|
144
147
|
|
|
148
|
+
def _prepare_link_fields(self, fields: set[str]) -> None:
|
|
149
|
+
raise NotImplementedError()
|
|
150
|
+
|
|
145
151
|
def _prepare_advanced_filters(
|
|
146
152
|
self, filters: Union[str, dict[str, Any], None]
|
|
147
153
|
) -> Optional[str]:
|
|
@@ -671,6 +671,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
671
671
|
self,
|
|
672
672
|
bundle_name: Optional[str] = None,
|
|
673
673
|
project_name: Optional[str] = None,
|
|
674
|
+
project_bundle_name: Optional[str] = None,
|
|
674
675
|
variant: Optional[str] = None,
|
|
675
676
|
site_id: Optional[str] = None,
|
|
676
677
|
use_site: bool = True,
|
|
@@ -714,6 +715,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
714
715
|
query = prepare_query_string({
|
|
715
716
|
"project_name": project_name or None,
|
|
716
717
|
"bundle_name": bundle_name or None,
|
|
718
|
+
"project_bundle_name": project_bundle_name or None,
|
|
717
719
|
"variant": variant or self.get_default_settings_variant() or None,
|
|
718
720
|
"site_id": site_id,
|
|
719
721
|
})
|
|
@@ -724,6 +726,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
724
726
|
def get_addons_studio_settings(
|
|
725
727
|
self,
|
|
726
728
|
bundle_name: Optional[str] = None,
|
|
729
|
+
project_bundle_name: Optional[str] = None,
|
|
727
730
|
variant: Optional[str] = None,
|
|
728
731
|
site_id: Optional[str] = None,
|
|
729
732
|
use_site: bool = True,
|
|
@@ -739,6 +742,8 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
739
742
|
Args:
|
|
740
743
|
bundle_name (Optional[str]): Name of bundle for which should be
|
|
741
744
|
settings received.
|
|
745
|
+
project_bundle_name (Optional[str]): Project bundle name for
|
|
746
|
+
which should be settings received.
|
|
742
747
|
variant (Optional[Literal['production', 'staging']]): Name of
|
|
743
748
|
settings variant. Used 'default_settings_variant' by default.
|
|
744
749
|
site_id (Optional[str]): Site id for which want to receive
|
|
@@ -755,6 +760,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
755
760
|
"""
|
|
756
761
|
output = self.get_bundle_settings(
|
|
757
762
|
bundle_name=bundle_name,
|
|
763
|
+
project_bundle_name=project_bundle_name,
|
|
758
764
|
variant=variant,
|
|
759
765
|
site_id=site_id,
|
|
760
766
|
use_site=use_site
|
|
@@ -770,6 +776,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
770
776
|
self,
|
|
771
777
|
project_name: str,
|
|
772
778
|
bundle_name: Optional[str] = None,
|
|
779
|
+
project_bundle_name: Optional[str] = None,
|
|
773
780
|
variant: Optional[str] = None,
|
|
774
781
|
site_id: Optional[str] = None,
|
|
775
782
|
use_site: bool = True,
|
|
@@ -801,6 +808,8 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
801
808
|
received.
|
|
802
809
|
bundle_name (Optional[str]): Name of bundle for which should be
|
|
803
810
|
settings received.
|
|
811
|
+
project_bundle_name (Optional[str]): Project bundle name for which
|
|
812
|
+
should be settings received.
|
|
804
813
|
variant (Optional[Literal['production', 'staging']]): Name of
|
|
805
814
|
settings variant. Used 'default_settings_variant' by default.
|
|
806
815
|
site_id (Optional[str]): Site id for which want to receive
|
|
@@ -822,6 +831,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
822
831
|
output = self.get_bundle_settings(
|
|
823
832
|
project_name=project_name,
|
|
824
833
|
bundle_name=bundle_name,
|
|
834
|
+
project_bundle_name=project_bundle_name,
|
|
825
835
|
variant=variant,
|
|
826
836
|
site_id=site_id,
|
|
827
837
|
use_site=use_site
|
|
@@ -836,6 +846,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
836
846
|
def get_addons_settings(
|
|
837
847
|
self,
|
|
838
848
|
bundle_name: Optional[str] = None,
|
|
849
|
+
project_bundle_name: Optional[str] = None,
|
|
839
850
|
project_name: Optional[str] = None,
|
|
840
851
|
variant: Optional[str] = None,
|
|
841
852
|
site_id: Optional[str] = None,
|
|
@@ -855,6 +866,8 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
855
866
|
Args:
|
|
856
867
|
bundle_name (Optional[str]): Name of bundle for which should be
|
|
857
868
|
settings received.
|
|
869
|
+
project_bundle_name (Optional[str]): Name of project bundle
|
|
870
|
+
for which should be settings received.
|
|
858
871
|
project_name (Optional[str]): Name of project for which should be
|
|
859
872
|
settings received.
|
|
860
873
|
variant (Optional[Literal['production', 'staging']]): Name of
|
|
@@ -871,6 +884,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
871
884
|
if project_name is None:
|
|
872
885
|
return self.get_addons_studio_settings(
|
|
873
886
|
bundle_name=bundle_name,
|
|
887
|
+
project_bundle_name=project_bundle_name,
|
|
874
888
|
variant=variant,
|
|
875
889
|
site_id=site_id,
|
|
876
890
|
use_site=use_site,
|
|
@@ -880,6 +894,7 @@ class BundlesAddonsAPI(BaseServerAPI):
|
|
|
880
894
|
return self.get_addons_project_settings(
|
|
881
895
|
project_name=project_name,
|
|
882
896
|
bundle_name=bundle_name,
|
|
897
|
+
project_bundle_name=project_bundle_name,
|
|
883
898
|
variant=variant,
|
|
884
899
|
site_id=site_id,
|
|
885
900
|
use_site=use_site,
|
|
@@ -331,6 +331,8 @@ class FoldersAPI(BaseServerAPI):
|
|
|
331
331
|
if own_attributes:
|
|
332
332
|
fields.add("ownAttrib")
|
|
333
333
|
|
|
334
|
+
self._prepare_link_fields(fields)
|
|
335
|
+
|
|
334
336
|
query = folders_graphql_query(fields)
|
|
335
337
|
for attr, filter_value in graphql_filters.items():
|
|
336
338
|
query.set_variable_value(attr, filter_value)
|
|
@@ -362,6 +362,7 @@ class LinksAPI(BaseServerAPI):
|
|
|
362
362
|
return output
|
|
363
363
|
|
|
364
364
|
link_fields = {"id", "links"}
|
|
365
|
+
self._prepare_link_fields(link_fields)
|
|
365
366
|
query = query_func(link_fields)
|
|
366
367
|
for attr, filter_value in filters.items():
|
|
367
368
|
query.set_variable_value(attr, filter_value)
|
|
@@ -179,6 +179,8 @@ class ProductsAPI(BaseServerAPI):
|
|
|
179
179
|
if filter_value:
|
|
180
180
|
graphql_filters[filter_key] = filter_value
|
|
181
181
|
|
|
182
|
+
self._prepare_link_fields(fields)
|
|
183
|
+
|
|
182
184
|
query = products_graphql_query(fields)
|
|
183
185
|
for attr, filter_value in graphql_filters.items():
|
|
184
186
|
query.set_variable_value(attr, filter_value)
|
|
@@ -106,6 +106,8 @@ class TasksAPI(BaseServerAPI):
|
|
|
106
106
|
if active is not None:
|
|
107
107
|
fields.add("active")
|
|
108
108
|
|
|
109
|
+
self._prepare_link_fields(fields)
|
|
110
|
+
|
|
109
111
|
query = tasks_graphql_query(fields)
|
|
110
112
|
for attr, filter_value in graphql_filters.items():
|
|
111
113
|
query.set_variable_value(attr, filter_value)
|
|
@@ -267,6 +269,8 @@ class TasksAPI(BaseServerAPI):
|
|
|
267
269
|
if active is not None:
|
|
268
270
|
fields.add("active")
|
|
269
271
|
|
|
272
|
+
self._prepare_link_fields(fields)
|
|
273
|
+
|
|
270
274
|
query = tasks_by_folder_paths_graphql_query(fields)
|
|
271
275
|
for attr, filter_value in graphql_filters.items():
|
|
272
276
|
query.set_variable_value(attr, filter_value)
|
|
@@ -87,6 +87,8 @@ class VersionsAPI(BaseServerAPI):
|
|
|
87
87
|
if active is not None:
|
|
88
88
|
fields.add("active")
|
|
89
89
|
|
|
90
|
+
self._prepare_link_fields(fields)
|
|
91
|
+
|
|
90
92
|
if own_attributes is not _PLACEHOLDER:
|
|
91
93
|
warnings.warn(
|
|
92
94
|
(
|
|
@@ -116,7 +118,6 @@ class VersionsAPI(BaseServerAPI):
|
|
|
116
118
|
):
|
|
117
119
|
return
|
|
118
120
|
|
|
119
|
-
|
|
120
121
|
filters = self._prepare_advanced_filters(filters)
|
|
121
122
|
if filters:
|
|
122
123
|
graphql_filters["filter"] = filters
|
|
@@ -1,18 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import collections
|
|
4
|
+
import typing
|
|
2
5
|
|
|
3
6
|
from .constants import DEFAULT_LINK_FIELDS
|
|
4
7
|
from .graphql import FIELD_VALUE, GraphQlQuery, fields_to_dict
|
|
5
8
|
|
|
9
|
+
if typing.TYPE_CHECKING:
|
|
10
|
+
from .graphql import (
|
|
11
|
+
GraphQlQueryEdgeField,
|
|
12
|
+
)
|
|
13
|
+
|
|
6
14
|
|
|
7
|
-
def add_links_fields(
|
|
15
|
+
def add_links_fields(
|
|
16
|
+
entity_field: GraphQlQueryEdgeField,
|
|
17
|
+
nested_fields: dict | None,
|
|
18
|
+
) -> None:
|
|
8
19
|
if "links" not in nested_fields:
|
|
9
20
|
return
|
|
10
21
|
links_fields = nested_fields.pop("links")
|
|
11
|
-
|
|
12
22
|
link_edge_fields = set(DEFAULT_LINK_FIELDS)
|
|
23
|
+
|
|
13
24
|
if isinstance(links_fields, dict):
|
|
14
25
|
simple_fields = set(links_fields)
|
|
15
|
-
|
|
26
|
+
diff = simple_fields - link_edge_fields
|
|
27
|
+
diff.discard("data")
|
|
28
|
+
simple_variant = len(diff) == 0
|
|
16
29
|
else:
|
|
17
30
|
simple_variant = True
|
|
18
31
|
simple_fields = link_edge_fields
|
|
@@ -121,7 +134,7 @@ def product_types_query(fields):
|
|
|
121
134
|
return query
|
|
122
135
|
|
|
123
136
|
|
|
124
|
-
def folders_graphql_query(fields):
|
|
137
|
+
def folders_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
125
138
|
query = GraphQlQuery("FoldersQuery")
|
|
126
139
|
project_name_var = query.add_variable("projectName", "String!")
|
|
127
140
|
folder_ids_var = query.add_variable("folderIds", "[String!]")
|
|
@@ -161,6 +174,7 @@ def folders_graphql_query(fields):
|
|
|
161
174
|
folders_field.set_filter("filter", filter_var)
|
|
162
175
|
|
|
163
176
|
nested_fields = fields_to_dict(fields)
|
|
177
|
+
|
|
164
178
|
add_links_fields(folders_field, nested_fields)
|
|
165
179
|
|
|
166
180
|
query_queue = collections.deque()
|
|
@@ -179,7 +193,7 @@ def folders_graphql_query(fields):
|
|
|
179
193
|
return query
|
|
180
194
|
|
|
181
195
|
|
|
182
|
-
def tasks_graphql_query(fields):
|
|
196
|
+
def tasks_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
183
197
|
query = GraphQlQuery("TasksQuery")
|
|
184
198
|
project_name_var = query.add_variable("projectName", "String!")
|
|
185
199
|
task_ids_var = query.add_variable("taskIds", "[String!]")
|
|
@@ -227,7 +241,7 @@ def tasks_graphql_query(fields):
|
|
|
227
241
|
return query
|
|
228
242
|
|
|
229
243
|
|
|
230
|
-
def tasks_by_folder_paths_graphql_query(fields):
|
|
244
|
+
def tasks_by_folder_paths_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
231
245
|
query = GraphQlQuery("TasksByFolderPathQuery")
|
|
232
246
|
project_name_var = query.add_variable("projectName", "String!")
|
|
233
247
|
task_names_var = query.add_variable("taskNames", "[String!]")
|
|
@@ -258,6 +272,7 @@ def tasks_by_folder_paths_graphql_query(fields):
|
|
|
258
272
|
tasks_field.set_filter("filter", filter_var)
|
|
259
273
|
|
|
260
274
|
nested_fields = fields_to_dict(fields)
|
|
275
|
+
|
|
261
276
|
add_links_fields(tasks_field, nested_fields)
|
|
262
277
|
|
|
263
278
|
query_queue = collections.deque()
|
|
@@ -276,7 +291,7 @@ def tasks_by_folder_paths_graphql_query(fields):
|
|
|
276
291
|
return query
|
|
277
292
|
|
|
278
293
|
|
|
279
|
-
def products_graphql_query(fields):
|
|
294
|
+
def products_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
280
295
|
query = GraphQlQuery("ProductsQuery")
|
|
281
296
|
|
|
282
297
|
project_name_var = query.add_variable("projectName", "String!")
|
|
@@ -326,7 +341,7 @@ def products_graphql_query(fields):
|
|
|
326
341
|
return query
|
|
327
342
|
|
|
328
343
|
|
|
329
|
-
def versions_graphql_query(fields):
|
|
344
|
+
def versions_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
330
345
|
query = GraphQlQuery("VersionsQuery")
|
|
331
346
|
|
|
332
347
|
project_name_var = query.add_variable("projectName", "String!")
|
|
@@ -377,7 +392,7 @@ def versions_graphql_query(fields):
|
|
|
377
392
|
return query
|
|
378
393
|
|
|
379
394
|
|
|
380
|
-
def representations_graphql_query(fields):
|
|
395
|
+
def representations_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
381
396
|
query = GraphQlQuery("RepresentationsQuery")
|
|
382
397
|
|
|
383
398
|
project_name_var = query.add_variable("projectName", "String!")
|
|
@@ -525,7 +540,7 @@ def representations_hierarchy_qraphql_query(
|
|
|
525
540
|
return query
|
|
526
541
|
|
|
527
542
|
|
|
528
|
-
def workfiles_info_graphql_query(fields):
|
|
543
|
+
def workfiles_info_graphql_query(fields: set[str]) -> GraphQlQuery:
|
|
529
544
|
query = GraphQlQuery("WorkfilesInfo")
|
|
530
545
|
project_name_var = query.add_variable("projectName", "String!")
|
|
531
546
|
workfiles_info_ids = query.add_variable("workfileIds", "[String!]")
|
|
@@ -834,8 +834,8 @@ class OperationsSession(object):
|
|
|
834
834
|
if body is not None:
|
|
835
835
|
operations_body.append(body)
|
|
836
836
|
|
|
837
|
-
self._con.
|
|
838
|
-
project_name, operations_body, can_fail=False
|
|
837
|
+
self._con.send_background_batch_operations(
|
|
838
|
+
project_name, operations_body, wait=True, can_fail=False
|
|
839
839
|
)
|
|
840
840
|
|
|
841
841
|
def create_entity(
|
|
@@ -38,6 +38,7 @@ from .constants import (
|
|
|
38
38
|
DEFAULT_ACTIVITY_FIELDS,
|
|
39
39
|
DEFAULT_USER_FIELDS,
|
|
40
40
|
DEFAULT_ENTITY_LIST_FIELDS,
|
|
41
|
+
DEFAULT_LINK_FIELDS,
|
|
41
42
|
)
|
|
42
43
|
from .graphql import INTROSPECTION_QUERY
|
|
43
44
|
from .graphql_queries import users_graphql_query
|
|
@@ -62,6 +63,7 @@ from .utils import (
|
|
|
62
63
|
get_default_site_id,
|
|
63
64
|
NOT_SET,
|
|
64
65
|
get_media_mime_type,
|
|
66
|
+
get_media_mime_type_for_stream,
|
|
65
67
|
get_machine_name,
|
|
66
68
|
fill_own_attribs,
|
|
67
69
|
)
|
|
@@ -328,6 +330,7 @@ class ServerAPI(
|
|
|
328
330
|
|
|
329
331
|
self._graphql_allows_traits_in_representations: Optional[bool] = None
|
|
330
332
|
self._product_base_type_supported = None
|
|
333
|
+
self._links_graphql_support_data = None
|
|
331
334
|
|
|
332
335
|
self._session = None
|
|
333
336
|
|
|
@@ -921,6 +924,15 @@ class ServerAPI(
|
|
|
921
924
|
)
|
|
922
925
|
return self._product_base_type_supported
|
|
923
926
|
|
|
927
|
+
def links_graphql_support_data(self) -> bool:
|
|
928
|
+
"""Links data can be received by GraphQl."""
|
|
929
|
+
if self._links_graphql_support_data is None:
|
|
930
|
+
major, minor, patch, _, _ = self.server_version_tuple
|
|
931
|
+
self._links_graphql_support_data = (
|
|
932
|
+
(major, minor, patch) >= (1, 14, 2)
|
|
933
|
+
)
|
|
934
|
+
return self._links_graphql_support_data
|
|
935
|
+
|
|
924
936
|
def _get_user_info(self) -> Optional[dict[str, Any]]:
|
|
925
937
|
if self._access_token is None:
|
|
926
938
|
return None
|
|
@@ -1414,7 +1426,7 @@ class ServerAPI(
|
|
|
1414
1426
|
if api_prepended:
|
|
1415
1427
|
self.log.warning(
|
|
1416
1428
|
f"Auto-fixed endpoint '{endpoint}' -> 'api/{endpoint}'."
|
|
1417
|
-
" Please fix the
|
|
1429
|
+
" Please fix the endpoint passed to the function."
|
|
1418
1430
|
)
|
|
1419
1431
|
|
|
1420
1432
|
def download_file_to_stream(
|
|
@@ -1517,6 +1529,117 @@ class ServerAPI(
|
|
|
1517
1529
|
|
|
1518
1530
|
return progress
|
|
1519
1531
|
|
|
1532
|
+
def upload_project_file(
|
|
1533
|
+
self,
|
|
1534
|
+
project_name: str,
|
|
1535
|
+
filepath: str,
|
|
1536
|
+
*,
|
|
1537
|
+
content_type: Optional[str] = None,
|
|
1538
|
+
filename: Optional[str] = None,
|
|
1539
|
+
file_id: Optional[str] = None,
|
|
1540
|
+
activity_id: Optional[str] = None,
|
|
1541
|
+
chunk_size: Optional[int] = None,
|
|
1542
|
+
progress: Optional[TransferProgress] = None,
|
|
1543
|
+
) -> requests.Response:
|
|
1544
|
+
"""Upload project file from a filepath.
|
|
1545
|
+
|
|
1546
|
+
Project files are usually binary files, such as images, videos,
|
|
1547
|
+
or other media files that can be accessed via api endpoint
|
|
1548
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1549
|
+
|
|
1550
|
+
Args:
|
|
1551
|
+
project_name (str): Project name.
|
|
1552
|
+
filepath (str): Path where file will be downloaded.
|
|
1553
|
+
content_type (Optional[str]): MIME type of file.
|
|
1554
|
+
filename (Optional[str]): Server filename, filename from filepath
|
|
1555
|
+
is used if not passed.
|
|
1556
|
+
file_id (Optional[str]): File id.
|
|
1557
|
+
activity_id (Optional[str]): To which activity is file related.
|
|
1558
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1559
|
+
in single loop.
|
|
1560
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1561
|
+
to track download progress.
|
|
1562
|
+
|
|
1563
|
+
Returns:
|
|
1564
|
+
requests.Response: Requests response.
|
|
1565
|
+
|
|
1566
|
+
"""
|
|
1567
|
+
if not filename:
|
|
1568
|
+
filename = os.path.basename(filepath)
|
|
1569
|
+
|
|
1570
|
+
if not content_type:
|
|
1571
|
+
content_type = get_media_mime_type(filepath)
|
|
1572
|
+
if not content_type:
|
|
1573
|
+
content_type = "application/octet-stream"
|
|
1574
|
+
|
|
1575
|
+
query = prepare_query_string({
|
|
1576
|
+
"x_file_id": file_id,
|
|
1577
|
+
"x_activity_id": activity_id,
|
|
1578
|
+
})
|
|
1579
|
+
return self.upload_file(
|
|
1580
|
+
f"api/projects/{project_name}/files{query}",
|
|
1581
|
+
filepath,
|
|
1582
|
+
content_type=content_type,
|
|
1583
|
+
filename=filename,
|
|
1584
|
+
chunk_size=chunk_size,
|
|
1585
|
+
progress=progress,
|
|
1586
|
+
request_type=RequestTypes.post,
|
|
1587
|
+
)
|
|
1588
|
+
|
|
1589
|
+
def upload_project_file_from_stream(
|
|
1590
|
+
self,
|
|
1591
|
+
project_name: str,
|
|
1592
|
+
stream: StreamType,
|
|
1593
|
+
filename: str,
|
|
1594
|
+
*,
|
|
1595
|
+
content_type: Optional[str] = None,
|
|
1596
|
+
file_id: Optional[str] = None,
|
|
1597
|
+
activity_id: Optional[str] = None,
|
|
1598
|
+
chunk_size: Optional[int] = None,
|
|
1599
|
+
progress: Optional[TransferProgress] = None,
|
|
1600
|
+
) -> requests.Response:
|
|
1601
|
+
"""Upload project file from a filepath.
|
|
1602
|
+
|
|
1603
|
+
Project files are usually binary files, such as images, videos,
|
|
1604
|
+
or other media files that can be accessed via api endpoint
|
|
1605
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1606
|
+
|
|
1607
|
+
Args:
|
|
1608
|
+
project_name (str): Project name.
|
|
1609
|
+
stream (StreamType): Stream used as source for upload.
|
|
1610
|
+
filename (str): Name of file on server.
|
|
1611
|
+
content_type (Optional[str]): MIME type of file.
|
|
1612
|
+
file_id (Optional[str]): File id.
|
|
1613
|
+
activity_id (Optional[str]): To which activity is file related.
|
|
1614
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1615
|
+
in single loop.
|
|
1616
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1617
|
+
to track download progress.
|
|
1618
|
+
|
|
1619
|
+
Returns:
|
|
1620
|
+
requests.Response: Requests response.
|
|
1621
|
+
|
|
1622
|
+
"""
|
|
1623
|
+
if not content_type:
|
|
1624
|
+
stream.seek(0)
|
|
1625
|
+
content_type = get_media_mime_type_for_stream(stream)
|
|
1626
|
+
if not content_type:
|
|
1627
|
+
content_type = "application/octet-stream"
|
|
1628
|
+
|
|
1629
|
+
query = prepare_query_string({
|
|
1630
|
+
"x_file_id": file_id,
|
|
1631
|
+
"x_activity_id": activity_id,
|
|
1632
|
+
})
|
|
1633
|
+
return self.upload_file_from_stream(
|
|
1634
|
+
f"api/projects/{project_name}/files{query}",
|
|
1635
|
+
stream,
|
|
1636
|
+
content_type=content_type,
|
|
1637
|
+
filename=filename,
|
|
1638
|
+
chunk_size=chunk_size,
|
|
1639
|
+
progress=progress,
|
|
1640
|
+
request_type=RequestTypes.post,
|
|
1641
|
+
)
|
|
1642
|
+
|
|
1520
1643
|
def download_project_file(
|
|
1521
1644
|
self,
|
|
1522
1645
|
project_name: str,
|
|
@@ -1587,6 +1710,11 @@ class ServerAPI(
|
|
|
1587
1710
|
progress=progress,
|
|
1588
1711
|
)
|
|
1589
1712
|
|
|
1713
|
+
def delete_project_file(self, project_name: str, file_id: str) -> None:
|
|
1714
|
+
"""Delete project file."""
|
|
1715
|
+
response = self.delete(f"projects/{project_name}/files/{file_id}")
|
|
1716
|
+
response.raise_for_status()
|
|
1717
|
+
|
|
1590
1718
|
@staticmethod
|
|
1591
1719
|
def _upload_chunks_iter(
|
|
1592
1720
|
file_stream: StreamType,
|
|
@@ -1619,6 +1747,9 @@ class ServerAPI(
|
|
|
1619
1747
|
progress: TransferProgress,
|
|
1620
1748
|
request_type: Optional[RequestType] = None,
|
|
1621
1749
|
chunk_size: Optional[int] = None,
|
|
1750
|
+
*,
|
|
1751
|
+
content_type: Optional[str] = None,
|
|
1752
|
+
filename: Optional[str] = None,
|
|
1622
1753
|
**kwargs
|
|
1623
1754
|
) -> requests.Response:
|
|
1624
1755
|
"""Upload file to server.
|
|
@@ -1646,11 +1777,14 @@ class ServerAPI(
|
|
|
1646
1777
|
url = self._endpoint_to_url(endpoint, use_rest=False)
|
|
1647
1778
|
progress.set_destination_url(url)
|
|
1648
1779
|
|
|
1780
|
+
headers = kwargs.setdefault("headers", {})
|
|
1781
|
+
headers_keys_by_low_key = {key.lower(): key for key in headers}
|
|
1649
1782
|
if self._session is None:
|
|
1650
|
-
headers = kwargs.setdefault("headers", {})
|
|
1651
1783
|
for key, value in self.get_headers().items():
|
|
1652
|
-
|
|
1784
|
+
orig_key = headers_keys_by_low_key.get(key)
|
|
1785
|
+
if not orig_key:
|
|
1653
1786
|
headers[key] = value
|
|
1787
|
+
|
|
1654
1788
|
post_func = self._base_functions_mapping[request_type]
|
|
1655
1789
|
else:
|
|
1656
1790
|
post_func = self._session_functions_mapping[request_type]
|
|
@@ -1658,6 +1792,17 @@ class ServerAPI(
|
|
|
1658
1792
|
if not chunk_size:
|
|
1659
1793
|
chunk_size = self.default_upload_chunk_size
|
|
1660
1794
|
|
|
1795
|
+
for key, value in (
|
|
1796
|
+
("x-file-name", filename),
|
|
1797
|
+
("Content-Type", content_type),
|
|
1798
|
+
):
|
|
1799
|
+
if not value:
|
|
1800
|
+
continue
|
|
1801
|
+
orig_key = headers_keys_by_low_key.get(key.lower())
|
|
1802
|
+
if orig_key:
|
|
1803
|
+
headers.pop(orig_key)
|
|
1804
|
+
headers[key] = value
|
|
1805
|
+
|
|
1661
1806
|
retries = self.get_default_max_retries()
|
|
1662
1807
|
response = None
|
|
1663
1808
|
|
|
@@ -1702,7 +1847,7 @@ class ServerAPI(
|
|
|
1702
1847
|
if api_prepended:
|
|
1703
1848
|
self.log.warning(
|
|
1704
1849
|
f"Auto-fixed endpoint '{endpoint}' -> 'api/{endpoint}'."
|
|
1705
|
-
" Please fix the
|
|
1850
|
+
" Please fix the endpoint passed to the function."
|
|
1706
1851
|
)
|
|
1707
1852
|
return response
|
|
1708
1853
|
|
|
@@ -1712,6 +1857,9 @@ class ServerAPI(
|
|
|
1712
1857
|
stream: StreamType,
|
|
1713
1858
|
progress: Optional[TransferProgress] = None,
|
|
1714
1859
|
request_type: Optional[RequestType] = None,
|
|
1860
|
+
*,
|
|
1861
|
+
content_type: Optional[str] = None,
|
|
1862
|
+
filename: Optional[str] = None,
|
|
1715
1863
|
**kwargs
|
|
1716
1864
|
) -> requests.Response:
|
|
1717
1865
|
"""Upload file to server from bytes.
|
|
@@ -1727,6 +1875,8 @@ class ServerAPI(
|
|
|
1727
1875
|
to track upload progress.
|
|
1728
1876
|
request_type (Optional[RequestType]): Type of request that will
|
|
1729
1877
|
be used to upload file.
|
|
1878
|
+
content_type (Optional[str]): MIME type of the file.
|
|
1879
|
+
filename (Optional[str]): Filename of file on server.
|
|
1730
1880
|
**kwargs (Any): Additional arguments that will be passed
|
|
1731
1881
|
to request function.
|
|
1732
1882
|
|
|
@@ -1747,6 +1897,8 @@ class ServerAPI(
|
|
|
1747
1897
|
stream,
|
|
1748
1898
|
progress,
|
|
1749
1899
|
request_type,
|
|
1900
|
+
content_type=content_type,
|
|
1901
|
+
filename=filename,
|
|
1750
1902
|
**kwargs
|
|
1751
1903
|
)
|
|
1752
1904
|
|
|
@@ -1763,6 +1915,9 @@ class ServerAPI(
|
|
|
1763
1915
|
filepath: str,
|
|
1764
1916
|
progress: Optional[TransferProgress] = None,
|
|
1765
1917
|
request_type: Optional[RequestType] = None,
|
|
1918
|
+
*,
|
|
1919
|
+
content_type: Optional[str] = None,
|
|
1920
|
+
filename: Optional[str] = None,
|
|
1766
1921
|
**kwargs
|
|
1767
1922
|
) -> requests.Response:
|
|
1768
1923
|
"""Upload file to server.
|
|
@@ -1778,6 +1933,8 @@ class ServerAPI(
|
|
|
1778
1933
|
to track upload progress.
|
|
1779
1934
|
request_type (Optional[RequestType]): Type of request that will
|
|
1780
1935
|
be used to upload file.
|
|
1936
|
+
content_type (Optional[str]): MIME type of the file.
|
|
1937
|
+
filename (Optional[str]): Filename of file on server.
|
|
1781
1938
|
**kwargs (Any): Additional arguments that will be passed
|
|
1782
1939
|
to request function.
|
|
1783
1940
|
|
|
@@ -1796,6 +1953,8 @@ class ServerAPI(
|
|
|
1796
1953
|
stream,
|
|
1797
1954
|
progress,
|
|
1798
1955
|
request_type,
|
|
1956
|
+
content_type=content_type,
|
|
1957
|
+
filename=filename,
|
|
1799
1958
|
**kwargs
|
|
1800
1959
|
)
|
|
1801
1960
|
|
|
@@ -1837,24 +1996,9 @@ class ServerAPI(
|
|
|
1837
1996
|
f"Could not determine MIME type of file '{filepath}'"
|
|
1838
1997
|
)
|
|
1839
1998
|
|
|
1840
|
-
if headers is None:
|
|
1841
|
-
headers = self.get_headers(content_type)
|
|
1842
|
-
else:
|
|
1843
|
-
# Make sure content-type is filled with file content type
|
|
1844
|
-
content_type_key = next(
|
|
1845
|
-
(
|
|
1846
|
-
key
|
|
1847
|
-
for key in headers
|
|
1848
|
-
if key.lower() == "content-type"
|
|
1849
|
-
),
|
|
1850
|
-
"Content-Type"
|
|
1851
|
-
)
|
|
1852
|
-
headers[content_type_key] = content_type
|
|
1853
|
-
|
|
1854
1999
|
# Fill original filename if not explicitly defined
|
|
1855
2000
|
if not filename:
|
|
1856
2001
|
filename = os.path.basename(filepath)
|
|
1857
|
-
headers["x-file-name"] = filename
|
|
1858
2002
|
|
|
1859
2003
|
query = prepare_query_string({"label": label or None})
|
|
1860
2004
|
endpoint = (
|
|
@@ -1865,6 +2009,8 @@ class ServerAPI(
|
|
|
1865
2009
|
endpoint,
|
|
1866
2010
|
filepath,
|
|
1867
2011
|
progress=progress,
|
|
2012
|
+
content_type=content_type,
|
|
2013
|
+
filename=filename,
|
|
1868
2014
|
headers=headers,
|
|
1869
2015
|
request_type=RequestTypes.post,
|
|
1870
2016
|
**kwargs
|
|
@@ -2310,6 +2456,17 @@ class ServerAPI(
|
|
|
2310
2456
|
)
|
|
2311
2457
|
}
|
|
2312
2458
|
|
|
2459
|
+
def _prepare_link_fields(self, fields: set[str]) -> None:
|
|
2460
|
+
if "links" not in fields:
|
|
2461
|
+
return
|
|
2462
|
+
|
|
2463
|
+
fields.discard("links")
|
|
2464
|
+
for field in DEFAULT_LINK_FIELDS:
|
|
2465
|
+
fields.add(f"links.{field}")
|
|
2466
|
+
|
|
2467
|
+
if self.links_graphql_support_data():
|
|
2468
|
+
fields.add("links.data")
|
|
2469
|
+
|
|
2313
2470
|
def _prepare_advanced_filters(
|
|
2314
2471
|
self, filters: Union[str, dict[str, Any], None]
|
|
2315
2472
|
) -> Optional[str]:
|
|
@@ -1118,12 +1118,12 @@ def _get_media_mime_type_for_content_base(content: bytes) -> Optional[str]:
|
|
|
1118
1118
|
content_len = len(content)
|
|
1119
1119
|
# Pre-validation (largest definition check)
|
|
1120
1120
|
# - hopefully there cannot be media defined in less than 12 bytes
|
|
1121
|
-
if content_len <
|
|
1121
|
+
if content_len < 4:
|
|
1122
1122
|
return None
|
|
1123
1123
|
|
|
1124
|
-
#
|
|
1125
|
-
if content[4
|
|
1126
|
-
return
|
|
1124
|
+
# PDF
|
|
1125
|
+
if content[0:4] == b"%PDF":
|
|
1126
|
+
return "application/pdf"
|
|
1127
1127
|
|
|
1128
1128
|
# BMP
|
|
1129
1129
|
if content[0:2] == b"BM":
|
|
@@ -1162,6 +1162,14 @@ def _get_media_mime_type_for_content_base(content: bytes) -> Optional[str]:
|
|
|
1162
1162
|
# with this header
|
|
1163
1163
|
if content[0:4] == b"\x00\x00\x01\x00":
|
|
1164
1164
|
return "image/x-icon"
|
|
1165
|
+
|
|
1166
|
+
if content_len < 8:
|
|
1167
|
+
return None
|
|
1168
|
+
|
|
1169
|
+
# FTYP
|
|
1170
|
+
if content[4:8] == b"ftyp":
|
|
1171
|
+
return _get_media_mime_type_from_ftyp(content)
|
|
1172
|
+
|
|
1165
1173
|
return None
|
|
1166
1174
|
|
|
1167
1175
|
|
|
@@ -1172,23 +1180,32 @@ def _get_svg_mime_type(content: bytes) -> Optional[str]:
|
|
|
1172
1180
|
return None
|
|
1173
1181
|
|
|
1174
1182
|
|
|
1183
|
+
def _get_json_mime_type(content: bytes) -> Optional[str]:
|
|
1184
|
+
# json
|
|
1185
|
+
try:
|
|
1186
|
+
json.loads(content.decode("utf-8"))
|
|
1187
|
+
return "application/json"
|
|
1188
|
+
except (UnicodeDecodeError, ValueError):
|
|
1189
|
+
pass
|
|
1190
|
+
return None
|
|
1191
|
+
|
|
1192
|
+
|
|
1175
1193
|
def get_media_mime_type_for_content(content: bytes) -> Optional[str]:
|
|
1176
1194
|
mime_type = _get_media_mime_type_for_content_base(content)
|
|
1177
1195
|
if mime_type is not None:
|
|
1178
1196
|
return mime_type
|
|
1179
|
-
return _get_svg_mime_type(content)
|
|
1197
|
+
return _get_svg_mime_type(content) or _get_json_mime_type(content)
|
|
1180
1198
|
|
|
1181
1199
|
|
|
1182
1200
|
def get_media_mime_type_for_stream(stream: StreamType) -> Optional[str]:
|
|
1183
1201
|
# Read only 12 bytes to determine mime type
|
|
1184
1202
|
content = stream.read(12)
|
|
1185
|
-
if len(content) < 12:
|
|
1186
|
-
return None
|
|
1187
1203
|
mime_type = _get_media_mime_type_for_content_base(content)
|
|
1188
|
-
if mime_type is None:
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1204
|
+
if mime_type is not None:
|
|
1205
|
+
return mime_type
|
|
1206
|
+
|
|
1207
|
+
content += stream.read()
|
|
1208
|
+
return _get_svg_mime_type(content) or _get_json_mime_type(content)
|
|
1192
1209
|
|
|
1193
1210
|
|
|
1194
1211
|
def get_media_mime_type(filepath: str) -> Optional[str]:
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Package declaring Python API for AYON server."""
|
|
2
|
-
__version__ = "1.2.
|
|
2
|
+
__version__ = "1.2.13"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ayon_python_api"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.13"
|
|
4
4
|
description = "AYON Python API"
|
|
5
5
|
license = {file = "LICENSE"}
|
|
6
6
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
@@ -28,7 +28,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
28
28
|
|
|
29
29
|
[tool.poetry]
|
|
30
30
|
name = "ayon_python_api"
|
|
31
|
-
version = "1.2.
|
|
31
|
+
version = "1.2.13"
|
|
32
32
|
description = "AYON Python API"
|
|
33
33
|
authors = [
|
|
34
34
|
"ynput.io <info@ynput.io>"
|
|
@@ -49,4 +49,4 @@ mock = "*"
|
|
|
49
49
|
sphinx-autoapi = "*"
|
|
50
50
|
revitron-sphinx-theme = { git = "https://github.com/revitron/revitron-sphinx-theme.git", branch = "master" }
|
|
51
51
|
pytest = "^6.2.5"
|
|
52
|
-
pydocstyle = "^6.3.0"
|
|
52
|
+
pydocstyle = "^6.3.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_api/_api_helpers/dependency_packages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ayon_python_api-1.2.11 → ayon_python_api-1.2.13}/ayon_python_api.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|