fal 0.12.5__py3-none-any.whl → 0.12.6__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/__main__.py +4 -0
- fal/apps.py +6 -2
- fal/auth/auth0.py +12 -14
- fal/cli.py +58 -29
- fal/console/ux.py +7 -10
- fal/workflows.py +10 -9
- {fal-0.12.5.dist-info → fal-0.12.6.dist-info}/METADATA +6 -2
- {fal-0.12.5.dist-info → fal-0.12.6.dist-info}/RECORD +10 -9
- {fal-0.12.5.dist-info → fal-0.12.6.dist-info}/WHEEL +0 -0
- {fal-0.12.5.dist-info → fal-0.12.6.dist-info}/entry_points.txt +0 -0
fal/__main__.py
ADDED
fal/apps.py
CHANGED
|
@@ -65,8 +65,12 @@ class RequestHandle:
|
|
|
65
65
|
def __post_init__(self):
|
|
66
66
|
app_id = _backwards_compatible_app_id(self.app_id)
|
|
67
67
|
# drop any extra path components
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
parts = app_id.split("/")[:3]
|
|
69
|
+
if parts[0] != "workflows":
|
|
70
|
+
# if the app_id is not a workflow, only keep the first two parts
|
|
71
|
+
parts = parts[:2]
|
|
72
|
+
|
|
73
|
+
self.app_id = "/".join(parts)
|
|
70
74
|
|
|
71
75
|
def status(self, *, logs: bool = False) -> _Status:
|
|
72
76
|
"""Check the status of an async inference request."""
|
fal/auth/auth0.py
CHANGED
|
@@ -9,7 +9,7 @@ import httpx
|
|
|
9
9
|
|
|
10
10
|
from fal.console import console
|
|
11
11
|
from fal.console.icons import CHECK_ICON
|
|
12
|
-
from fal.console.ux import
|
|
12
|
+
from fal.console.ux import maybe_open_browser_tab
|
|
13
13
|
|
|
14
14
|
WEBSITE_URL = "https://fal.ai"
|
|
15
15
|
|
|
@@ -27,19 +27,17 @@ def logout_url(return_url: str):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def _open_browser(url: str, code: str | None) -> None:
|
|
30
|
-
|
|
31
|
-
console.print()
|
|
30
|
+
maybe_open_browser_tab(url)
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
32
|
+
console.print(
|
|
33
|
+
"If browser didn't open automatically, on your computer or mobile device navigate to"
|
|
34
|
+
)
|
|
35
|
+
console.print(url)
|
|
36
|
+
|
|
37
|
+
if code:
|
|
38
|
+
console.print(
|
|
39
|
+
f"\nConfirm it shows the following code: [markdown.code]{code}[/]\n"
|
|
40
|
+
)
|
|
43
41
|
|
|
44
42
|
|
|
45
43
|
def login() -> dict:
|
|
@@ -183,7 +181,7 @@ def validate_id_token(token: str):
|
|
|
183
181
|
def verify_access_token_expiration(token: str):
|
|
184
182
|
from jwt import decode
|
|
185
183
|
|
|
186
|
-
leeway =
|
|
184
|
+
leeway = 30 * 60 # 30 minutes
|
|
187
185
|
decode(
|
|
188
186
|
token,
|
|
189
187
|
leeway=-leeway, # negative to consider expired before actual expiration
|
fal/cli.py
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
from dataclasses import dataclass, field
|
|
4
5
|
from http import HTTPStatus
|
|
5
6
|
from sys import argv
|
|
6
|
-
from typing import Literal
|
|
7
|
+
from typing import Any, Callable, Literal
|
|
7
8
|
from uuid import uuid4
|
|
8
9
|
|
|
9
10
|
import click
|
|
10
11
|
import openapi_fal_rest.api.billing.get_user_details as get_user_details
|
|
11
12
|
from rich.table import Table
|
|
13
|
+
from rich_click import RichCommand, RichGroup
|
|
12
14
|
|
|
13
15
|
import fal
|
|
14
16
|
import fal.auth as auth
|
|
@@ -32,16 +34,29 @@ DEBUG_ENABLED = False
|
|
|
32
34
|
logger = get_logger(__name__)
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
@dataclass
|
|
38
|
+
class State:
|
|
39
|
+
debug: bool = False
|
|
40
|
+
invocation_id: str = field(default_factory=lambda: str(uuid4()))
|
|
38
41
|
|
|
39
|
-
def __init__(self, debug=False):
|
|
40
|
-
self.debug = debug
|
|
41
|
-
self.invocation_id = str(uuid4())
|
|
42
42
|
|
|
43
|
+
def debug_option(*param_decls: str, **kwargs: Any) -> Callable[[click.FC], click.FC]:
|
|
44
|
+
def callback(ctx: click.Context, param: click.Parameter, value: bool) -> None:
|
|
45
|
+
state = ctx.ensure_object(State)
|
|
46
|
+
state.debug = value
|
|
47
|
+
set_debug_logging(value)
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
if not param_decls:
|
|
50
|
+
param_decls = ("--debug",)
|
|
51
|
+
|
|
52
|
+
kwargs.setdefault("is_flag", True)
|
|
53
|
+
kwargs.setdefault("expose_value", False)
|
|
54
|
+
kwargs.setdefault("callback", callback)
|
|
55
|
+
kwargs.setdefault("help", "Enable detailed errors and verbose logging.")
|
|
56
|
+
return click.option(*param_decls, **kwargs)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class MainGroup(RichGroup):
|
|
45
60
|
"""A custom implementation of the top-level group
|
|
46
61
|
(i.e. called on all commands and subcommands).
|
|
47
62
|
|
|
@@ -56,13 +71,11 @@ class MainGroup(click.Group):
|
|
|
56
71
|
def invoke(self, ctx):
|
|
57
72
|
from click.exceptions import Abort, ClickException, Exit
|
|
58
73
|
|
|
59
|
-
|
|
74
|
+
state = ctx.ensure_object(State)
|
|
60
75
|
qualified_name = " ".join([ctx.info_name] + argv[1:])
|
|
61
|
-
invocation_id = execution_info.invocation_id
|
|
62
|
-
set_debug_logging(execution_info.debug)
|
|
63
76
|
|
|
64
77
|
with self._tracer.start_as_current_span(
|
|
65
|
-
qualified_name, attributes={"invocation_id": invocation_id}
|
|
78
|
+
qualified_name, attributes={"invocation_id": state.invocation_id}
|
|
66
79
|
):
|
|
67
80
|
try:
|
|
68
81
|
logger.debug(
|
|
@@ -75,20 +88,20 @@ class MainGroup(click.Group):
|
|
|
75
88
|
raise
|
|
76
89
|
except Exception as exception:
|
|
77
90
|
logger.error(exception)
|
|
78
|
-
if
|
|
91
|
+
if state.debug:
|
|
79
92
|
# Here we supress detailed errors on click lines because
|
|
80
93
|
# they're mostly decorator calls, irrelevant to the dev's error tracing
|
|
81
94
|
console.print_exception(suppress=[click])
|
|
82
95
|
console.print()
|
|
83
96
|
console.print(
|
|
84
|
-
f"The [markdown.code]invocation_id[/] for this operation is: [white]{invocation_id}[/]"
|
|
97
|
+
f"The [markdown.code]invocation_id[/] for this operation is: [white]{state.invocation_id}[/]"
|
|
85
98
|
)
|
|
86
99
|
else:
|
|
87
100
|
self._exception_handler.handle(exception)
|
|
88
101
|
|
|
89
102
|
def add_command(
|
|
90
103
|
self,
|
|
91
|
-
cmd:
|
|
104
|
+
cmd: RichCommand,
|
|
92
105
|
name: str | None = None,
|
|
93
106
|
aliases: list[str] | None = None,
|
|
94
107
|
) -> None:
|
|
@@ -113,7 +126,7 @@ class MainGroup(click.Group):
|
|
|
113
126
|
self.add_command(alias_cmd, alias)
|
|
114
127
|
|
|
115
128
|
|
|
116
|
-
class AliasCommand(
|
|
129
|
+
class AliasCommand(RichCommand):
|
|
117
130
|
def __init__(self, wrapped):
|
|
118
131
|
self._wrapped = wrapped
|
|
119
132
|
|
|
@@ -129,31 +142,33 @@ class AliasCommand(click.Command):
|
|
|
129
142
|
|
|
130
143
|
|
|
131
144
|
@click.group(cls=MainGroup)
|
|
132
|
-
@click.option(
|
|
133
|
-
"--debug", is_flag=True, help="Enable detailed errors and verbose logging."
|
|
134
|
-
)
|
|
135
145
|
@click.version_option()
|
|
136
|
-
|
|
146
|
+
@debug_option()
|
|
147
|
+
def cli():
|
|
137
148
|
pass
|
|
138
149
|
|
|
139
150
|
|
|
140
151
|
###### Auth group ######
|
|
141
|
-
@click.group
|
|
152
|
+
@click.group(cls=RichGroup)
|
|
153
|
+
@debug_option()
|
|
142
154
|
def auth_cli():
|
|
143
155
|
pass
|
|
144
156
|
|
|
145
157
|
|
|
146
158
|
@auth_cli.command(name="login")
|
|
159
|
+
@debug_option()
|
|
147
160
|
def auth_login():
|
|
148
161
|
auth.login()
|
|
149
162
|
|
|
150
163
|
|
|
151
164
|
@auth_cli.command(name="logout")
|
|
165
|
+
@debug_option()
|
|
152
166
|
def auth_logout():
|
|
153
167
|
auth.logout()
|
|
154
168
|
|
|
155
169
|
|
|
156
170
|
@auth_cli.command(name="hello", hidden=True)
|
|
171
|
+
@debug_option()
|
|
157
172
|
def auth_test():
|
|
158
173
|
"""
|
|
159
174
|
To test auth.
|
|
@@ -162,9 +177,10 @@ def auth_test():
|
|
|
162
177
|
|
|
163
178
|
|
|
164
179
|
###### Key group ######
|
|
165
|
-
@click.group
|
|
180
|
+
@click.group(cls=RichGroup)
|
|
166
181
|
@click.option("--host", default=DEFAULT_HOST, envvar=HOST_ENVVAR)
|
|
167
182
|
@click.option("--port", default=DEFAULT_PORT, envvar=PORT_ENVVAR, hidden=True)
|
|
183
|
+
@debug_option()
|
|
168
184
|
@click.pass_context
|
|
169
185
|
def key_cli(ctx, host: str, port: str):
|
|
170
186
|
ctx.obj = sdk.FalServerlessClient(f"{host}:{port}")
|
|
@@ -183,6 +199,7 @@ def key_cli(ctx, host: str, port: str):
|
|
|
183
199
|
default=None,
|
|
184
200
|
help="An alias for the key.",
|
|
185
201
|
)
|
|
202
|
+
@debug_option()
|
|
186
203
|
@click.pass_obj
|
|
187
204
|
def key_generate(client: sdk.FalServerlessClient, scope: str, alias: str | None):
|
|
188
205
|
with client.connect() as connection:
|
|
@@ -197,6 +214,7 @@ def key_generate(client: sdk.FalServerlessClient, scope: str, alias: str | None)
|
|
|
197
214
|
|
|
198
215
|
|
|
199
216
|
@key_cli.command(name="list")
|
|
217
|
+
@debug_option()
|
|
200
218
|
@click.pass_obj
|
|
201
219
|
def key_list(client: sdk.FalServerlessClient):
|
|
202
220
|
table = Table(title="Keys")
|
|
@@ -217,6 +235,7 @@ def key_list(client: sdk.FalServerlessClient):
|
|
|
217
235
|
|
|
218
236
|
@key_cli.command(name="revoke")
|
|
219
237
|
@click.argument("key_id", required=True)
|
|
238
|
+
@debug_option()
|
|
220
239
|
@click.pass_obj
|
|
221
240
|
def key_revoke(client: sdk.FalServerlessClient, key_id: str):
|
|
222
241
|
with client.connect() as connection:
|
|
@@ -228,9 +247,10 @@ ALIAS_AUTH_OPTIONS = ["public", "private", "shared"]
|
|
|
228
247
|
ALIAS_AUTH_TYPE = Literal["public", "private", "shared"]
|
|
229
248
|
|
|
230
249
|
|
|
231
|
-
@click.group
|
|
250
|
+
@click.group(cls=RichGroup)
|
|
232
251
|
@click.option("--host", default=DEFAULT_HOST, envvar=HOST_ENVVAR)
|
|
233
252
|
@click.option("--port", default=DEFAULT_PORT, envvar=PORT_ENVVAR, hidden=True)
|
|
253
|
+
@debug_option()
|
|
234
254
|
@click.pass_context
|
|
235
255
|
def function_cli(ctx, host: str, port: str):
|
|
236
256
|
ctx.obj = api.FalServerlessHost(f"{host}:{port}")
|
|
@@ -272,6 +292,7 @@ def load_function_from(
|
|
|
272
292
|
)
|
|
273
293
|
@click.argument("file_path", required=True)
|
|
274
294
|
@click.argument("function_name", required=True)
|
|
295
|
+
@debug_option()
|
|
275
296
|
@click.pass_obj
|
|
276
297
|
def register_application(
|
|
277
298
|
host: api.FalServerlessHost,
|
|
@@ -323,6 +344,7 @@ def register_application(
|
|
|
323
344
|
@function_cli.command("run")
|
|
324
345
|
@click.argument("file_path", required=True)
|
|
325
346
|
@click.argument("function_name", required=True)
|
|
347
|
+
@debug_option()
|
|
326
348
|
@click.pass_obj
|
|
327
349
|
def run(host: api.FalServerlessHost, file_path: str, function_name: str):
|
|
328
350
|
isolated_function = load_function_from(host, file_path, function_name)
|
|
@@ -332,6 +354,7 @@ def run(host: api.FalServerlessHost, file_path: str, function_name: str):
|
|
|
332
354
|
@function_cli.command("logs")
|
|
333
355
|
@click.option("--lines", default=100)
|
|
334
356
|
@click.option("--url", default=None)
|
|
357
|
+
@debug_option()
|
|
335
358
|
@click.pass_obj
|
|
336
359
|
def get_logs(
|
|
337
360
|
host: api.FalServerlessHost, lines: int | None = 100, url: str | None = None
|
|
@@ -342,9 +365,10 @@ def get_logs(
|
|
|
342
365
|
|
|
343
366
|
|
|
344
367
|
##### Alias group #####
|
|
345
|
-
@click.group
|
|
368
|
+
@click.group(cls=RichGroup)
|
|
346
369
|
@click.option("--host", default=DEFAULT_HOST, envvar=HOST_ENVVAR)
|
|
347
370
|
@click.option("--port", default=DEFAULT_PORT, envvar=PORT_ENVVAR, hidden=True)
|
|
371
|
+
@debug_option()
|
|
348
372
|
@click.pass_context
|
|
349
373
|
def alias_cli(ctx, host: str, port: str):
|
|
350
374
|
ctx.obj = api.FalServerlessClient(f"{host}:{port}")
|
|
@@ -385,6 +409,7 @@ def _alias_table(aliases: list[AliasInfo]):
|
|
|
385
409
|
type=click.Choice(ALIAS_AUTH_OPTIONS),
|
|
386
410
|
default="private",
|
|
387
411
|
)
|
|
412
|
+
@debug_option()
|
|
388
413
|
@click.pass_obj
|
|
389
414
|
def alias_set(
|
|
390
415
|
client: api.FalServerlessClient,
|
|
@@ -398,6 +423,7 @@ def alias_set(
|
|
|
398
423
|
|
|
399
424
|
@alias_cli.command("delete")
|
|
400
425
|
@click.argument("alias", required=True)
|
|
426
|
+
@debug_option()
|
|
401
427
|
@click.pass_obj
|
|
402
428
|
def alias_delete(client: api.FalServerlessClient, alias: str):
|
|
403
429
|
with client.connect() as connection:
|
|
@@ -407,6 +433,7 @@ def alias_delete(client: api.FalServerlessClient, alias: str):
|
|
|
407
433
|
|
|
408
434
|
|
|
409
435
|
@alias_cli.command("list")
|
|
436
|
+
@debug_option()
|
|
410
437
|
@click.pass_obj
|
|
411
438
|
def alias_list(client: api.FalServerlessClient):
|
|
412
439
|
with client.connect() as connection:
|
|
@@ -428,6 +455,7 @@ def alias_list(client: api.FalServerlessClient):
|
|
|
428
455
|
# "auth_mode",
|
|
429
456
|
# type=click.Choice(ALIAS_AUTH_OPTIONS),
|
|
430
457
|
# )
|
|
458
|
+
@debug_option()
|
|
431
459
|
@click.pass_obj
|
|
432
460
|
def alias_update(
|
|
433
461
|
client: api.FalServerlessClient,
|
|
@@ -461,6 +489,7 @@ def alias_update(
|
|
|
461
489
|
|
|
462
490
|
@alias_cli.command("runners")
|
|
463
491
|
@click.argument("alias", required=True)
|
|
492
|
+
@debug_option()
|
|
464
493
|
@click.pass_obj
|
|
465
494
|
def alias_list_runners(
|
|
466
495
|
client: api.FalServerlessClient,
|
|
@@ -491,15 +520,17 @@ def alias_list_runners(
|
|
|
491
520
|
|
|
492
521
|
|
|
493
522
|
##### Secrets group #####
|
|
494
|
-
@click.group
|
|
523
|
+
@click.group(cls=RichGroup)
|
|
495
524
|
@click.option("--host", default=DEFAULT_HOST, envvar=HOST_ENVVAR)
|
|
496
525
|
@click.option("--port", default=DEFAULT_PORT, envvar=PORT_ENVVAR, hidden=True)
|
|
526
|
+
@debug_option()
|
|
497
527
|
@click.pass_context
|
|
498
528
|
def secrets_cli(ctx, host: str, port: str):
|
|
499
529
|
ctx.obj = sdk.FalServerlessClient(f"{host}:{port}")
|
|
500
530
|
|
|
501
531
|
|
|
502
532
|
@secrets_cli.command("list")
|
|
533
|
+
@debug_option()
|
|
503
534
|
@click.pass_obj
|
|
504
535
|
def list_secrets(client: api.FalServerlessClient):
|
|
505
536
|
table = Table(title="Secrets")
|
|
@@ -516,6 +547,7 @@ def list_secrets(client: api.FalServerlessClient):
|
|
|
516
547
|
@secrets_cli.command("set")
|
|
517
548
|
@click.argument("secret_name", required=True)
|
|
518
549
|
@click.argument("secret_value", required=True)
|
|
550
|
+
@debug_option()
|
|
519
551
|
@click.pass_obj
|
|
520
552
|
def set_secret(client: api.FalServerlessClient, secret_name: str, secret_value: str):
|
|
521
553
|
with client.connect() as connection:
|
|
@@ -525,6 +557,7 @@ def set_secret(client: api.FalServerlessClient, secret_name: str, secret_value:
|
|
|
525
557
|
|
|
526
558
|
@secrets_cli.command("delete")
|
|
527
559
|
@click.argument("secret_name", required=True)
|
|
560
|
+
@debug_option()
|
|
528
561
|
@click.pass_obj
|
|
529
562
|
def delete_secret(client: api.FalServerlessClient, secret_name: str):
|
|
530
563
|
with client.connect() as connection:
|
|
@@ -583,7 +616,3 @@ def _get_user_id() -> str:
|
|
|
583
616
|
return user_id
|
|
584
617
|
except Exception as e:
|
|
585
618
|
raise api.FalServerlessError(f"Could not parse the user data: {e}")
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if __name__ == "__main__":
|
|
589
|
-
cli()
|
fal/console/ux.py
CHANGED
|
@@ -3,15 +3,12 @@ from __future__ import annotations
|
|
|
3
3
|
import webbrowser
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def
|
|
7
|
-
"""Gets a reference to the default browser, if available.
|
|
8
|
-
|
|
9
|
-
This allows us to decide on a flow before showing the actual browser window.
|
|
10
|
-
It also avoids unwanted output in the console from the standard `webbrowser.open()`.
|
|
11
|
-
|
|
12
|
-
See https://stackoverflow.com/a/19199794
|
|
13
|
-
"""
|
|
6
|
+
def maybe_open_browser_tab(url) -> None:
|
|
14
7
|
try:
|
|
15
|
-
|
|
8
|
+
# Avoids unwanted output in the console from the standard `webbrowser.open()`.
|
|
9
|
+
# See https://stackoverflow.com/a/19199794
|
|
10
|
+
browser = webbrowser.get()
|
|
11
|
+
|
|
12
|
+
browser.open_new_tab(url)
|
|
16
13
|
except webbrowser.Error:
|
|
17
|
-
|
|
14
|
+
pass
|
fal/workflows.py
CHANGED
|
@@ -12,6 +12,7 @@ import rich
|
|
|
12
12
|
from openapi_fal_rest.api.workflows import (
|
|
13
13
|
create_or_update_workflow_workflows_post as publish_workflow,
|
|
14
14
|
)
|
|
15
|
+
from openapi_fal_rest.models.http_validation_error import HTTPValidationError
|
|
15
16
|
from pydantic import BaseModel
|
|
16
17
|
from rich.syntax import Syntax
|
|
17
18
|
|
|
@@ -363,7 +364,7 @@ class Workflow:
|
|
|
363
364
|
|
|
364
365
|
to_dict = to_json
|
|
365
366
|
|
|
366
|
-
def publish(self, title: str, *, is_public: bool = True)
|
|
367
|
+
def publish(self, title: str, *, is_public: bool = True):
|
|
367
368
|
workflow_contents = publish_workflow.TypedWorkflow(
|
|
368
369
|
name=self.name,
|
|
369
370
|
title=title,
|
|
@@ -376,14 +377,14 @@ class Workflow:
|
|
|
376
377
|
)
|
|
377
378
|
if isinstance(published_workflow, Exception):
|
|
378
379
|
raise published_workflow
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
380
|
+
if isinstance(published_workflow, HTTPValidationError):
|
|
381
|
+
raise RuntimeError(published_workflow.detail)
|
|
382
|
+
if not published_workflow:
|
|
383
|
+
raise RuntimeError("Failed to publish the workflow")
|
|
384
|
+
|
|
385
|
+
# NOTE: dropping the provider prefix from the user_id
|
|
386
|
+
user_id_part = published_workflow.user_id.split("|")[-1]
|
|
387
|
+
return f"{user_id_part}/{published_workflow.name}"
|
|
387
388
|
|
|
388
389
|
|
|
389
390
|
def create_workflow(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.6
|
|
4
4
|
Summary: fal is an easy-to-use Serverless Python Framework
|
|
5
5
|
Author: Features & Labels
|
|
6
6
|
Author-email: hello@fal.ai
|
|
@@ -29,15 +29,19 @@ Requires-Dist: pathspec (>=0.11.1,<0.12.0)
|
|
|
29
29
|
Requires-Dist: pillow (>=10.2.0,<11.0.0)
|
|
30
30
|
Requires-Dist: portalocker (>=2.7.0,<3.0.0)
|
|
31
31
|
Requires-Dist: pydantic (<2.0)
|
|
32
|
-
Requires-Dist: pyjwt (>=2.8.0,<3.0.0)
|
|
32
|
+
Requires-Dist: pyjwt[crypto] (>=2.8.0,<3.0.0)
|
|
33
33
|
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
|
|
34
34
|
Requires-Dist: rich (>=13.3.2,<14.0.0)
|
|
35
|
+
Requires-Dist: rich_click
|
|
35
36
|
Requires-Dist: structlog (>=22.3.0,<23.0.0)
|
|
36
37
|
Requires-Dist: types-python-dateutil (>=2.8.0,<3.0.0)
|
|
37
38
|
Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
|
|
38
39
|
Requires-Dist: websockets (>=12.0,<13.0)
|
|
39
40
|
Description-Content-Type: text/markdown
|
|
40
41
|
|
|
42
|
+
[](https://pypi.org/project/fal)
|
|
43
|
+
[](https://github.com/fal-ai/fal/actions)
|
|
44
|
+
|
|
41
45
|
# fal
|
|
42
46
|
|
|
43
47
|
fal is a serverless Python runtime that lets you run and scale code in the cloud with no infra management.
|
|
@@ -41,17 +41,18 @@ openapi_fal_rest/models/workflow_schema_output.py,sha256=EblwSPAGfWfYVWw_WSSaBzQ
|
|
|
41
41
|
openapi_fal_rest/py.typed,sha256=8ZJUsxZiuOy1oJeVhsTWQhTG_6pTVHVXk5hJL79ebTk,25
|
|
42
42
|
openapi_fal_rest/types.py,sha256=GLwJwOotUOdfqryo_r0naw55-dh6Ilm4IvxePekSACk,994
|
|
43
43
|
fal/__init__.py,sha256=6SvCuotCb0tuqSWDZSFDjtySktJ5m1QpVIlefumJpvM,1199
|
|
44
|
+
fal/__main__.py,sha256=8hDtWlaFZK24KhfNq_ZKgtXqYHsDQDetukOCMlsbW0Q,59
|
|
44
45
|
fal/_serialization.py,sha256=l_dZuSX5BT7SogXw1CalYLfT2H3zy3tfq4y6jHuxZqQ,4201
|
|
45
46
|
fal/api.py,sha256=Qack_oYNkvF4qown3P_oKvyvRfTJkhOG7PL1xpa8FUQ,32872
|
|
46
47
|
fal/app.py,sha256=KAIgvBBpvzp6oY8BpH5hFOLDUpG4bjtwlV5jPGj2IE0,12487
|
|
47
|
-
fal/apps.py,sha256=
|
|
48
|
+
fal/apps.py,sha256=UhR6mq8jBiTAp-QvUnvbnMNcuJ5wHIKSqdlfyx8aBQ8,6829
|
|
48
49
|
fal/auth/__init__.py,sha256=ZnR1fxonzDk0UhS3-i33Kq2xOrN-leYXvJ-Ddnj94xc,3594
|
|
49
|
-
fal/auth/auth0.py,sha256=
|
|
50
|
+
fal/auth/auth0.py,sha256=5y4-9udOSX2-N_zvinLCpFwl10MdaPydZX2v9GQMZEE,5406
|
|
50
51
|
fal/auth/local.py,sha256=lZqp4j32l2xFpY8zYvLoIHHyJrNAJDcm5MxgsLpY_pw,1786
|
|
51
|
-
fal/cli.py,sha256=
|
|
52
|
+
fal/cli.py,sha256=bzoN2_oMgSldNQqJH7TCD_uokmH0-gGrdYCciA-EAVk,18338
|
|
52
53
|
fal/console/__init__.py,sha256=ernZ4bzvvliQh5SmrEqQ7lA5eVcbw6Ra2jalKtA7dxg,132
|
|
53
54
|
fal/console/icons.py,sha256=De9MfFaSkO2Lqfne13n3PrYfTXJVIzYZVqYn5BWsdrA,108
|
|
54
|
-
fal/console/ux.py,sha256=
|
|
55
|
+
fal/console/ux.py,sha256=KMQs3UHQvVHDxDQQqlot-WskVKoMQXOE3jiVkkfmIMY,356
|
|
55
56
|
fal/env.py,sha256=-fA8x62BbOX3MOuO0maupa-_QJ9PNwr8ogfeG11QUyQ,53
|
|
56
57
|
fal/exceptions/__init__.py,sha256=Q4LCSqIrJ8GFQZWH5BvWL5mDPR0HwYQuIhNvsdiOkEU,938
|
|
57
58
|
fal/exceptions/_base.py,sha256=LeQmx-soL_-s1742WKN18VwTVjUuYP0L0BdQHPJBpM4,460
|
|
@@ -81,8 +82,8 @@ fal/toolkit/mainify.py,sha256=E7gE45nZQZoaJdSlIq0mqajcH-IjcuPBWFmKm5hvhAU,406
|
|
|
81
82
|
fal/toolkit/optimize.py,sha256=OIhX0T-efRMgUJDpvL0bujdun5SovZgTdKxNOv01b_Y,1394
|
|
82
83
|
fal/toolkit/utils/__init__.py,sha256=b3zVpm50Upx1saXU7RiV9r9in6-Chs4OU9KRjBv7MYI,83
|
|
83
84
|
fal/toolkit/utils/download_utils.py,sha256=bigcLJjLK1OBAGxpYisJ0-5vcQCh0HAPuCykPrcCNd0,15596
|
|
84
|
-
fal/workflows.py,sha256=
|
|
85
|
-
fal-0.12.
|
|
86
|
-
fal-0.12.
|
|
87
|
-
fal-0.12.
|
|
88
|
-
fal-0.12.
|
|
85
|
+
fal/workflows.py,sha256=hkyDk5KQCDcjyUbo_IhQePGP8t4nxzZ7Uw6rVbLtdq4,14448
|
|
86
|
+
fal-0.12.6.dist-info/entry_points.txt,sha256=nE9GBVV3PdBosudFwbIzZQUe_9lfPR6EH8K_FdDASnM,62
|
|
87
|
+
fal-0.12.6.dist-info/METADATA,sha256=qbt8-SaiKeEfaFR1BqOnIt5Kau6by-Q5NU3kViGwez8,3212
|
|
88
|
+
fal-0.12.6.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
|
89
|
+
fal-0.12.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|