libentry 1.11.4__py3-none-any.whl → 1.11.5__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.
- libentry/api.py +20 -1
- libentry/service/flask.py +33 -22
- {libentry-1.11.4.dist-info → libentry-1.11.5.dist-info}/METADATA +1 -1
- {libentry-1.11.4.dist-info → libentry-1.11.5.dist-info}/RECORD +8 -8
- {libentry-1.11.4.dist-info → libentry-1.11.5.dist-info}/LICENSE +0 -0
- {libentry-1.11.4.dist-info → libentry-1.11.5.dist-info}/WHEEL +0 -0
- {libentry-1.11.4.dist-info → libentry-1.11.5.dist-info}/top_level.txt +0 -0
- {libentry-1.11.4.dist-info → libentry-1.11.5.dist-info}/zip-safe +0 -0
libentry/api.py
CHANGED
@@ -31,6 +31,7 @@ class APIInfo:
|
|
31
31
|
chunk_suffix: str = field(default=None)
|
32
32
|
stream_prefix: str = field(default=None)
|
33
33
|
stream_suffix: str = field(default=None)
|
34
|
+
error_prefix: str = field(default="ERROR: ")
|
34
35
|
extra_info: Mapping[str, Any] = field(default_factory=dict)
|
35
36
|
|
36
37
|
|
@@ -212,6 +213,7 @@ class APIClient:
|
|
212
213
|
chunk_delimiter: str = "\n\n",
|
213
214
|
chunk_prefix: str = None,
|
214
215
|
chunk_suffix: str = None,
|
216
|
+
error_prefix: str = "ERROR: "
|
215
217
|
):
|
216
218
|
full_url = urljoin(self.base_url, path)
|
217
219
|
|
@@ -239,6 +241,7 @@ class APIClient:
|
|
239
241
|
chunk_delimiter=chunk_delimiter.encode() if chunk_delimiter else None,
|
240
242
|
chunk_prefix=chunk_prefix.encode() if chunk_prefix else None,
|
241
243
|
chunk_suffix=chunk_suffix.encode() if chunk_suffix else None,
|
244
|
+
error_prefix=error_prefix.encode() if error_prefix else None,
|
242
245
|
)
|
243
246
|
else:
|
244
247
|
try:
|
@@ -251,13 +254,26 @@ class APIClient:
|
|
251
254
|
response: requests.Response,
|
252
255
|
chunk_delimiter: bytes,
|
253
256
|
chunk_prefix: bytes,
|
254
|
-
chunk_suffix: bytes
|
257
|
+
chunk_suffix: bytes,
|
258
|
+
error_prefix: bytes
|
255
259
|
) -> Iterable:
|
256
260
|
try:
|
261
|
+
error = None
|
257
262
|
for chunk in response.iter_lines(decode_unicode=False, delimiter=chunk_delimiter):
|
263
|
+
if error is not None:
|
264
|
+
# error is not None means there is a fatal exception raised from the server side.
|
265
|
+
# The client should just complete the stream and then raise the error to the upper.
|
266
|
+
continue
|
267
|
+
|
258
268
|
if not chunk:
|
259
269
|
continue
|
260
270
|
|
271
|
+
if error_prefix is not None:
|
272
|
+
if chunk.startswith(error_prefix):
|
273
|
+
chunk = chunk[len(error_prefix):]
|
274
|
+
error = ServiceError(chunk)
|
275
|
+
continue
|
276
|
+
|
261
277
|
if chunk_prefix is not None:
|
262
278
|
if chunk.startswith(chunk_prefix):
|
263
279
|
chunk = chunk[len(chunk_prefix):]
|
@@ -271,5 +287,8 @@ class APIClient:
|
|
271
287
|
continue
|
272
288
|
|
273
289
|
yield _load_json_or_str(chunk)
|
290
|
+
|
291
|
+
if error is not None:
|
292
|
+
raise error
|
274
293
|
finally:
|
275
294
|
response.close()
|
libentry/service/flask.py
CHANGED
@@ -33,16 +33,27 @@ class JSONDumper:
|
|
33
33
|
if self.api_info.chunk_delimiter is not None:
|
34
34
|
yield self.api_info.chunk_delimiter
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
try:
|
37
|
+
for item in response:
|
38
|
+
text = self.dump(item)
|
38
39
|
|
39
|
-
|
40
|
-
|
40
|
+
if self.api_info.chunk_prefix is not None:
|
41
|
+
yield self.api_info.chunk_prefix
|
41
42
|
|
42
|
-
|
43
|
+
yield text
|
43
44
|
|
44
|
-
|
45
|
-
|
45
|
+
if self.api_info.chunk_suffix is not None:
|
46
|
+
yield self.api_info.chunk_suffix
|
47
|
+
|
48
|
+
if self.api_info.chunk_delimiter is not None:
|
49
|
+
yield self.api_info.chunk_delimiter
|
50
|
+
except Exception as e:
|
51
|
+
if isinstance(e, (SystemExit, KeyboardInterrupt)):
|
52
|
+
raise e
|
53
|
+
if self.api_info.error_prefix is not None:
|
54
|
+
yield self.api_info.error_prefix
|
55
|
+
|
56
|
+
yield self.dump_error(e)
|
46
57
|
|
47
58
|
if self.api_info.chunk_delimiter is not None:
|
48
59
|
yield self.api_info.chunk_delimiter
|
@@ -65,6 +76,19 @@ class JSONDumper:
|
|
65
76
|
except TypeError:
|
66
77
|
return repr(response)
|
67
78
|
|
79
|
+
@staticmethod
|
80
|
+
def dump_error(e: Exception) -> str:
|
81
|
+
err_cls = e.__class__
|
82
|
+
err_name = err_cls.__name__
|
83
|
+
module = err_cls.__module__
|
84
|
+
if module != "builtins":
|
85
|
+
err_name = f"{module}.{err_name}"
|
86
|
+
return json.dumps({
|
87
|
+
"error": err_name,
|
88
|
+
"message": str(e),
|
89
|
+
"traceback": traceback.format_exc()
|
90
|
+
}, indent=2)
|
91
|
+
|
68
92
|
|
69
93
|
def create_model_from_signature(fn):
|
70
94
|
sig = signature(fn)
|
@@ -122,14 +146,14 @@ class FlaskWrapper:
|
|
122
146
|
except Exception as e:
|
123
147
|
if isinstance(e, (SystemExit, KeyboardInterrupt)):
|
124
148
|
raise e
|
125
|
-
return self.app.error(self.
|
149
|
+
return self.app.error(self.dumper.dump_error(e))
|
126
150
|
else:
|
127
151
|
try:
|
128
152
|
response = self.fn(**input_json)
|
129
153
|
except Exception as e:
|
130
154
|
if isinstance(e, (SystemExit, KeyboardInterrupt)):
|
131
155
|
raise e
|
132
|
-
return self.app.error(self.
|
156
|
+
return self.app.error(self.dumper.dump_error(e))
|
133
157
|
|
134
158
|
if isinstance(response, (GeneratorType, range)):
|
135
159
|
return self.app.response_class(
|
@@ -142,19 +166,6 @@ class FlaskWrapper:
|
|
142
166
|
mimetype=self.api_info.mime_type
|
143
167
|
)
|
144
168
|
|
145
|
-
@staticmethod
|
146
|
-
def make_err(e):
|
147
|
-
err_cls = e.__class__
|
148
|
-
err_name = err_cls.__name__
|
149
|
-
module = err_cls.__module__
|
150
|
-
if module != "builtins":
|
151
|
-
err_name = f"{module}.{err_name}"
|
152
|
-
return json.dumps({
|
153
|
-
"error": err_name,
|
154
|
-
"message": str(e),
|
155
|
-
"traceback": traceback.format_exc()
|
156
|
-
}, indent=2)
|
157
|
-
|
158
169
|
|
159
170
|
class CustomGenerateJsonSchema(GenerateJsonSchema):
|
160
171
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
libentry/__init__.py,sha256=rDBip9M1Xb1N4wMKE1ni_DldrQbkRjp8DxPkTp3K2qo,170
|
2
|
-
libentry/api.py,sha256=
|
2
|
+
libentry/api.py,sha256=2LWDPP3QJRmwk5WfNI9y57uqjjEQilojlLg6v4pbuPk,8746
|
3
3
|
libentry/argparse.py,sha256=Bk11H4WRKxcjMlSd0mjWj1T4NWh0JW5eA7TX3C21IoE,10116
|
4
4
|
libentry/dataclasses.py,sha256=AQV2PuxplJCwGZ5HKX72U-z-POUhTdy3XtpEK9KNIGQ,4541
|
5
5
|
libentry/executor.py,sha256=cTV0WxJi0nU1TP-cOwmeodN8DD6L1691M2HIQsJtGrU,6582
|
@@ -9,14 +9,14 @@ libentry/logging.py,sha256=IiYoCUzm8XTK1fduA-NA0FI2Qz_m81NEPV3d3tEfgdI,1349
|
|
9
9
|
libentry/server.py,sha256=gYPoZXd0umlDYZf-6ZV0_vJadg3YQvnLDc6JFDJh9jc,1503
|
10
10
|
libentry/service/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
|
11
11
|
libentry/service/common.py,sha256=OVaW2afgKA6YqstJmtnprBCqQEUZEWotZ6tHavmJJeU,42
|
12
|
-
libentry/service/flask.py,sha256=
|
12
|
+
libentry/service/flask.py,sha256=jPpOSkxPRz0ma1d-O4zyqbxfy-XrEE2Hku-ccaCADNE,9627
|
13
13
|
libentry/service/list.py,sha256=ElHWhTgShGOhaxMUEwVbMXos0NQKjHsODboiQ-3AMwE,1397
|
14
14
|
libentry/service/running.py,sha256=FrPJoJX6wYxcHIysoatAxhW3LajCCm0Gx6l7__6sULQ,5105
|
15
15
|
libentry/service/start.py,sha256=mZT7b9rVULvzy9GTZwxWnciCHgv9dbGN2JbxM60OMn4,1270
|
16
16
|
libentry/service/stop.py,sha256=wOpwZgrEJ7QirntfvibGq-XsTC6b3ELhzRW2zezh-0s,1187
|
17
|
-
libentry-1.11.
|
18
|
-
libentry-1.11.
|
19
|
-
libentry-1.11.
|
20
|
-
libentry-1.11.
|
21
|
-
libentry-1.11.
|
22
|
-
libentry-1.11.
|
17
|
+
libentry-1.11.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
18
|
+
libentry-1.11.5.dist-info/METADATA,sha256=Mv2rrwKRRvjEE2B8kmkWZe7mRltbbXv8GF3E_DTGKNc,500
|
19
|
+
libentry-1.11.5.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
|
20
|
+
libentry-1.11.5.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
|
21
|
+
libentry-1.11.5.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
22
|
+
libentry-1.11.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|