clarifai-grpc 6.4.0__py3-none-any.whl → 11.10.3__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.
- clarifai_grpc/__init__.py +33 -0
- clarifai_grpc/channel/clarifai_channel.py +150 -44
- clarifai_grpc/channel/custom_converters/custom_dict_to_message.py +41 -34
- clarifai_grpc/channel/custom_converters/custom_message_to_dict.py +85 -74
- clarifai_grpc/channel/errors.py +5 -0
- clarifai_grpc/channel/exceptions.py +1 -1
- clarifai_grpc/channel/grpc_json_channel.py +387 -261
- clarifai_grpc/channel/http_client.py +125 -104
- clarifai_grpc/grpc/api/resources_pb2.py +984 -7266
- clarifai_grpc/grpc/api/resources_pb2.pyi +17925 -0
- clarifai_grpc/grpc/api/resources_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/api/service_pb2.py +1578 -8672
- clarifai_grpc/grpc/api/service_pb2.pyi +18269 -0
- clarifai_grpc/grpc/api/service_pb2_grpc.py +9746 -1859
- clarifai_grpc/grpc/api/status/status_code_pb2.py +33 -1334
- clarifai_grpc/grpc/api/status/status_code_pb2.pyi +1210 -0
- clarifai_grpc/grpc/api/status/status_code_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/api/status/status_pb2.py +23 -149
- clarifai_grpc/grpc/api/status/status_pb2.pyi +174 -0
- clarifai_grpc/grpc/api/status/status_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/api/utils/extensions_pb2.py +13 -46
- clarifai_grpc/grpc/api/utils/extensions_pb2.pyi +39 -0
- clarifai_grpc/grpc/api/utils/extensions_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/api/utils/matrix_pb2.py +26 -0
- clarifai_grpc/grpc/api/utils/matrix_pb2.pyi +53 -0
- clarifai_grpc/grpc/api/utils/matrix_pb2_grpc.py +4 -0
- clarifai_grpc/grpc/api/utils/test_proto_pb2.py +17 -158
- clarifai_grpc/grpc/api/utils/test_proto_pb2.pyi +107 -0
- clarifai_grpc/grpc/api/utils/test_proto_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/auth/scope/scope_pb2.py +245 -448
- clarifai_grpc/grpc/auth/scope/scope_pb2.pyi +550 -0
- clarifai_grpc/grpc/auth/scope/scope_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/auth/types/types_pb2.py +11 -62
- clarifai_grpc/grpc/auth/types/types_pb2.pyi +78 -0
- clarifai_grpc/grpc/auth/types/types_pb2_grpc.py +1 -0
- clarifai_grpc/grpc/auth/util/extension_pb2.py +14 -68
- clarifai_grpc/grpc/auth/util/extension_pb2.pyi +68 -0
- clarifai_grpc/grpc/auth/util/extension_pb2_grpc.py +1 -0
- clarifai_grpc-11.10.3.dist-info/METADATA +124 -0
- clarifai_grpc-11.10.3.dist-info/RECORD +53 -0
- {clarifai_grpc-6.4.0.dist-info → clarifai_grpc-11.10.3.dist-info}/WHEEL +1 -1
- {clarifai_grpc-6.4.0.dist-info → clarifai_grpc-11.10.3.dist-info}/top_level.txt +0 -2
- clarifai_grpc-6.4.0.dist-info/METADATA +0 -88
- clarifai_grpc-6.4.0.dist-info/RECORD +0 -46
- scripts/__init__.py +0 -0
- scripts/app_and_key_for_tests.py +0 -180
- tests/__init__.py +0 -0
- tests/helpers.py +0 -105
- tests/test_integration.py +0 -243
- {clarifai_grpc-6.4.0.dist-info → clarifai_grpc-11.10.3.dist-info/licenses}/LICENSE +0 -0
clarifai_grpc/__init__.py
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
__version__ = "11.10.3"
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
# pop off env var set to the old python implementation
|
|
6
|
+
unset = False
|
|
7
|
+
if os.environ.get('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', None) == 'python':
|
|
8
|
+
unset = True
|
|
9
|
+
os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION')
|
|
10
|
+
# Don't use the clarifai logger since it is in the SDK package and depends on protobuf.
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
if unset:
|
|
16
|
+
logger.warning(
|
|
17
|
+
"Unsetting PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python env var while importing clarifai package. It's best to unset this env var in your environemnt for faster performance."
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from google.protobuf.internal import api_implementation
|
|
22
|
+
|
|
23
|
+
if api_implementation.Type() == 'python':
|
|
24
|
+
logger.warning(
|
|
25
|
+
"The python version of google protobuf is being used. We recommend that you upgrade the protobuf package >=4.21.0 to use the upd version which is much faster."
|
|
26
|
+
)
|
|
27
|
+
# and not os.environ.get('CLARIFAI_SKIP_PROTOBUF_CHECK', 'false') == 'true'
|
|
28
|
+
# ):
|
|
29
|
+
# raise Exception(
|
|
30
|
+
# "We do not recommend running this library with the Python implementation of Protocol Buffers. Please check your installation to use the cpp or upb implementation. We recommend setting the environment variable PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=upb. You can skip this check by setting CLARIFAI_SKIP_PROTOBUF_CHECK=true"
|
|
31
|
+
# )
|
|
32
|
+
except ImportError:
|
|
33
|
+
pass
|
|
@@ -1,61 +1,167 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import os
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
import grpc
|
|
4
5
|
|
|
5
6
|
from clarifai_grpc.channel.grpc_json_channel import GRPCJSONChannel
|
|
6
|
-
from clarifai_grpc.grpc.api import service_pb2_grpc
|
|
7
|
-
|
|
8
7
|
|
|
9
8
|
RETRIES = 2 # if connections fail retry a couple times.
|
|
10
|
-
CONNECTIONS =
|
|
9
|
+
CONNECTIONS = (
|
|
10
|
+
20 # number of connections to maintain in pool, only usd for json channel, not direct GRPC.
|
|
11
|
+
)
|
|
12
|
+
MAX_MESSAGE_LENGTH = 1024 * 1024 * 1024 # 1GB
|
|
11
13
|
|
|
12
14
|
wrap_response_deserializer = None
|
|
13
15
|
|
|
16
|
+
grpc_json_config = json.dumps(
|
|
17
|
+
{
|
|
18
|
+
"methodConfig": [
|
|
19
|
+
{
|
|
20
|
+
"name": [{"service": "clarifai.api.V2"}],
|
|
21
|
+
"retryPolicy": {
|
|
22
|
+
"maxAttempts": 5,
|
|
23
|
+
"initialBackoff": "0.01s",
|
|
24
|
+
"maxBackoff": "5s",
|
|
25
|
+
"backoffMultiplier": 2,
|
|
26
|
+
"retryableStatusCodes": ["UNAVAILABLE"],
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
|
|
14
33
|
|
|
15
34
|
def _response_deserializer_for_json(response_deserializer):
|
|
16
|
-
|
|
35
|
+
return response_deserializer
|
|
17
36
|
|
|
18
37
|
|
|
19
38
|
def _response_deserializer_for_grpc(response_deserializer):
|
|
20
|
-
|
|
39
|
+
return response_deserializer.FromString
|
|
21
40
|
|
|
22
41
|
|
|
23
42
|
class ClarifaiChannel:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
43
|
+
@classmethod
|
|
44
|
+
def get_json_channel(
|
|
45
|
+
cls, base_url=os.environ.get("CLARIFAI_API_BASE", "https://api.clarifai.com")
|
|
46
|
+
):
|
|
47
|
+
global wrap_response_deserializer
|
|
48
|
+
wrap_response_deserializer = _response_deserializer_for_json
|
|
49
|
+
|
|
50
|
+
session = cls._make_requests_session()
|
|
51
|
+
|
|
52
|
+
return GRPCJSONChannel(session=session, base_url=base_url)
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def _make_requests_session():
|
|
56
|
+
import requests # noqa
|
|
57
|
+
|
|
58
|
+
http_adapter = requests.adapters.HTTPAdapter(
|
|
59
|
+
max_retries=RETRIES, pool_connections=CONNECTIONS, pool_maxsize=CONNECTIONS
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
session = requests.Session()
|
|
63
|
+
session.mount("http://", http_adapter)
|
|
64
|
+
session.mount("https://", http_adapter)
|
|
65
|
+
return session
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def get_grpc_channel(base=None, root_certificates_path=None):
|
|
69
|
+
global wrap_response_deserializer
|
|
70
|
+
wrap_response_deserializer = _response_deserializer_for_grpc
|
|
71
|
+
|
|
72
|
+
if not base:
|
|
73
|
+
base = os.environ.get("CLARIFAI_GRPC_BASE", "api.clarifai.com")
|
|
74
|
+
if base.startswith("http:") or base.startswith("https:"):
|
|
75
|
+
raise ValueError(
|
|
76
|
+
"For secure channels the 'base' passed via arguments or env variable CLARIFAI_GRPC_BASE should not start with http:// or https:// but be a direct api endpoint like 'api.clarifai.com'"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if root_certificates_path:
|
|
80
|
+
with open(root_certificates_path, "rb") as f:
|
|
81
|
+
root_certificates = f.read()
|
|
82
|
+
credentials = grpc.ssl_channel_credentials(root_certificates)
|
|
83
|
+
else:
|
|
84
|
+
credentials = grpc.ssl_channel_credentials()
|
|
85
|
+
|
|
86
|
+
return grpc.secure_channel(
|
|
87
|
+
base,
|
|
88
|
+
credentials,
|
|
89
|
+
options=[
|
|
90
|
+
("grpc.service_config", grpc_json_config),
|
|
91
|
+
("grpc.max_receive_message_length", MAX_MESSAGE_LENGTH),
|
|
92
|
+
("grpc.max_send_message_length", MAX_MESSAGE_LENGTH),
|
|
93
|
+
],
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def get_insecure_grpc_channel(base=None, port=18080):
|
|
98
|
+
global wrap_response_deserializer
|
|
99
|
+
wrap_response_deserializer = _response_deserializer_for_grpc
|
|
100
|
+
|
|
101
|
+
if not base:
|
|
102
|
+
base = os.environ.get("CLARIFAI_GRPC_BASE", None)
|
|
103
|
+
|
|
104
|
+
if not base:
|
|
105
|
+
raise ValueError("Please set 'base' via arguments or env variable CLARIFAI_GRPC_BASE")
|
|
106
|
+
|
|
107
|
+
channel_address = "{}:{}".format(base, port)
|
|
108
|
+
|
|
109
|
+
return grpc.insecure_channel(
|
|
110
|
+
channel_address,
|
|
111
|
+
options=[
|
|
112
|
+
("grpc.service_config", grpc_json_config),
|
|
113
|
+
("grpc.max_receive_message_length", MAX_MESSAGE_LENGTH),
|
|
114
|
+
("grpc.max_send_message_length", MAX_MESSAGE_LENGTH),
|
|
115
|
+
],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def get_aio_grpc_channel(base=None, root_certificates_path=None):
|
|
120
|
+
global wrap_response_deserializer
|
|
121
|
+
wrap_response_deserializer = _response_deserializer_for_grpc
|
|
122
|
+
|
|
123
|
+
if not base:
|
|
124
|
+
base = os.environ.get("CLARIFAI_GRPC_BASE", "api.clarifai.com")
|
|
125
|
+
if base.startswith("http:") or base.startswith("https:"):
|
|
126
|
+
raise ValueError(
|
|
127
|
+
"For secure channels the 'base' passed via arguments or env variable CLARIFAI_GRPC_BASE should not start with http:// or https:// but be a direct api endpoint like 'api.clarifai.com'"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if root_certificates_path:
|
|
131
|
+
with open(root_certificates_path, "rb") as f:
|
|
132
|
+
root_certificates = f.read()
|
|
133
|
+
credentials = grpc.ssl_channel_credentials(root_certificates)
|
|
134
|
+
else:
|
|
135
|
+
credentials = grpc.ssl_channel_credentials()
|
|
136
|
+
|
|
137
|
+
return grpc.aio.secure_channel(
|
|
138
|
+
base,
|
|
139
|
+
credentials,
|
|
140
|
+
options=[
|
|
141
|
+
("grpc.service_config", grpc_json_config),
|
|
142
|
+
("grpc.max_receive_message_length", MAX_MESSAGE_LENGTH),
|
|
143
|
+
("grpc.max_send_message_length", MAX_MESSAGE_LENGTH),
|
|
144
|
+
],
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def get_aio_insecure_grpc_channel(base=None, port=18080):
|
|
149
|
+
global wrap_response_deserializer
|
|
150
|
+
wrap_response_deserializer = _response_deserializer_for_grpc
|
|
151
|
+
|
|
152
|
+
if not base:
|
|
153
|
+
base = os.environ.get("CLARIFAI_GRPC_BASE", None)
|
|
154
|
+
|
|
155
|
+
if not base:
|
|
156
|
+
raise ValueError("Please set 'base' via arguments or env variable CLARIFAI_GRPC_BASE")
|
|
157
|
+
|
|
158
|
+
channel_address = "{}:{}".format(base, port)
|
|
159
|
+
|
|
160
|
+
return grpc.aio.insecure_channel(
|
|
161
|
+
channel_address,
|
|
162
|
+
options=[
|
|
163
|
+
("grpc.service_config", grpc_json_config),
|
|
164
|
+
("grpc.max_receive_message_length", MAX_MESSAGE_LENGTH),
|
|
165
|
+
("grpc.max_send_message_length", MAX_MESSAGE_LENGTH),
|
|
166
|
+
],
|
|
167
|
+
)
|
|
@@ -3,43 +3,50 @@ from google.protobuf.message import Message # noqa
|
|
|
3
3
|
|
|
4
4
|
from clarifai_grpc.grpc.api.utils import extensions_pb2
|
|
5
5
|
|
|
6
|
-
# Python 3 deprecates getargspec and introduces getfullargspec, which Python 2 doesn't have.
|
|
7
|
-
try:
|
|
8
|
-
from inspect import getfullargspec as get_args
|
|
9
|
-
except ImportError:
|
|
10
|
-
from inspect import getargspec as get_args
|
|
11
6
|
|
|
7
|
+
def dict_to_protobuf(
|
|
8
|
+
protobuf_class,
|
|
9
|
+
js_dict,
|
|
10
|
+
ignore_unknown_fields=False,
|
|
11
|
+
descriptor_pool=None,
|
|
12
|
+
max_recursion_depth=100,
|
|
13
|
+
):
|
|
14
|
+
"""Parses a JSON dictionary representation into a message.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
js_dict: Dict representation of a JSON message.
|
|
18
|
+
message: A protocol buffer message to merge into.
|
|
19
|
+
ignore_unknown_fields: If True, do not raise errors for unknown fields.
|
|
20
|
+
descriptor_pool: A Descriptor Pool for resolving types. If None use the
|
|
21
|
+
default.
|
|
22
|
+
max_recursion_depth: max recursion depth of JSON message to be
|
|
23
|
+
deserialized. JSON messages over this depth will fail to be
|
|
24
|
+
deserialized. Default value is 100.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
The same message passed as argument.
|
|
28
|
+
"""
|
|
29
|
+
message = protobuf_class()
|
|
12
30
|
|
|
13
|
-
|
|
14
|
-
# type: (type(Message), dict, bool) -> Message
|
|
15
|
-
message = protobuf_class()
|
|
16
|
-
|
|
17
|
-
# Protobuf versions 3.6.* and 3.7.0 require a different number of parameters in the _Parser's
|
|
18
|
-
# constructor. In the case of 3.6.*, we pass only the argument ignore_unknown_fields, but in
|
|
19
|
-
# the case of 3.7.0, we pass in one additional None parameter. To be future proof(ish), pass in
|
|
20
|
-
# None to any subsequent parameter.
|
|
21
|
-
num_of_args = len(get_args(_Parser.__init__).args)
|
|
22
|
-
none_args = [None] * (num_of_args - 2) # Subtract 2 for self and ignore_unknown_fields.
|
|
23
|
-
parser = _CustomParser(ignore_unknown_fields, *none_args)
|
|
31
|
+
parser = _CustomParser(ignore_unknown_fields, descriptor_pool, max_recursion_depth)
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
parser.ConvertMessage(js_dict, message, path="")
|
|
34
|
+
return message
|
|
27
35
|
|
|
28
36
|
|
|
29
37
|
class _CustomParser(_Parser):
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
super(_CustomParser, self)._ConvertFieldValuePair(js, message)
|
|
38
|
+
def _ConvertFieldValuePair(self, js, message, path):
|
|
39
|
+
"""
|
|
40
|
+
Because of fields with custom extensions such as cl_default_float, we need
|
|
41
|
+
to adjust the original's method's JSON object parameter by setting them explicitly to the
|
|
42
|
+
default value.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
message_descriptor = message.DESCRIPTOR
|
|
46
|
+
for f in message_descriptor.fields:
|
|
47
|
+
default_float = f.GetOptions().Extensions[extensions_pb2.cl_default_float]
|
|
48
|
+
if default_float:
|
|
49
|
+
if f.name not in js:
|
|
50
|
+
js[f.name] = default_float
|
|
51
|
+
|
|
52
|
+
super(_CustomParser, self)._ConvertFieldValuePair(js, message, path)
|
|
@@ -8,81 +8,92 @@ from clarifai_grpc.grpc.api.utils import extensions_pb2
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def protobuf_to_dict(object_protobuf, use_integers_for_enums=True, ignore_show_empty=False):
|
|
11
|
-
|
|
11
|
+
# type: (Message, typing.Optional[bool], typing.Optional[bool]) -> dict
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
# printer = _CustomPrinter(
|
|
14
|
+
printer = _CustomPrinter(
|
|
15
|
+
including_default_value_fields=False,
|
|
16
|
+
preserving_proto_field_name=True,
|
|
17
|
+
use_integers_for_enums=use_integers_for_enums,
|
|
18
|
+
ignore_show_empty=ignore_show_empty,
|
|
19
|
+
)
|
|
20
|
+
# pylint: disable=protected-access
|
|
21
|
+
return printer._MessageToJsonObject(object_protobuf)
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class _CustomPrinter(_Printer):
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
including_default_value_fields,
|
|
29
|
+
preserving_proto_field_name,
|
|
30
|
+
use_integers_for_enums,
|
|
31
|
+
ignore_show_empty,
|
|
32
|
+
):
|
|
33
|
+
super(_CustomPrinter, self).__init__(
|
|
34
|
+
always_print_fields_with_no_presence=including_default_value_fields,
|
|
35
|
+
preserving_proto_field_name=preserving_proto_field_name,
|
|
36
|
+
use_integers_for_enums=use_integers_for_enums,
|
|
37
|
+
)
|
|
38
|
+
self._ignore_show_empty = ignore_show_empty
|
|
39
|
+
|
|
40
|
+
def _RegularMessageToJsonObject(self, message, js):
|
|
41
|
+
"""
|
|
42
|
+
Because of the fields with the custom extension `cl_show_if_empty`, we need to adjust the
|
|
43
|
+
original's method's return JSON object and keep these fields.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
js = super(_CustomPrinter, self)._RegularMessageToJsonObject(message, js)
|
|
47
|
+
|
|
48
|
+
message_descriptor = message.DESCRIPTOR
|
|
49
|
+
for field in message_descriptor.fields:
|
|
50
|
+
if (
|
|
51
|
+
self._ignore_show_empty
|
|
52
|
+
and not field.GetOptions().Extensions[extensions_pb2.cl_default_float]
|
|
53
|
+
):
|
|
54
|
+
continue
|
|
55
|
+
if not field.GetOptions().Extensions[extensions_pb2.cl_show_if_empty]:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
# Singular message fields and oneof fields will not be affected.
|
|
59
|
+
if (
|
|
60
|
+
field.label != descriptor.FieldDescriptor.LABEL_REPEATED
|
|
61
|
+
and field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE
|
|
62
|
+
) or field.containing_oneof:
|
|
63
|
+
continue
|
|
64
|
+
if self.preserving_proto_field_name:
|
|
65
|
+
name = field.name
|
|
66
|
+
else:
|
|
67
|
+
name = field.json_name
|
|
68
|
+
if name in js:
|
|
69
|
+
# Skip the field which has been serialized already.
|
|
70
|
+
continue
|
|
71
|
+
if _IsMapEntry(field):
|
|
72
|
+
js[name] = {}
|
|
73
|
+
elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
|
|
74
|
+
js[name] = []
|
|
75
|
+
else:
|
|
76
|
+
js[name] = self._FieldToJsonObject(field, field.default_value)
|
|
77
|
+
|
|
78
|
+
return js
|
|
79
|
+
|
|
80
|
+
def _StructMessageToJsonObject(self, message):
|
|
81
|
+
"""
|
|
82
|
+
Converts Struct message according to Proto3 JSON Specification.
|
|
83
|
+
|
|
84
|
+
However, by default, empty objects {} get converted to null. We overwrite this behavior so {}
|
|
85
|
+
get converted to {}.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
fields = message.fields
|
|
89
|
+
ret = {}
|
|
90
|
+
for key in fields:
|
|
91
|
+
# When there's a Struct with an empty Struct field, this condition will hold True.
|
|
92
|
+
# Far as I know this is the only case this condition will be true. If not, this condition
|
|
93
|
+
# needs to be amended.
|
|
94
|
+
if fields[key].WhichOneof("kind") is None:
|
|
95
|
+
json_object = {}
|
|
96
|
+
else:
|
|
97
|
+
json_object = self._ValueMessageToJsonObject(fields[key])
|
|
98
|
+
ret[key] = json_object
|
|
99
|
+
return ret
|
clarifai_grpc/channel/errors.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
class ClarifaiException(Exception):
|
|
2
|
-
|
|
2
|
+
pass
|