fal 1.39.2__py3-none-any.whl → 1.40.1__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 CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.39.2'
32
- __version_tuple__ = version_tuple = (1, 39, 2)
31
+ __version__ = version = '1.40.1'
32
+ __version_tuple__ = version_tuple = (1, 40, 1)
33
33
 
34
34
  __commit_id__ = commit_id = None
fal/app.py CHANGED
@@ -300,7 +300,7 @@ def _print_python_packages() -> None:
300
300
  class App(BaseServable):
301
301
  requirements: ClassVar[list[str]] = []
302
302
  local_python_modules: ClassVar[list[str]] = []
303
- machine_type: ClassVar[str] = "S"
303
+ machine_type: ClassVar[str | list[str]] = "S"
304
304
  num_gpus: ClassVar[int | None] = None
305
305
  host_kwargs: ClassVar[dict[str, Any]] = {
306
306
  "_scheduler": "nomad",
fal/auth/__init__.py CHANGED
@@ -17,6 +17,15 @@ class GoogleColabState:
17
17
  self.lock = Lock()
18
18
  self.secret: Optional[str] = None
19
19
 
20
+ def __getstate__(self):
21
+ state = self.__dict__.copy()
22
+ state["lock"] = None # type: ignore
23
+ return state
24
+
25
+ def __setstate__(self, state):
26
+ self.__dict__.update(state)
27
+ self.lock = Lock()
28
+
20
29
 
21
30
  _colab_state = GoogleColabState()
22
31
 
fal/cli/main.py CHANGED
@@ -16,6 +16,7 @@ from . import (
16
16
  files,
17
17
  keys,
18
18
  profile,
19
+ queue,
19
20
  run,
20
21
  runners,
21
22
  secrets,
@@ -49,6 +50,7 @@ def _get_main_parser() -> argparse.ArgumentParser:
49
50
  api,
50
51
  auth,
51
52
  apps,
53
+ queue,
52
54
  deploy,
53
55
  run,
54
56
  keys,
fal/cli/queue.py ADDED
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from http import HTTPStatus
5
+
6
+ import httpx
7
+
8
+ from fal.rest_client import REST_CLIENT
9
+
10
+ from .parser import FalClientParser, get_output_parser
11
+
12
+
13
+ def _queue_size(args):
14
+ from .deploy import _get_user
15
+
16
+ user = _get_user()
17
+
18
+ url = f"{REST_CLIENT.base_url}/applications/{user.username}/{args.app_name}/queue"
19
+ headers = REST_CLIENT.get_headers()
20
+
21
+ with httpx.Client(base_url=REST_CLIENT.base_url, headers=headers, timeout=300) as c:
22
+ resp = c.get(url)
23
+
24
+ if resp.status_code != HTTPStatus.OK:
25
+ try:
26
+ detail = resp.json().get("detail", resp.text)
27
+ except Exception:
28
+ detail = resp.text
29
+ raise RuntimeError(f"Failed to get queue size: {detail}")
30
+
31
+ data = resp.json()
32
+ size = data.get("size", 0)
33
+
34
+ if args.output == "json":
35
+ args.console.print(json.dumps({"size": size}))
36
+ else:
37
+ args.console.print(f"Queue size: {size}")
38
+
39
+
40
+ def _queue_flush(args):
41
+ from .deploy import _get_user
42
+
43
+ user = _get_user()
44
+
45
+ url = f"{REST_CLIENT.base_url}/applications/{user.username}/{args.app_name}/queue"
46
+ headers = REST_CLIENT.get_headers()
47
+
48
+ with httpx.Client(base_url=REST_CLIENT.base_url, headers=headers, timeout=300) as c:
49
+ resp = c.delete(url)
50
+
51
+ if resp.status_code != HTTPStatus.OK:
52
+ try:
53
+ detail = resp.json().get("detail", resp.text)
54
+ except Exception:
55
+ detail = resp.text
56
+ raise RuntimeError(f"Failed to flush queue: {detail}")
57
+
58
+ args.console.print("Queue flushed successfully.")
59
+
60
+
61
+ def add_parser(main_subparsers, parents):
62
+ queue_help = "Manage application queues."
63
+ parser = main_subparsers.add_parser(
64
+ "queue",
65
+ description=queue_help,
66
+ help=queue_help,
67
+ parents=parents,
68
+ )
69
+
70
+ subparsers = parser.add_subparsers(
71
+ title="Commands",
72
+ metavar="command",
73
+ required=True,
74
+ parser_class=FalClientParser,
75
+ )
76
+
77
+ size_help = "Get queue size for an application."
78
+ size_parser = subparsers.add_parser(
79
+ "size",
80
+ description=size_help,
81
+ help=size_help,
82
+ parents=[*parents, get_output_parser()],
83
+ )
84
+ size_parser.add_argument(
85
+ "app_name",
86
+ help="Application name (do not prefix with owner).",
87
+ )
88
+ size_parser.set_defaults(func=_queue_size)
89
+
90
+ flush_help = "Flush all pending requests in an application queue."
91
+ flush_parser = subparsers.add_parser(
92
+ "flush",
93
+ description=flush_help,
94
+ help=flush_help,
95
+ parents=parents,
96
+ )
97
+ flush_parser.add_argument(
98
+ "app_name",
99
+ help="Application name.",
100
+ )
101
+ flush_parser.set_defaults(func=_queue_flush)
fal/logging/__init__.py CHANGED
@@ -6,7 +6,6 @@ import structlog
6
6
  from structlog.typing import EventDict, WrappedLogger
7
7
 
8
8
  from .style import LEVEL_STYLES
9
- from .user import AddUserIdProcessor
10
9
 
11
10
  # Unfortunately structlog console processor does not support
12
11
  # more general theming as a public API. Consider a PR on the
@@ -43,7 +42,6 @@ structlog.configure(
43
42
  structlog.stdlib.PositionalArgumentsFormatter(),
44
43
  structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S"),
45
44
  structlog.processors.StackInfoRenderer(),
46
- AddUserIdProcessor(),
47
45
  _console_log_output,
48
46
  ],
49
47
  wrapper_class=structlog.stdlib.BoundLogger,
@@ -159,6 +159,18 @@ class FalV2TokenManager:
159
159
  expires_at=datetime.fromisoformat(result["expires_at"]),
160
160
  )
161
161
 
162
+ def __getstate__(self) -> dict[str, Any]:
163
+ state = self.__dict__.copy()
164
+ # Remove the lock from the state dictionary
165
+ del state["_lock"]
166
+ return state
167
+
168
+ def __setstate__(self, state: dict[str, Any]) -> None:
169
+ # Restore the instance attributes
170
+ self.__dict__.update(state)
171
+ # Recreate the lock
172
+ self._lock = threading.Lock()
173
+
162
174
 
163
175
  class FalV3TokenManager(FalV2TokenManager):
164
176
  token_cls: type[FalV2Token] = FalV3Token
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.39.2
3
+ Version: 1.40.1
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
@@ -1,10 +1,10 @@
1
1
  fal/__init__.py,sha256=wXs1G0gSc7ZK60-bHe-B2m0l_sA6TrFk4BxY0tMoLe8,784
2
2
  fal/__main__.py,sha256=4JMK66Wj4uLZTKbF-sT3LAxOsr6buig77PmOkJCRRxw,83
3
- fal/_fal_version.py,sha256=J8OISQMYQX6BPD5dSFSbfEKap5J-Az3VgM5Q9FjiDtQ,706
3
+ fal/_fal_version.py,sha256=XulopT_VgT2mWr-TUuH1VMduLqKc7_3J0NxfyFwMu44,706
4
4
  fal/_serialization.py,sha256=npXNsFJ5G7jzBeBIyVMH01Ww34mGY4XWhHpRbSrTtnQ,7598
5
5
  fal/_version.py,sha256=1BbTFnucNC_6ldKJ_ZoC722_UkW4S9aDBSW9L0fkKAw,2315
6
6
  fal/api.py,sha256=U_TBUBhkIvA5wFVOeqQejk-8Yxhy4pgWY4DLoelWxjU,49369
7
- fal/app.py,sha256=sSWr2pPjaTSJbKuhwp5gCjLEnoumjto08KBNzzGY8og,25978
7
+ fal/app.py,sha256=V4aBmtRpn7ysiuoX2ojSu4FyJ-T6ee14koIJ1VSQ0Dw,25990
8
8
  fal/apps.py,sha256=pzCd2mrKl5J_4oVc40_pggvPtFahXBCdrZXWpnaEJVs,12130
9
9
  fal/config.py,sha256=1HRaOJFOAjB7fbQoEPCSH85gMvEEMIMPeupVWgrHVgU,3572
10
10
  fal/container.py,sha256=FTsa5hOW4ars-yV1lUoc0BNeIIvAZcpw7Ftyt3A4m_w,2000
@@ -17,7 +17,7 @@ fal/sdk.py,sha256=iKpyL4RrWCdaFMK4wiIM3zOuM2H0VsN0wv8wF9OBxHM,28099
17
17
  fal/sync.py,sha256=ZuIJA2-hTPNANG9B_NNJZUsO68EIdTH0dc9MzeVE2VU,4340
18
18
  fal/utils.py,sha256=iQTBG3-i6JZgHkkwbY_I4210g0xoW-as51yrke608u0,2208
19
19
  fal/workflows.py,sha256=Zl4f6Bs085hY40zmqScxDUyCu7zXkukDbW02iYOLTTI,14805
20
- fal/auth/__init__.py,sha256=2mEKdk6_1GclF3cPC3uWSRKFf0KHNIUNAi0xYRbdJ1A,6278
20
+ fal/auth/__init__.py,sha256=mtyQou8DGHC-COjW9WbtRyyzjyt7fMlhVmsB4U-CBh4,6509
21
21
  fal/auth/auth0.py,sha256=g5OgEKe4rsbkLQp6l7EauOAVL6WsmKjuA1wmzmyvvhc,5354
22
22
  fal/auth/local.py,sha256=sndkM6vKpeVny6NHTacVlTbiIFqaksOmw0Viqs_RN1U,1790
23
23
  fal/cli/__init__.py,sha256=padK4o0BFqq61kxAA1qQ0jYr2SuhA2mf90B3AaRkmJA,37
@@ -32,9 +32,10 @@ fal/cli/deploy.py,sha256=aezafp-g8vvLoARl1i84uGd-zIR1TtlSKi9E0dm-Z7E,8703
32
32
  fal/cli/doctor.py,sha256=8SZrYG9Ku0F6LLUHtFdKopdIgZfFkw5E3Mwrxa9KOSk,1613
33
33
  fal/cli/files.py,sha256=-j0q4g53A7CWSczGLdfeUCTSd4zXoV3pfZFdman7JOw,3450
34
34
  fal/cli/keys.py,sha256=iQVMr3WT8CUqSQT3qeCCiy6rRwoux9F-UEaC4bCwMWo,3754
35
- fal/cli/main.py,sha256=s_LxEyz9z64dewk3oiGEI33_h3vJ3IVdu8aY3qydkMo,3345
35
+ fal/cli/main.py,sha256=LDy3gze9TRsvGa4uSNc8NMFmWMLpsyoC-msteICNiso,3371
36
36
  fal/cli/parser.py,sha256=PZi5MWS4Z-3YSPe6np_F87ay4kF6gaYxlP0avByPr-0,5222
37
37
  fal/cli/profile.py,sha256=PAY_ffifCT71VJ8VxfDVaXPT0U1oN8drvWZDFRXwvek,6678
38
+ fal/cli/queue.py,sha256=9Kid3zR6VOFfAdDgnqi2TNN4ocIv5Vs61ASEZnwMa9o,2713
38
39
  fal/cli/run.py,sha256=nAC12Qss4Fg1XmV0qOS9RdGNLYcdoHeRgQMvbTN4P9I,1202
39
40
  fal/cli/runners.py,sha256=AXUB2pq9Ot0VU2cOeJydSgmgTlUm4i6iNgJOClO7ZZw,6533
40
41
  fal/cli/secrets.py,sha256=HfIeO2IZpCEiBC6Cs5Kpi3zckfDnc7GsLwLdgj3NnPU,3085
@@ -46,11 +47,10 @@ fal/exceptions/__init__.py,sha256=m2okJEpax11mnwmoqO_pCGtbt-FvzKiiuMhKo2ok-_8,27
46
47
  fal/exceptions/_base.py,sha256=LwzpMaW_eYQEC5s26h2qGXbNA-S4bOqC8s-bMCX6HjE,1491
47
48
  fal/exceptions/_cuda.py,sha256=L3qvDNaPTthp95IFSBI6pMt3YbRfn1H0inQkj_7NKF8,1719
48
49
  fal/exceptions/auth.py,sha256=fHea3SIeguInJVB5M33IuP4I5e_pVEifck1C_XJTYvc,351
49
- fal/logging/__init__.py,sha256=avgKA2V8GJeUtZuWZJjSYgkkrXKpuDMS-YiIBmLda7w,1599
50
+ fal/logging/__init__.py,sha256=U7DhMpnNqmVdC2XCT5xZkNmYhpL0Q85iDYPeSo_56LU,1532
50
51
  fal/logging/isolate.py,sha256=jIryi46ZVlJ1mfan4HLNQQ3jwMi8z-WwfqqLlttQVkc,2449
51
52
  fal/logging/style.py,sha256=ckIgHzvF4DShM5kQh8F133X53z_vF46snuDHVmo_h9g,386
52
53
  fal/logging/trace.py,sha256=OhzB6d4rQZimBc18WFLqH_9BGfqFFumKKTAGSsmWRMg,1904
53
- fal/logging/user.py,sha256=H7Pg-nqhpzsUb5f6uXyZUeLWAsr3oImQEaYSCIIAlqo,818
54
54
  fal/toolkit/__init__.py,sha256=GR5KxAsNODlhs-DTarJcb5raujActubn0afR7FPueWs,886
55
55
  fal/toolkit/exceptions.py,sha256=8-EMuqDXEofPu-eVoWowc7WEM-ifusithyv6tnsm2MM,301
56
56
  fal/toolkit/kv.py,sha256=5kMk-I5PMRORK4TYc0jqqowjqKkbk7zUIgz9rAIztxE,2364
@@ -61,7 +61,7 @@ fal/toolkit/audio/audio.py,sha256=gt458h989iQ-EhQSH-mCuJuPBY4RneLJE05f_QWU1E0,57
61
61
  fal/toolkit/file/__init__.py,sha256=FbNl6wD-P0aSSTUwzHt4HujBXrbC3ABmaigPQA4hRfg,70
62
62
  fal/toolkit/file/file.py,sha256=_KCKmtmBkBIKD_gFOZALV10dCtOFZTC9MQw2qmdeevw,11013
63
63
  fal/toolkit/file/types.py,sha256=MMAH_AyLOhowQPesOv1V25wB4qgbJ3vYNlnTPbdSv1M,2304
64
- fal/toolkit/file/providers/fal.py,sha256=z2Htg7DJoBxq_y4Q71KOGM1mHvJzUQCGtz2_m2lqK6c,47155
64
+ fal/toolkit/file/providers/fal.py,sha256=P9hm11uKVe6ilmL7CjFztBHswZEHOm4k-K4B36UZe6M,47543
65
65
  fal/toolkit/file/providers/gcp.py,sha256=DKeZpm1MjwbvEsYvkdXUtuLIJDr_UNbqXj_Mfv3NTeo,2437
66
66
  fal/toolkit/file/providers/r2.py,sha256=YqnYkkAo_ZKIa-xoSuDnnidUFwJWHdziAR34PE6irdI,3061
67
67
  fal/toolkit/file/providers/s3.py,sha256=EI45T54Mox7lHZKROss_O8o0DIn3CHP9k1iaNYVrxvg,2714
@@ -143,8 +143,8 @@ openapi_fal_rest/models/workflow_node_type.py,sha256=-FzyeY2bxcNmizKbJI8joG7byRi
143
143
  openapi_fal_rest/models/workflow_schema.py,sha256=4K5gsv9u9pxx2ItkffoyHeNjBBYf6ur5bN4m_zePZNY,2019
144
144
  openapi_fal_rest/models/workflow_schema_input.py,sha256=2OkOXWHTNsCXHWS6EGDFzcJKkW5FIap-2gfO233EvZQ,1191
145
145
  openapi_fal_rest/models/workflow_schema_output.py,sha256=EblwSPAGfWfYVWw_WSSaBzQVju296is9o28rMBAd0mc,1196
146
- fal-1.39.2.dist-info/METADATA,sha256=hGhmMfVOFiN5eEEtWK4DdaV0pu-SOEJU15omH1M60eM,4132
147
- fal-1.39.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
148
- fal-1.39.2.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
149
- fal-1.39.2.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
150
- fal-1.39.2.dist-info/RECORD,,
146
+ fal-1.40.1.dist-info/METADATA,sha256=JyaMRBK_S1vsn84l7jgkGVST0XHgPRdRtMXTu0puPPY,4132
147
+ fal-1.40.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
148
+ fal-1.40.1.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
149
+ fal-1.40.1.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
150
+ fal-1.40.1.dist-info/RECORD,,
fal/logging/user.py DELETED
@@ -1,25 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from structlog.typing import EventDict, WrappedLogger
4
-
5
-
6
- class AddUserIdProcessor:
7
- def __init__(self):
8
- from fal.auth import UserAccess
9
-
10
- self.user_access = UserAccess()
11
-
12
- def __call__(
13
- self, logger: WrappedLogger, method_name: str, event_dict: EventDict
14
- ) -> EventDict:
15
- """The structlog processor that sends the logged user id on every log"""
16
- user_id: str | None = None
17
- try:
18
- user_id = self.user_access.info.get("sub")
19
- except Exception:
20
- # logs are fail-safe, so any exception is safe to ignore
21
- # this is expected to happen only when user is logged out
22
- # or there's no internet connection
23
- pass
24
- event_dict["usr.id"] = user_id
25
- return event_dict
File without changes