modal 0.72.47__py3-none-any.whl → 0.72.49__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.
modal/functions.py CHANGED
@@ -383,7 +383,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
383
383
  _serve_mounts: frozenset[_Mount] # set at load time, only by loader
384
384
  _app: Optional["modal.app._App"] = None
385
385
  _obj: Optional["modal.cls._Obj"] = None # only set for InstanceServiceFunctions and bound instance methods
386
- _web_url: Optional[str]
386
+
387
+ _webhook_config: Optional[api_pb2.WebhookConfig] = None # this is set in definition scope, only locally
388
+ _web_url: Optional[str] # this is set on hydration
389
+
387
390
  _function_name: Optional[str]
388
391
  _is_method: bool
389
392
  _spec: Optional[_FunctionSpec] = None
@@ -912,6 +915,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
912
915
  obj._cluster_size = cluster_size
913
916
  obj._is_method = False
914
917
  obj._spec = function_spec # needed for modal shell
918
+ obj._webhook_config = webhook_config # only set locally
915
919
 
916
920
  # Used to check whether we should rebuild a modal.Image which uses `run_function`.
917
921
  gpus: list[GPU_T] = gpu if isinstance(gpu, list) else [gpu]
@@ -1138,6 +1142,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1138
1142
  assert self._spec
1139
1143
  return self._spec
1140
1144
 
1145
+ def _is_web_endpoint(self) -> bool:
1146
+ # only defined in definition scope/locally, and not for class methods at the moment
1147
+ return bool(self._webhook_config and self._webhook_config.type != api_pb2.WEBHOOK_TYPE_UNSPECIFIED)
1148
+
1141
1149
  def get_build_def(self) -> str:
1142
1150
  """mdmd:hidden"""
1143
1151
  # Plaintext source and arg definition for the function, so it's part of the image
modal/functions.pyi CHANGED
@@ -141,6 +141,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal._object
141
141
  _serve_mounts: frozenset[modal.mount._Mount]
142
142
  _app: typing.Optional[modal.app._App]
143
143
  _obj: typing.Optional[modal.cls._Obj]
144
+ _webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig]
144
145
  _web_url: typing.Optional[str]
145
146
  _function_name: typing.Optional[str]
146
147
  _is_method: bool
@@ -231,6 +232,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal._object
231
232
  def info(self) -> modal._utils.function_utils.FunctionInfo: ...
232
233
  @property
233
234
  def spec(self) -> _FunctionSpec: ...
235
+ def _is_web_endpoint(self) -> bool: ...
234
236
  def get_build_def(self) -> str: ...
235
237
  def _initialize_from_empty(self): ...
236
238
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
@@ -309,6 +311,7 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
309
311
  _serve_mounts: frozenset[modal.mount.Mount]
310
312
  _app: typing.Optional[modal.app.App]
311
313
  _obj: typing.Optional[modal.cls.Obj]
314
+ _webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig]
312
315
  _web_url: typing.Optional[str]
313
316
  _function_name: typing.Optional[str]
314
317
  _is_method: bool
@@ -419,6 +422,7 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
419
422
  def info(self) -> modal._utils.function_utils.FunctionInfo: ...
420
423
  @property
421
424
  def spec(self) -> _FunctionSpec: ...
425
+ def _is_web_endpoint(self) -> bool: ...
422
426
  def get_build_def(self) -> str: ...
423
427
  def _initialize_from_empty(self): ...
424
428
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
@@ -465,11 +469,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
465
469
 
466
470
  _call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
467
471
 
468
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
472
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
469
473
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
470
474
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
471
475
 
472
- remote: __remote_spec[P, ReturnType, typing_extensions.Self]
476
+ remote: __remote_spec[ReturnType, P, typing_extensions.Self]
473
477
 
474
478
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
475
479
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -482,17 +486,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
482
486
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
483
487
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
484
488
 
485
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
489
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
486
490
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
487
491
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
488
492
 
489
- _experimental_spawn: ___experimental_spawn_spec[P, ReturnType, typing_extensions.Self]
493
+ _experimental_spawn: ___experimental_spawn_spec[ReturnType, P, typing_extensions.Self]
490
494
 
491
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
495
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
492
496
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
493
497
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
494
498
 
495
- spawn: __spawn_spec[P, ReturnType, typing_extensions.Self]
499
+ spawn: __spawn_spec[ReturnType, P, typing_extensions.Self]
496
500
 
497
501
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
498
502
 
modal/partial_function.py CHANGED
@@ -92,6 +92,11 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
92
92
  def _get_raw_f(self) -> Callable[P, ReturnType]:
93
93
  return self.raw_f
94
94
 
95
+ def _is_web_endpoint(self) -> bool:
96
+ if self.webhook_config is None:
97
+ return False
98
+ return self.webhook_config.type != api_pb2.WEBHOOK_TYPE_UNSPECIFIED
99
+
95
100
  def __get__(self, obj, objtype=None) -> _Function[P, ReturnType, OriginalReturnType]:
96
101
  k = self.raw_f.__name__
97
102
  if obj: # accessing the method on an instance of a class, e.g. `MyClass().fun``
@@ -50,6 +50,7 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
50
50
  build_timeout: typing.Optional[int] = None,
51
51
  ): ...
52
52
  def _get_raw_f(self) -> collections.abc.Callable[P, ReturnType]: ...
53
+ def _is_web_endpoint(self) -> bool: ...
53
54
  def __get__(self, obj, objtype=None) -> modal.functions._Function[P, ReturnType, OriginalReturnType]: ...
54
55
  def __del__(self): ...
55
56
  def add_flags(self, flags) -> _PartialFunction: ...
@@ -80,6 +81,7 @@ class PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
80
81
  build_timeout: typing.Optional[int] = None,
81
82
  ): ...
82
83
  def _get_raw_f(self) -> collections.abc.Callable[P, ReturnType]: ...
84
+ def _is_web_endpoint(self) -> bool: ...
83
85
  def __get__(self, obj, objtype=None) -> modal.functions.Function[P, ReturnType, OriginalReturnType]: ...
84
86
  def __del__(self): ...
85
87
  def add_flags(self, flags) -> PartialFunction: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.72.47
3
+ Version: 0.72.49
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -16,14 +16,14 @@ modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
16
16
  modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
17
17
  modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
18
18
  modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
19
- modal/app.py,sha256=mz-fmvaL4ND616rqGOi-ikAuQWCv2CKeR_HpviIurYc,45353
20
- modal/app.pyi,sha256=aZJkeqsnsv72R7OTLXcifom0c-NBU6xgVhRc9yEt9nE,25760
19
+ modal/app.py,sha256=KNfzLlkI2dJPl9LY8AgW76whZpwIvYKi2E2p9u4F3N4,43659
20
+ modal/app.pyi,sha256=vnQhENaQBhJO6el-ieOcw3NEeYQ314SFXRDtjij4DM8,25324
21
21
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
22
22
  modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
23
- modal/client.pyi,sha256=YBEKf_pdjZ3n-Re4jxkJOeXlsmfAZVPItV9zh7X4Y8M,7593
23
+ modal/client.pyi,sha256=X4fFtdmhM0JFVwM8z5XBXUOoxYbZZ_t8PcUiQ_d3Tl8,7593
24
24
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
25
25
  modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
26
- modal/cls.py,sha256=xHgZZAmymplw0I2YZGAA8raBboixdNKKTrnsxQZI7G8,32159
26
+ modal/cls.py,sha256=7Czu5ff8Sezzl4ayHyI9nMgB0el3401_uHvyZU4vbhc,32206
27
27
  modal/cls.pyi,sha256=LrX2YVbcRqSKioOtXIMT9NShe4gaVYpDKt16SDZHh5s,8966
28
28
  modal/config.py,sha256=BzhZYUUwOmvVwf6x5kf0ywMC257s648dmuhsnB6g3gk,11041
29
29
  modal/container_process.py,sha256=WTqLn01dJPVkPpwR_0w_JH96ceN5mV4TGtiu1ZR2RRA,6108
@@ -38,8 +38,8 @@ modal/experimental.pyi,sha256=24tIYu_w9RLwFrz1cIsgYuqmDCtV8eg6-bQNz3zjhDo,939
38
38
  modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
39
39
  modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
40
40
  modal/file_pattern_matcher.py,sha256=dSo7BMQGZBAuoBFOX-e_72HxmF3FLzjQlEtnGtJiaD4,6506
41
- modal/functions.py,sha256=dUzTocLsL-Huw5dwqs8HCksiOqvGHSTiwnZJOlAluAA,68601
42
- modal/functions.pyi,sha256=lX3zZwIzbHXpmJA5QFki6ozaK3bdrdP-AM91_NFBimg,26301
41
+ modal/functions.py,sha256=BrqbgeKpuoiA3-waNfdmUJfAGF7BsbQHvlTfAS1eHNQ,69046
42
+ modal/functions.pyi,sha256=m2a2ZnjqZFC6REG1_uhA5LM0O1etkFbQH3KnsLSXUKs,26533
43
43
  modal/gpu.py,sha256=2qZMNnoMrjU-5Bu7fx68pANUAKTtZq0EWEEeBA9OUVQ,7426
44
44
  modal/image.py,sha256=leeY7fLfFjS0IqTi3D4cRxIDOb80BPtb3jsQfqvVJ8c,90912
45
45
  modal/image.pyi,sha256=QMKS6E3CsZr5DoyNqGpcJPBYJTJZSvtAQIsAhPVd_E4,26347
@@ -54,8 +54,8 @@ modal/object.pyi,sha256=kyJkRQcVv3ct7zSAxvvXcuhBVeH914v80uSlqeS7cA4,5632
54
54
  modal/output.py,sha256=N0xf4qeudEaYrslzdAl35VKV8rapstgIM2e9wO8_iy0,1967
55
55
  modal/parallel_map.py,sha256=POBTyiWabe2e4qBNlsjjksiu1AAPEsNqI-mM8cgNFco,16042
56
56
  modal/parallel_map.pyi,sha256=0ltjcIpPUqPGGOWmHqzCfBu5y3ISjRZDrqOJhiNhfYk,2522
57
- modal/partial_function.py,sha256=zr-9onLYZDF2NDm_BXj2zBL9eZy52T5S7U2OhHF2dao,28529
58
- modal/partial_function.pyi,sha256=pXB6u36SX1C0KsxBnyu7zDXDrV0DbjZJn4sb37_kilE,9817
57
+ modal/partial_function.py,sha256=4_hGVCCX-dYdjs_86Metfsuih8YyypiVMrExcwRGDS8,28711
58
+ modal/partial_function.pyi,sha256=Dj4WDxbGkXjxAbucSBSqr2_vrNbEWEAwdXnMzh2d80Y,9905
59
59
  modal/proxy.py,sha256=NrOevrWxG3G7-zlyRzG6BcIvop7AWLeyahZxitbBaOk,1418
60
60
  modal/proxy.pyi,sha256=1OEKIVUyC-xb7fHMzngakQso0nTsK60TVhXtlcMj6Wk,390
61
61
  modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -116,12 +116,12 @@ modal/cli/container.py,sha256=FYwEgjf93j4NMorAjGbSV98i1wpebqdAeNU1wfrFp1k,3668
116
116
  modal/cli/dict.py,sha256=HaEcjfll7i3Uj3Fg56aj4407if5UljsYfr6fIq-D2W8,4589
117
117
  modal/cli/entry_point.py,sha256=aaNxFAqZcmtSjwzkYIA_Ba9CkL4cL4_i2gy5VjoXxkM,4228
118
118
  modal/cli/environment.py,sha256=Ayddkiq9jdj3XYDJ8ZmUqFpPPH8xajYlbexRkzGtUcg,4334
119
- modal/cli/import_refs.py,sha256=W-jU9AsUkaseUDduAmENQCkEE5mmVKWlJFAgEvulwuI,12023
120
- modal/cli/launch.py,sha256=HgaVXJq0KbVCNUSaU3lq1zP9eCksq6jbSBYBNcMUaoA,3097
119
+ modal/cli/import_refs.py,sha256=vp4r28FGnag3hKRbR_haiuCIGmOTthrhcGhAqSwwc7Q,11753
120
+ modal/cli/launch.py,sha256=pzQt2QlcrbIUU0MVzWWPAvMQ6MCyqsHZ0X9JcV-sY04,3242
121
121
  modal/cli/network_file_system.py,sha256=o6VLTgN4xn5XUiNPBfxYec-5uWCgYrDmfFFLM1ZW_eE,8180
122
122
  modal/cli/profile.py,sha256=rLXfjJObfPNjaZvNfHGIKqs7y9bGYyGe-K7V0w-Ni0M,3110
123
123
  modal/cli/queues.py,sha256=MIh2OsliNE2QeL1erubfsRsNuG4fxqcqWA2vgIfQ4Mg,4494
124
- modal/cli/run.py,sha256=7WSJ7PSF6IrVWhTBmdC8ywEvdJcx-NS6YXYKTrgMV7w,18231
124
+ modal/cli/run.py,sha256=1rIfCRuCJb5fJQPW2j9huHh9h72u45g708IXf3QXKB8,20051
125
125
  modal/cli/secret.py,sha256=uQpwYrMY98iMCWeZOQTcktOYhPTZ8IHnyealDc2CZqo,4206
126
126
  modal/cli/token.py,sha256=mxSgOWakXG6N71hQb1ko61XAR9ZGkTMZD-Txn7gmTac,1924
127
127
  modal/cli/utils.py,sha256=hZmjyzcPjDnQSkLvycZD2LhGdcsfdZshs_rOU78EpvI,3717
@@ -150,10 +150,10 @@ modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
150
150
  modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
151
151
  modal_global_objects/mounts/python_standalone.py,sha256=pEML5GaV2_0ahci_1vpfc_FnySpsfi2fhYmFF5I7IiQ,1837
152
152
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
153
- modal_proto/api.proto,sha256=6Rt3GfhD5PWxmkAerWPFQZQ4TL7u0-s7PBcvajuKl5A,85069
153
+ modal_proto/api.proto,sha256=Rbfevf7b1q7mhBGKO36cwedjdA3hkvDqmP-lAVx9sRA,85152
154
154
  modal_proto/api_grpc.py,sha256=_YeTxy_4EyqC4jp9eBsJWnziGRafK5c61kcvdWpJXRY,109089
155
- modal_proto/api_pb2.py,sha256=uds7csRod6-2Hq3PehpeKJ82agfcfZc-fmKrQ4-01m0,310738
156
- modal_proto/api_pb2.pyi,sha256=FBNlLVTt75Nq6G1JwnB_1nLz5WsK9XCOYoqNafXKSaA,413655
155
+ modal_proto/api_pb2.py,sha256=ZSD-9VZc4hUlto59RXtNMBYPJ-ebVt-fupZ0tbwW_YM,310899
156
+ modal_proto/api_pb2.pyi,sha256=kEXj0GopoM7ovY2Br_UIo2qGa7Z3gX1E8Gqdq0oj7Dk,414178
157
157
  modal_proto/api_pb2_grpc.py,sha256=LlW5e2YKWPJS3lPYoJDyKjf1AxJSCCHi0DhupX05YyQ,235804
158
158
  modal_proto/api_pb2_grpc.pyi,sha256=BM4068ohQqF1VUxvYdAYEVLgUebJVQvyrii-aXcel74,54910
159
159
  modal_proto/modal_api_grpc.py,sha256=fYh-4oxTB8fB1NWrYm8S9-8umvKvAxJ58eNZ_e4B0WA,14556
@@ -167,10 +167,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
167
167
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
168
168
  modal_version/__init__.py,sha256=kGya2ZlItX2zB7oHORs-wvP4PG8lg_mtbi1QIK3G6SQ,470
169
169
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
170
- modal_version/_version_generated.py,sha256=Ly3TRbYg5c7IaFzHo4g0dfndktKC5IRRiBahsmv8Cdw,149
171
- modal-0.72.47.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
172
- modal-0.72.47.dist-info/METADATA,sha256=oO7nH8zYiETU4PTFTP5BD8NIMQu5KzB3htHHFy3W5Dw,2329
173
- modal-0.72.47.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
174
- modal-0.72.47.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
175
- modal-0.72.47.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
176
- modal-0.72.47.dist-info/RECORD,,
170
+ modal_version/_version_generated.py,sha256=6pmky2Bgiq1GWme6H42Uk02_iaUWWNiPSQEcJGVFJ1c,149
171
+ modal-0.72.49.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
172
+ modal-0.72.49.dist-info/METADATA,sha256=tC7LwhupgezKLQKMry_0QPKlc5YI0WKK32TyURGn55w,2329
173
+ modal-0.72.49.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
174
+ modal-0.72.49.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
175
+ modal-0.72.49.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
176
+ modal-0.72.49.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -168,6 +168,7 @@ enum ParameterType {
168
168
  PARAM_TYPE_UNSPECIFIED = 0;
169
169
  PARAM_TYPE_STRING = 1;
170
170
  PARAM_TYPE_INT = 2;
171
+ PARAM_TYPE_PICKLE = 3;
171
172
  }
172
173
 
173
174
  enum ProgressType {
@@ -681,6 +682,7 @@ message ClassParameterSpec {
681
682
  oneof default_oneof {
682
683
  string string_default = 4;
683
684
  int64 int_default = 5;
685
+ bytes pickle_default = 6;
684
686
  }
685
687
  }
686
688
 
@@ -693,6 +695,7 @@ message ClassParameterValue {
693
695
  oneof value_oneof {
694
696
  string string_value = 3;
695
697
  int64 int_value = 4;
698
+ bytes pickle_value = 5;
696
699
  }
697
700
  }
698
701