fal 1.0.7__py3-none-any.whl → 1.0.8__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.
Potentially problematic release.
This version of fal might be problematic. Click here for more details.
- fal/_fal_version.py +2 -2
- fal/api.py +90 -4
- fal/app.py +63 -1
- fal/cli/doctor.py +37 -0
- fal/cli/main.py +2 -2
- fal/sdk.py +6 -2
- fal/toolkit/file/providers/fal.py +1 -0
- {fal-1.0.7.dist-info → fal-1.0.8.dist-info}/METADATA +2 -1
- {fal-1.0.7.dist-info → fal-1.0.8.dist-info}/RECORD +12 -11
- {fal-1.0.7.dist-info → fal-1.0.8.dist-info}/WHEEL +0 -0
- {fal-1.0.7.dist-info → fal-1.0.8.dist-info}/entry_points.txt +0 -0
- {fal-1.0.7.dist-info → fal-1.0.8.dist-info}/top_level.txt +0 -0
fal/_fal_version.py
CHANGED
fal/api.py
CHANGED
|
@@ -5,11 +5,12 @@ import os
|
|
|
5
5
|
import sys
|
|
6
6
|
import threading
|
|
7
7
|
from collections import defaultdict
|
|
8
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
8
|
+
from concurrent.futures import Future, ThreadPoolExecutor
|
|
9
9
|
from contextlib import asynccontextmanager, suppress
|
|
10
10
|
from dataclasses import dataclass, field, replace
|
|
11
11
|
from functools import wraps
|
|
12
12
|
from os import PathLike
|
|
13
|
+
from queue import Queue
|
|
13
14
|
from typing import (
|
|
14
15
|
Any,
|
|
15
16
|
Callable,
|
|
@@ -72,6 +73,8 @@ SERVE_REQUIREMENTS = [
|
|
|
72
73
|
]
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
THREAD_POOL = ThreadPoolExecutor()
|
|
77
|
+
|
|
75
78
|
@dataclass
|
|
76
79
|
class FalServerlessError(FalServerlessException):
|
|
77
80
|
message: str
|
|
@@ -87,6 +90,31 @@ class FalMissingDependencyError(FalServerlessError):
|
|
|
87
90
|
...
|
|
88
91
|
|
|
89
92
|
|
|
93
|
+
@dataclass
|
|
94
|
+
class SpawnInfo:
|
|
95
|
+
future: Future | None = None
|
|
96
|
+
logs: Queue = field(default_factory=Queue)
|
|
97
|
+
_url_ready: threading.Event = field(default_factory=threading.Event)
|
|
98
|
+
_url: str | None = None
|
|
99
|
+
stream: Any = None
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def return_value(self):
|
|
103
|
+
if self.future is None:
|
|
104
|
+
raise ValueError
|
|
105
|
+
return self.future.result()
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def url(self):
|
|
109
|
+
self._url_ready.wait()
|
|
110
|
+
return self._url
|
|
111
|
+
|
|
112
|
+
@url.setter
|
|
113
|
+
def url(self, value):
|
|
114
|
+
self._url_ready.set()
|
|
115
|
+
self._url = value
|
|
116
|
+
|
|
117
|
+
|
|
90
118
|
@dataclass
|
|
91
119
|
class Host(Generic[ArgsT, ReturnT]):
|
|
92
120
|
"""The physical environment where the isolated code
|
|
@@ -150,6 +178,15 @@ class Host(Generic[ArgsT, ReturnT]):
|
|
|
150
178
|
"""Run the given function in the isolated environment."""
|
|
151
179
|
raise NotImplementedError
|
|
152
180
|
|
|
181
|
+
def spawn(
|
|
182
|
+
self,
|
|
183
|
+
func: Callable[ArgsT, ReturnT],
|
|
184
|
+
options: Options,
|
|
185
|
+
args: tuple[Any, ...],
|
|
186
|
+
kwargs: dict[str, Any],
|
|
187
|
+
) -> SpawnInfo:
|
|
188
|
+
raise NotImplementedError
|
|
189
|
+
|
|
153
190
|
|
|
154
191
|
def cached(func: Callable[ArgsT, ReturnT]) -> Callable[ArgsT, ReturnT]:
|
|
155
192
|
"""Cache the result of the given function in-memory."""
|
|
@@ -444,12 +481,13 @@ class FalServerlessHost(Host):
|
|
|
444
481
|
return None
|
|
445
482
|
|
|
446
483
|
@_handle_grpc_error()
|
|
447
|
-
def
|
|
484
|
+
def _run(
|
|
448
485
|
self,
|
|
449
486
|
func: Callable[..., ReturnT],
|
|
450
487
|
options: Options,
|
|
451
488
|
args: tuple[Any, ...],
|
|
452
489
|
kwargs: dict[str, Any],
|
|
490
|
+
result_handler: Callable[..., None],
|
|
453
491
|
) -> ReturnT:
|
|
454
492
|
environment_options = options.environment.copy()
|
|
455
493
|
environment_options.setdefault("python_version", active_python())
|
|
@@ -490,8 +528,7 @@ class FalServerlessHost(Host):
|
|
|
490
528
|
machine_requirements=machine_requirements,
|
|
491
529
|
setup_function=setup_function,
|
|
492
530
|
):
|
|
493
|
-
|
|
494
|
-
self._log_printer.print(log)
|
|
531
|
+
result_handler(partial_result)
|
|
495
532
|
|
|
496
533
|
if partial_result.status.state is not HostedRunState.IN_PROGRESS:
|
|
497
534
|
state = partial_result.status.state
|
|
@@ -512,6 +549,47 @@ class FalServerlessHost(Host):
|
|
|
512
549
|
return cast(ReturnT, return_value)
|
|
513
550
|
|
|
514
551
|
|
|
552
|
+
def run(
|
|
553
|
+
self,
|
|
554
|
+
func: Callable[..., ReturnT],
|
|
555
|
+
options: Options,
|
|
556
|
+
args: tuple[Any, ...],
|
|
557
|
+
kwargs: dict[str, Any],
|
|
558
|
+
) -> ReturnT:
|
|
559
|
+
def result_handler(partial_result):
|
|
560
|
+
for log in partial_result.logs:
|
|
561
|
+
self._log_printer.print(log)
|
|
562
|
+
|
|
563
|
+
return self._run(func, options, args, kwargs, result_handler=result_handler)
|
|
564
|
+
|
|
565
|
+
def spawn(
|
|
566
|
+
self,
|
|
567
|
+
func: Callable[..., ReturnT],
|
|
568
|
+
options: Options,
|
|
569
|
+
args: tuple[Any, ...],
|
|
570
|
+
kwargs: dict[str, Any],
|
|
571
|
+
) -> SpawnInfo:
|
|
572
|
+
ret = SpawnInfo()
|
|
573
|
+
|
|
574
|
+
def result_handler(partial_result):
|
|
575
|
+
ret.stream = partial_result.stream
|
|
576
|
+
for log in partial_result.logs:
|
|
577
|
+
if "Access your exposed service at" in log.message:
|
|
578
|
+
ret.url = log.message.rsplit()[-1]
|
|
579
|
+
ret.logs.put(log)
|
|
580
|
+
|
|
581
|
+
THREAD_POOL.submit(
|
|
582
|
+
self._run,
|
|
583
|
+
func,
|
|
584
|
+
options,
|
|
585
|
+
args,
|
|
586
|
+
kwargs,
|
|
587
|
+
result_handler=result_handler,
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
return ret
|
|
591
|
+
|
|
592
|
+
|
|
515
593
|
@dataclass
|
|
516
594
|
class Options:
|
|
517
595
|
host: BasicConfig = field(default_factory=dict)
|
|
@@ -1052,6 +1130,14 @@ class IsolatedFunction(Generic[ArgsT, ReturnT]):
|
|
|
1052
1130
|
)
|
|
1053
1131
|
return future
|
|
1054
1132
|
|
|
1133
|
+
def spawn(self, *args: ArgsT.args, **kwargs: ArgsT.kwargs):
|
|
1134
|
+
return self.host.spawn(
|
|
1135
|
+
self.func,
|
|
1136
|
+
self.options,
|
|
1137
|
+
args,
|
|
1138
|
+
kwargs,
|
|
1139
|
+
)
|
|
1140
|
+
|
|
1055
1141
|
def __call__(self, *args: ArgsT.args, **kwargs: ArgsT.kwargs) -> ReturnT:
|
|
1056
1142
|
try:
|
|
1057
1143
|
return self.host.run(
|
fal/app.py
CHANGED
|
@@ -4,10 +4,12 @@ import inspect
|
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
6
|
import re
|
|
7
|
+
import time
|
|
7
8
|
import typing
|
|
8
|
-
from contextlib import asynccontextmanager
|
|
9
|
+
from contextlib import asynccontextmanager, contextmanager
|
|
9
10
|
from typing import Any, Callable, ClassVar, TypeVar
|
|
10
11
|
|
|
12
|
+
import httpx
|
|
11
13
|
from fastapi import FastAPI
|
|
12
14
|
|
|
13
15
|
import fal.api
|
|
@@ -69,6 +71,66 @@ def wrap_app(cls: type[App], **kwargs) -> fal.api.IsolatedFunction:
|
|
|
69
71
|
return fn
|
|
70
72
|
|
|
71
73
|
|
|
74
|
+
class EndpointClient:
|
|
75
|
+
def __init__(self, url, endpoint, signature):
|
|
76
|
+
self.url = url
|
|
77
|
+
self.endpoint = endpoint
|
|
78
|
+
self.signature = signature
|
|
79
|
+
|
|
80
|
+
annotations = endpoint.__annotations__ or {}
|
|
81
|
+
self.return_type = annotations.get("return") or None
|
|
82
|
+
|
|
83
|
+
def __call__(self, data):
|
|
84
|
+
with httpx.Client() as client:
|
|
85
|
+
resp = client.post(self.url + self.signature.path, json=dict(data))
|
|
86
|
+
resp.raise_for_status()
|
|
87
|
+
resp_dict = resp.json()
|
|
88
|
+
|
|
89
|
+
if not self.return_type:
|
|
90
|
+
return resp_dict
|
|
91
|
+
|
|
92
|
+
return self.return_type(**resp_dict)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class AppClient:
|
|
96
|
+
def __init__(self, cls, url):
|
|
97
|
+
self.url = url
|
|
98
|
+
self.cls = cls
|
|
99
|
+
|
|
100
|
+
for name, endpoint in inspect.getmembers(cls, inspect.isfunction):
|
|
101
|
+
signature = getattr(endpoint, "route_signature", None)
|
|
102
|
+
if signature is None:
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
setattr(self, name, EndpointClient(self.url, endpoint, signature))
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
@contextmanager
|
|
109
|
+
def connect(cls, app_cls):
|
|
110
|
+
app = wrap_app(app_cls)
|
|
111
|
+
info = app.spawn()
|
|
112
|
+
try:
|
|
113
|
+
with httpx.Client() as client:
|
|
114
|
+
retries = 100
|
|
115
|
+
while retries:
|
|
116
|
+
resp = client.get(info.url + "/health")
|
|
117
|
+
if resp.is_success:
|
|
118
|
+
break
|
|
119
|
+
elif resp.status_code != 500:
|
|
120
|
+
resp.raise_for_status()
|
|
121
|
+
time.sleep(0.1)
|
|
122
|
+
retries -= 1
|
|
123
|
+
|
|
124
|
+
yield cls(app_cls, info.url)
|
|
125
|
+
finally:
|
|
126
|
+
info.stream.cancel()
|
|
127
|
+
|
|
128
|
+
def health(self):
|
|
129
|
+
with httpx.Client() as client:
|
|
130
|
+
resp = client.get(self.url + "/health")
|
|
131
|
+
resp.raise_for_status()
|
|
132
|
+
return resp.json()
|
|
133
|
+
|
|
72
134
|
|
|
73
135
|
PART_FINDER_RE = re.compile(r"[A-Z][a-z]*")
|
|
74
136
|
|
fal/cli/doctor.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _doctor(args):
|
|
6
|
+
import isolate
|
|
7
|
+
from rich.table import Table
|
|
8
|
+
|
|
9
|
+
import fal
|
|
10
|
+
|
|
11
|
+
table = Table(show_header=False, show_lines=False, box=None)
|
|
12
|
+
table.add_column("name", no_wrap=True, style="bold")
|
|
13
|
+
table.add_column("value", no_wrap=True)
|
|
14
|
+
|
|
15
|
+
table.add_row("fal", fal.__version__)
|
|
16
|
+
table.add_row("isolate", isolate.__version__)
|
|
17
|
+
|
|
18
|
+
table.add_row("", "")
|
|
19
|
+
table.add_row("python", platform.python_version())
|
|
20
|
+
table.add_row("platform", platform.platform())
|
|
21
|
+
|
|
22
|
+
table.add_row("", "")
|
|
23
|
+
table.add_row("FAL_HOST", fal.flags.GRPC_HOST)
|
|
24
|
+
table.add_row("FAL_KEY", os.getenv("FAL_KEY", "").split(":")[0])
|
|
25
|
+
|
|
26
|
+
args.console.print(table)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def add_parser(main_subparsers, parents):
|
|
30
|
+
doctor_help = "fal version and misc environment information."
|
|
31
|
+
parser = main_subparsers.add_parser(
|
|
32
|
+
"doctor",
|
|
33
|
+
description=doctor_help,
|
|
34
|
+
help=doctor_help,
|
|
35
|
+
parents=parents,
|
|
36
|
+
)
|
|
37
|
+
parser.set_defaults(func=_doctor)
|
fal/cli/main.py
CHANGED
|
@@ -6,7 +6,7 @@ from fal import __version__
|
|
|
6
6
|
from fal.console import console
|
|
7
7
|
from fal.console.icons import CROSS_ICON
|
|
8
8
|
|
|
9
|
-
from . import apps, auth, deploy, keys, run, secrets
|
|
9
|
+
from . import apps, auth, deploy, doctor, keys, run, secrets
|
|
10
10
|
from .debug import debugtools, get_debug_parser
|
|
11
11
|
from .parser import FalParser, FalParserExit
|
|
12
12
|
|
|
@@ -31,7 +31,7 @@ def _get_main_parser() -> argparse.ArgumentParser:
|
|
|
31
31
|
required=True,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
for cmd in [auth, apps, deploy, run, keys, secrets]:
|
|
34
|
+
for cmd in [auth, apps, deploy, run, keys, secrets, doctor]:
|
|
35
35
|
cmd.add_parser(subparsers, parents)
|
|
36
36
|
|
|
37
37
|
return parser
|
fal/sdk.py
CHANGED
|
@@ -224,6 +224,7 @@ class HostedRunResult(Generic[ResultT]):
|
|
|
224
224
|
status: HostedRunStatus
|
|
225
225
|
logs: list[Log] = field(default_factory=list)
|
|
226
226
|
result: ResultT | None = None
|
|
227
|
+
stream: Any = None
|
|
227
228
|
|
|
228
229
|
|
|
229
230
|
@dataclass
|
|
@@ -569,8 +570,11 @@ class FalServerlessConnection:
|
|
|
569
570
|
request.setup_func.MergeFrom(
|
|
570
571
|
to_serialized_object(setup_function, serialization_method)
|
|
571
572
|
)
|
|
572
|
-
|
|
573
|
-
|
|
573
|
+
stream = self.stub.Run(request)
|
|
574
|
+
for partial_result in stream:
|
|
575
|
+
res = from_grpc(partial_result)
|
|
576
|
+
res.stream = stream
|
|
577
|
+
yield res
|
|
574
578
|
|
|
575
579
|
def create_alias(
|
|
576
580
|
self,
|
|
@@ -98,6 +98,7 @@ class FalCDNFileRepository(FileRepository):
|
|
|
98
98
|
**self.auth_headers,
|
|
99
99
|
"Accept": "application/json",
|
|
100
100
|
"Content-Type": file.content_type,
|
|
101
|
+
"X-Fal-File-Name": file.file_name,
|
|
101
102
|
"X-Fal-Object-Lifecycle-Preference": json.dumps(
|
|
102
103
|
dataclasses.asdict(GLOBAL_LIFECYCLE_PREFERENCE)
|
|
103
104
|
),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: fal is an easy-to-use Serverless Python Framework
|
|
5
5
|
Author: Features & Labels <support@fal.ai>
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -43,6 +43,7 @@ Requires-Dist: pytest <8 ; extra == 'test'
|
|
|
43
43
|
Requires-Dist: pytest-asyncio ; extra == 'test'
|
|
44
44
|
Requires-Dist: pytest-xdist ; extra == 'test'
|
|
45
45
|
Requires-Dist: flaky ; extra == 'test'
|
|
46
|
+
Requires-Dist: boto3 ; extra == 'test'
|
|
46
47
|
|
|
47
48
|
[](https://pypi.org/project/fal)
|
|
48
49
|
[](https://github.com/fal-ai/fal/actions)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
fal/__init__.py,sha256=wXs1G0gSc7ZK60-bHe-B2m0l_sA6TrFk4BxY0tMoLe8,784
|
|
2
2
|
fal/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
|
|
3
|
-
fal/_fal_version.py,sha256=
|
|
3
|
+
fal/_fal_version.py,sha256=vy0P95Si-KzUl6NsixjrWEHfr5xcmkA_oO_S3bQRmvE,411
|
|
4
4
|
fal/_serialization.py,sha256=7urrZXw99qmsK-RkjCurk6Va4TMEfDIMajkzKbSW4j4,7655
|
|
5
5
|
fal/_version.py,sha256=EBGqrknaf1WygENX-H4fBefLvHryvJBBGtVJetaB0NY,266
|
|
6
|
-
fal/api.py,sha256=
|
|
7
|
-
fal/app.py,sha256=
|
|
6
|
+
fal/api.py,sha256=Qkp97ozww5EBXHq1oSikuDMGB0m7ZaYb5TCvROAknsA,40174
|
|
7
|
+
fal/app.py,sha256=duOf_YKE8o30hmhNtF9zvkT8wlKYXW7hdQLJtPrXHik,15793
|
|
8
8
|
fal/apps.py,sha256=UhR6mq8jBiTAp-QvUnvbnMNcuJ5wHIKSqdlfyx8aBQ8,6829
|
|
9
9
|
fal/container.py,sha256=V7riyyq8AZGwEX9QaqRQDZyDN_bUKeRKV1OOZArXjL0,622
|
|
10
10
|
fal/flags.py,sha256=oWN_eidSUOcE9wdPK_77si3A1fpgOC0UEERPsvNLIMc,842
|
|
11
11
|
fal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
fal/rest_client.py,sha256=kGBGmuyHfX1lR910EoKCYPjsyU8MdXawT_cW2q8Sajc,568
|
|
13
|
-
fal/sdk.py,sha256=
|
|
13
|
+
fal/sdk.py,sha256=_1aK9VSzHPoDPbLm3nbhE4213zI66qAsgYs1Y1Wc3J8,20077
|
|
14
14
|
fal/sync.py,sha256=ZuIJA2-hTPNANG9B_NNJZUsO68EIdTH0dc9MzeVE2VU,4340
|
|
15
15
|
fal/utils.py,sha256=MFDs-eO3rBgc3jqIwBpfBtvvK5tbzAYWMzHV-tTVLic,1754
|
|
16
16
|
fal/workflows.py,sha256=4rjqL4xB6GHLJsqTplJmAvpd6uHZJ28sc8su33BFXEo,14682
|
|
@@ -22,8 +22,9 @@ fal/cli/apps.py,sha256=Dqcx7ewUNY6dh0bYqRlOCHVDzmkdpFxe9CNThEz7HX4,8144
|
|
|
22
22
|
fal/cli/auth.py,sha256=--MhfHGwxmtHbRkGioyn1prKn_U-pBzbz0G_QeZou-U,1352
|
|
23
23
|
fal/cli/debug.py,sha256=1doDNwoaPDfLQginGNBxpC20dZYs5UxIojflDvV1Q04,1342
|
|
24
24
|
fal/cli/deploy.py,sha256=S_HIMLqDpGyzDdbiIxudRizwjGoAaHpN-sXcl2uCaQ4,4329
|
|
25
|
+
fal/cli/doctor.py,sha256=U4ne9LX5gQwNblsYQ27XdO8AYDgbYjTO39EtxhwexRM,983
|
|
25
26
|
fal/cli/keys.py,sha256=-9N6ZY6rW-_IE9tpupgaBPDGjGdKB3HKqU2g9daM3Xc,3109
|
|
26
|
-
fal/cli/main.py,sha256=
|
|
27
|
+
fal/cli/main.py,sha256=MxETDhqIT37quMbmofSMxBcAFOhnEHjpQ_pYEtOhApM,1993
|
|
27
28
|
fal/cli/parser.py,sha256=r1hd5e8Jq6yzDZw8-S0On1EjJbjRtHMuVuHC6MlvUj4,2835
|
|
28
29
|
fal/cli/run.py,sha256=NXwzkAWCKrRwgoMLsBOgW7RJPJW4IgSTrG85q2iePyk,894
|
|
29
30
|
fal/cli/secrets.py,sha256=mgHp3gBr8d2su7wBApeADKWHPkYu2ueB6gG3eNMETh8,2595
|
|
@@ -44,7 +45,7 @@ fal/toolkit/optimize.py,sha256=p75sovF0SmRP6zxzpIaaOmqlxvXB_xEz3XPNf59EF7w,1339
|
|
|
44
45
|
fal/toolkit/file/__init__.py,sha256=FbNl6wD-P0aSSTUwzHt4HujBXrbC3ABmaigPQA4hRfg,70
|
|
45
46
|
fal/toolkit/file/file.py,sha256=r8PzNCgv8Gkj6s1zM0yW-pcMKIouyaiEH06iBue8MwM,6066
|
|
46
47
|
fal/toolkit/file/types.py,sha256=9CqDh8SmNJNzfsrvtj468uo2SprJH9rOk8KMhhfU73c,1050
|
|
47
|
-
fal/toolkit/file/providers/fal.py,sha256=
|
|
48
|
+
fal/toolkit/file/providers/fal.py,sha256=ACxkfQ9kmMJ1xP8dNUHzkLkJJLZvoybTpVt8avGb8Nw,3747
|
|
48
49
|
fal/toolkit/file/providers/gcp.py,sha256=7Lg7BXoHKkFu0jkGv3_vKh2Ks6eRfDMbw31N3mvDUtk,1913
|
|
49
50
|
fal/toolkit/file/providers/r2.py,sha256=YW5aJBOX41MQxfx1rA_f-IiJhAPMZ5md0cxBcg3y08I,2537
|
|
50
51
|
fal/toolkit/image/__init__.py,sha256=qNLyXsBWysionUjbeWbohLqWlw3G_UpzunamkZd_JLQ,71
|
|
@@ -93,8 +94,8 @@ openapi_fal_rest/models/workflow_node_type.py,sha256=-FzyeY2bxcNmizKbJI8joG7byRi
|
|
|
93
94
|
openapi_fal_rest/models/workflow_schema.py,sha256=4K5gsv9u9pxx2ItkffoyHeNjBBYf6ur5bN4m_zePZNY,2019
|
|
94
95
|
openapi_fal_rest/models/workflow_schema_input.py,sha256=2OkOXWHTNsCXHWS6EGDFzcJKkW5FIap-2gfO233EvZQ,1191
|
|
95
96
|
openapi_fal_rest/models/workflow_schema_output.py,sha256=EblwSPAGfWfYVWw_WSSaBzQVju296is9o28rMBAd0mc,1196
|
|
96
|
-
fal-1.0.
|
|
97
|
-
fal-1.0.
|
|
98
|
-
fal-1.0.
|
|
99
|
-
fal-1.0.
|
|
100
|
-
fal-1.0.
|
|
97
|
+
fal-1.0.8.dist-info/METADATA,sha256=J6Lpic62ohISriecQ7IwHdL2PjZrNhrWVumFV7vhhJE,3777
|
|
98
|
+
fal-1.0.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
99
|
+
fal-1.0.8.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
|
|
100
|
+
fal-1.0.8.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
|
|
101
|
+
fal-1.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|