fal 1.26.3__py3-none-any.whl → 1.26.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.

Potentially problematic release.


This version of fal might be problematic. Click here for more details.

fal/_fal_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.26.3'
21
- __version_tuple__ = version_tuple = (1, 26, 3)
20
+ __version__ = version = '1.26.5'
21
+ __version_tuple__ = version_tuple = (1, 26, 5)
fal/cli/apps.py CHANGED
@@ -246,7 +246,10 @@ def _add_scale_parser(subparsers, parents):
246
246
  def _set_rev(args):
247
247
  client = get_client(args.host, args.team)
248
248
  with client.connect() as connection:
249
- connection.create_alias(args.app_name, args.app_rev, args.auth)
249
+ alias_info = connection.create_alias(args.app_name, args.app_rev, args.auth)
250
+ table = _apps_table([alias_info])
251
+
252
+ args.console.print(table)
250
253
 
251
254
 
252
255
  def _add_set_rev_parser(subparsers, parents):
fal/cli/profile.py CHANGED
@@ -23,14 +23,38 @@ def _list(args):
23
23
 
24
24
 
25
25
  def _set(args):
26
- with Config().edit() as config:
27
- config.set_internal("profile", args.PROFILE)
28
- args.console.print(f"Default profile set to [cyan]{args.PROFILE}[/].")
29
- config.profile = args.PROFILE
30
- if not config.get("key"):
26
+ config = Config()
27
+
28
+ # Check if the profile exists
29
+ if args.PROFILE not in config._config:
30
+ # Profile doesn't exist, offer to create it
31
+ args.console.print(f"Profile [cyan]{args.PROFILE}[/] does not exist.")
32
+ create_profile = input("Would you like to create it? (y/N): ").strip().lower()
33
+
34
+ if create_profile in ["y", "yes"]:
35
+ # Create the profile by setting it
36
+ with config.edit() as config:
37
+ config.set_internal("profile", args.PROFILE)
38
+ config._config[args.PROFILE] = {}
39
+ config._profile = args.PROFILE
31
40
  args.console.print(
32
- "No key set for profile. Use [bold]fal profile key[/] to set a key."
41
+ f"Profile [cyan]{args.PROFILE}[/] created and set as default."
33
42
  )
43
+ else:
44
+ args.console.print("Profile creation cancelled.")
45
+ return
46
+ else:
47
+ # Profile exists, just set it as default
48
+ with config.edit() as config:
49
+ config.set_internal("profile", args.PROFILE)
50
+ config._profile = args.PROFILE
51
+ args.console.print(f"Default profile set to [cyan]{args.PROFILE}[/].")
52
+
53
+ # Check if key is set for the profile
54
+ if not config.get("key"):
55
+ args.console.print(
56
+ "No key set for profile. Use [bold]fal profile key[/] to set a key."
57
+ )
34
58
 
35
59
 
36
60
  def _unset(args, config: Config | None = None):
@@ -42,6 +66,8 @@ def _unset(args, config: Config | None = None):
42
66
 
43
67
 
44
68
  def _key_set(args):
69
+ config = Config(validate_profile=True)
70
+
45
71
  while True:
46
72
  key = input("Enter the key: ")
47
73
  if ":" in key:
@@ -50,7 +76,7 @@ def _key_set(args):
50
76
  "[red]Invalid key. The key must be in the format [bold]key:value[/].[/]"
51
77
  )
52
78
 
53
- with Config().edit() as config:
79
+ with config.edit():
54
80
  config.set("key", key)
55
81
  args.console.print(f"Key set for profile [cyan]{config.profile}[/].")
56
82
 
@@ -61,6 +87,24 @@ def _host_set(args):
61
87
  args.console.print(f"Fal host set to [cyan]{args.HOST}[/].")
62
88
 
63
89
 
90
+ def _create(args):
91
+ config = Config()
92
+
93
+ # Check if the profile already exists
94
+ if args.PROFILE in config._config:
95
+ args.console.print(f"Profile [cyan]{args.PROFILE}[/] already exists.")
96
+ return
97
+
98
+ # Create the profile
99
+ with config.edit() as config:
100
+ config._config[args.PROFILE] = {}
101
+
102
+ args.console.print(f"Profile [cyan]{args.PROFILE}[/] created.")
103
+ args.console.print(
104
+ f"Use [bold]fal profile set {args.PROFILE}[/] to set it as default."
105
+ )
106
+
107
+
64
108
  def _delete(args):
65
109
  with Config().edit() as config:
66
110
  if config.profile == args.PROFILE:
@@ -96,7 +140,7 @@ def add_parser(main_subparsers, parents):
96
140
  )
97
141
  list_parser.set_defaults(func=_list)
98
142
 
99
- set_help = "Set default profile."
143
+ set_help = "Set default profile. If the profile doesn't exist, you'll be prompted to create it." # noqa: E501
100
144
  set_parser = subparsers.add_parser(
101
145
  "set",
102
146
  description=set_help,
@@ -140,6 +184,19 @@ def add_parser(main_subparsers, parents):
140
184
  )
141
185
  host_set_parser.set_defaults(func=_host_set)
142
186
 
187
+ create_help = "Create a new profile. Use 'fal profile set <name>' to set it as default after creation." # noqa: E501
188
+ create_parser = subparsers.add_parser(
189
+ "create",
190
+ description=create_help,
191
+ help=create_help,
192
+ parents=parents,
193
+ )
194
+ create_parser.add_argument(
195
+ "PROFILE",
196
+ help="Profile name.",
197
+ )
198
+ create_parser.set_defaults(func=_create)
199
+
143
200
  delete_help = "Delete profile."
144
201
  delete_parser = subparsers.add_parser(
145
202
  "delete",
fal/config.py CHANGED
@@ -4,8 +4,9 @@ import os
4
4
  from contextlib import contextmanager
5
5
  from typing import Dict, Iterator, List, Optional
6
6
 
7
- SETTINGS_SECTION = "__internal__" # legacy
8
- DEFAULT_PROFILE = "default"
7
+ SETTINGS_SECTION = "__internal__"
8
+
9
+ NO_PROFILE_ERROR = ValueError("No profile set.")
9
10
 
10
11
 
11
12
  class Config:
@@ -15,7 +16,7 @@ class Config:
15
16
 
16
17
  DEFAULT_CONFIG_PATH = "~/.fal/config.toml"
17
18
 
18
- def __init__(self):
19
+ def __init__(self, *, validate_profile: bool = False):
19
20
  import tomli
20
21
 
21
22
  self.config_path = os.path.expanduser(
@@ -28,11 +29,17 @@ class Config:
28
29
  except FileNotFoundError:
29
30
  self._config = {}
30
31
 
31
- profile = (
32
- os.getenv("FAL_PROFILE") or self.get_internal("profile") or DEFAULT_PROFILE
33
- )
32
+ profile = os.getenv("FAL_PROFILE") or self.get_internal("profile")
33
+
34
+ # Try to set the profile, but don't fail if it doesn't exist
35
+ try:
36
+ self.profile = profile
37
+ except ValueError:
38
+ # Profile doesn't exist, set to None
39
+ self._profile = None
34
40
 
35
- self.profile = profile
41
+ if validate_profile and not self.profile:
42
+ raise NO_PROFILE_ERROR
36
43
 
37
44
  @property
38
45
  def profile(self) -> Optional[str]:
@@ -41,9 +48,10 @@ class Config:
41
48
  @profile.setter
42
49
  def profile(self, value: Optional[str]) -> None:
43
50
  if value and value not in self._config:
44
- # Make sure the section exists
45
- self._config[value] = {}
46
- self.set_internal("profile", value)
51
+ # Don't automatically create profiles - they should be created explicitly
52
+ raise ValueError(
53
+ f"Profile '{value}' does not exist. Create it first or use the profile set command." # noqa: E501
54
+ )
47
55
  elif not value:
48
56
  self.unset_internal("profile")
49
57
 
@@ -53,11 +61,7 @@ class Config:
53
61
  keys: List[str] = []
54
62
  for key in self._config:
55
63
  if key != SETTINGS_SECTION:
56
- if key == DEFAULT_PROFILE:
57
- # Add it at the beginning
58
- keys.insert(0, key)
59
- else:
60
- keys.append(key)
64
+ keys.append(key)
61
65
 
62
66
  return keys
63
67
 
@@ -75,13 +79,13 @@ class Config:
75
79
 
76
80
  def set(self, key: str, value: str) -> None:
77
81
  if not self.profile:
78
- raise ValueError("No profile set.")
82
+ raise NO_PROFILE_ERROR
79
83
 
80
84
  self._config[self.profile][key] = value
81
85
 
82
86
  def unset(self, key: str) -> None:
83
87
  if not self.profile:
84
- raise ValueError("No profile set.")
88
+ raise NO_PROFILE_ERROR
85
89
 
86
90
  self._config.get(self.profile, {}).pop(key, None)
87
91
 
fal/files.py CHANGED
@@ -56,6 +56,16 @@ class FalFileSystem(AbstractFileSystem):
56
56
  raise FalServerlessException(detail)
57
57
  return response
58
58
 
59
+ def _abspath(self, rpath):
60
+ if rpath.startswith("/"):
61
+ return rpath
62
+
63
+ cwd = "/data"
64
+ if rpath in [".", ""]:
65
+ return cwd
66
+
67
+ return posixpath.join(cwd, rpath)
68
+
59
69
  def _ls(self, path):
60
70
  response = self._request("GET", f"/files/list/{path}")
61
71
  files = response.json()
@@ -73,7 +83,7 @@ class FalFileSystem(AbstractFileSystem):
73
83
  )
74
84
 
75
85
  def ls(self, path, detail=True, **kwargs):
76
- abs_path = "/" + path.lstrip("/")
86
+ abs_path = self._abspath(path)
77
87
  if abs_path in self.dircache:
78
88
  entries = self.dircache[abs_path]
79
89
  elif abs_path in ["/", "", "."]:
@@ -95,20 +105,29 @@ class FalFileSystem(AbstractFileSystem):
95
105
  return [entry["name"] for entry in entries]
96
106
 
97
107
  def info(self, path, **kwargs):
98
- parent = posixpath.dirname(path)
108
+ abs_path = self._abspath(path)
109
+ if abs_path == "/":
110
+ return {
111
+ "name": "/",
112
+ "size": 0,
113
+ "type": "directory",
114
+ "mtime": 0,
115
+ }
116
+ parent = posixpath.dirname(abs_path)
99
117
  entries = self.ls(parent, detail=True)
100
118
  for entry in entries:
101
- if entry["name"] == path:
119
+ if entry["name"] == abs_path:
102
120
  return entry
103
- raise FileNotFoundError(f"File not found: {path}")
121
+ raise FileNotFoundError(f"File not found: {abs_path}")
104
122
 
105
123
  def get_file(self, rpath, lpath, **kwargs):
106
- if self.isdir(rpath):
124
+ abs_rpath = self._abspath(rpath)
125
+ if self.isdir(abs_rpath):
107
126
  os.makedirs(lpath, exist_ok=True)
108
127
  return
109
128
 
110
129
  with open(lpath, "wb") as fobj:
111
- response = self._request("GET", f"/files/file/{rpath}")
130
+ response = self._request("GET", f"/files/file/{abs_rpath}")
112
131
  fobj.write(response.content)
113
132
 
114
133
  def _put_file_part(self, rpath, lpath, upload_id, part_number, chunk_size):
@@ -177,6 +196,8 @@ class FalFileSystem(AbstractFileSystem):
177
196
  if os.path.isdir(lpath):
178
197
  return
179
198
 
199
+ abs_rpath = self._abspath(rpath)
200
+
180
201
  size = os.path.getsize(lpath)
181
202
  with Progress(
182
203
  SpinnerColumn(),
@@ -185,29 +206,31 @@ class FalFileSystem(AbstractFileSystem):
185
206
  TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
186
207
  ) as progress:
187
208
  if size > MULTIPART_THRESHOLD:
188
- self._put_file_multipart(lpath, rpath, size, progress)
209
+ self._put_file_multipart(lpath, abs_rpath, size, progress)
189
210
  else:
190
211
  task = progress.add_task(f"{os.path.basename(lpath)}", total=1)
191
212
  with open(lpath, "rb") as fobj:
192
213
  self._request(
193
214
  "POST",
194
- f"/files/file/local/{rpath}",
215
+ f"/files/file/local/{abs_rpath}",
195
216
  files={"file_upload": (posixpath.basename(lpath), fobj)},
196
217
  )
197
218
  progress.advance(task)
198
219
  self.dircache.clear()
199
220
 
200
221
  def put_file_from_url(self, url, rpath, mode="overwrite", **kwargs):
222
+ abs_rpath = self._abspath(rpath)
201
223
  self._request(
202
224
  "POST",
203
- f"/files/file/url/{rpath}",
225
+ f"/files/file/url/{abs_rpath}",
204
226
  json={"url": url},
205
227
  )
206
228
  self.dircache.clear()
207
229
 
208
230
  def rm(self, path, **kwargs):
231
+ abs_path = self._abspath(path)
209
232
  self._request(
210
233
  "DELETE",
211
- f"/files/file/{path}",
234
+ f"/files/file/{abs_path}",
212
235
  )
213
236
  self.dircache.clear()
fal/sdk.py CHANGED
@@ -735,7 +735,7 @@ class FalServerlessConnection:
735
735
  alias: str,
736
736
  revision: str,
737
737
  auth_mode: AuthMode,
738
- ):
738
+ ) -> AliasInfo:
739
739
  if auth_mode == "public":
740
740
  auth = isolate_proto.ApplicationAuthMode.PUBLIC
741
741
  elif auth_mode == "shared":
@@ -750,7 +750,8 @@ class FalServerlessConnection:
750
750
  revision=revision,
751
751
  auth_mode=auth,
752
752
  )
753
- self.stub.SetAlias(request)
753
+ res = self.stub.SetAlias(request)
754
+ return from_grpc(res.alias_info)
754
755
 
755
756
  def delete_alias(self, alias: str) -> str | None:
756
757
  request = isolate_proto.DeleteAliasRequest(alias=alias)
@@ -9,7 +9,7 @@ from contextlib import contextmanager
9
9
  from dataclasses import dataclass
10
10
  from datetime import datetime, timezone
11
11
  from pathlib import Path
12
- from typing import Any, Generator, Generic, TypeVar
12
+ from typing import Any, Dict, Generator, Generic, TypeVar
13
13
  from urllib.error import HTTPError
14
14
  from urllib.parse import urlparse, urlunparse
15
15
  from urllib.request import Request, urlopen
@@ -69,6 +69,19 @@ def _maybe_retry_request(
69
69
  yield response
70
70
 
71
71
 
72
+ def _object_lifecycle_headers(
73
+ headers: dict[str, str],
74
+ object_lifecycle_preference: dict[str, str] | None,
75
+ ):
76
+ if object_lifecycle_preference:
77
+ # Used by V3 CDN
78
+ headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
79
+ # Used by V1 CDN
80
+ headers["X-Fal-Object-Lifecycle-Preference"] = json.dumps(
81
+ object_lifecycle_preference
82
+ )
83
+
84
+
72
85
  @dataclass
73
86
  class FalV2Token:
74
87
  token: str
@@ -451,14 +464,6 @@ class MultipartUploadGCS:
451
464
 
452
465
  @dataclass
453
466
  class FalFileRepository(FalFileRepositoryBase):
454
- def _object_lifecycle_headers(
455
- self,
456
- headers: dict[str, str],
457
- object_lifecycle_preference: dict[str, str] | None,
458
- ):
459
- if object_lifecycle_preference:
460
- headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
461
-
462
467
  def save(
463
468
  self,
464
469
  file: FileData,
@@ -479,9 +484,8 @@ class FalFileRepository(FalFileRepositoryBase):
479
484
  max_concurrency=multipart_max_concurrency,
480
485
  )
481
486
 
482
- headers = {}
483
- if object_lifecycle_preference:
484
- headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
487
+ headers: Dict[str, str] = {}
488
+ _object_lifecycle_headers(headers, object_lifecycle_preference)
485
489
 
486
490
  return self._save(file, "gcs", headers=headers)
487
491
 
@@ -1124,6 +1128,8 @@ class FalFileRepositoryV2(FalFileRepositoryBase):
1124
1128
  "Content-Type": file.content_type,
1125
1129
  }
1126
1130
 
1131
+ _object_lifecycle_headers(headers, object_lifecycle_preference)
1132
+
1127
1133
  storage_url = f"{token.base_upload_url}/upload"
1128
1134
 
1129
1135
  try:
@@ -1195,16 +1201,6 @@ class InMemoryRepository(FileRepository):
1195
1201
 
1196
1202
  @dataclass
1197
1203
  class FalCDNFileRepository(FileRepository):
1198
- def _object_lifecycle_headers(
1199
- self,
1200
- headers: dict[str, str],
1201
- object_lifecycle_preference: dict[str, str] | None,
1202
- ):
1203
- if object_lifecycle_preference:
1204
- headers["X-Fal-Object-Lifecycle-Preference"] = json.dumps(
1205
- object_lifecycle_preference
1206
- )
1207
-
1208
1204
  def save(
1209
1205
  self,
1210
1206
  file: FileData,
@@ -1221,7 +1217,7 @@ class FalCDNFileRepository(FileRepository):
1221
1217
  "X-Fal-File-Name": file.file_name,
1222
1218
  }
1223
1219
 
1224
- self._object_lifecycle_headers(headers, object_lifecycle_preference)
1220
+ _object_lifecycle_headers(headers, object_lifecycle_preference)
1225
1221
 
1226
1222
  url = os.getenv("FAL_CDN_HOST", _FAL_CDN) + "/files/upload"
1227
1223
  request = Request(url, headers=headers, method="POST", data=file.data)
@@ -1288,6 +1284,7 @@ class FalFileRepositoryV3(FileRepository):
1288
1284
  "Accept": "application/json",
1289
1285
  "Content-Type": "application/json",
1290
1286
  }
1287
+ _object_lifecycle_headers(headers, object_lifecycle_preference)
1291
1288
 
1292
1289
  grpc_host = os.environ.get("FAL_HOST", "api.alpha.fal.ai")
1293
1290
  rest_host = grpc_host.replace("api", "rest", 1)
@@ -1376,14 +1373,6 @@ class InternalFalFileRepositoryV3(FileRepository):
1376
1373
  That way it can avoid the need to refresh the token for every upload.
1377
1374
  """
1378
1375
 
1379
- def _object_lifecycle_headers(
1380
- self,
1381
- headers: dict[str, str],
1382
- object_lifecycle_preference: dict[str, str] | None,
1383
- ):
1384
- if object_lifecycle_preference:
1385
- headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
1386
-
1387
1376
  def save(
1388
1377
  self,
1389
1378
  file: FileData,
@@ -1413,7 +1402,7 @@ class InternalFalFileRepositoryV3(FileRepository):
1413
1402
  "X-Fal-File-Name": file.file_name,
1414
1403
  }
1415
1404
 
1416
- self._object_lifecycle_headers(headers, object_lifecycle_preference)
1405
+ _object_lifecycle_headers(headers, object_lifecycle_preference)
1417
1406
 
1418
1407
  url = os.getenv("FAL_CDN_V3_HOST", _FAL_CDN_V3) + "/files/upload"
1419
1408
  request = Request(url, headers=headers, method="POST", data=file.data)
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.26.3
3
+ Version: 1.26.5
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
7
7
  Description-Content-Type: text/markdown
8
8
  Requires-Dist: isolate[build]<0.19.0,>=0.18.0
9
- Requires-Dist: isolate-proto<0.11.0,>=0.10.0
9
+ Requires-Dist: isolate-proto<0.11.0,>=0.10.2
10
10
  Requires-Dist: grpcio<2,>=1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -1,19 +1,19 @@
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=9Qmp6vQjB4unZk_UypODVD9TXWJfujU_wpuyb9wAzpQ,513
3
+ fal/_fal_version.py,sha256=r8-mjCjV1nY6UT0cjXxBKSJyUs5zQ39PpwPh_7phUbA,513
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=wIEt21P1C7U-dYQEcyHUxxuuTnvzFyTpWDoHoaxq7tg,47385
7
7
  fal/app.py,sha256=3RDFV6JUiUk8b3WJanKQYA-kW74t5bqaNy8OYuUH5-Q,25491
8
8
  fal/apps.py,sha256=pzCd2mrKl5J_4oVc40_pggvPtFahXBCdrZXWpnaEJVs,12130
9
- fal/config.py,sha256=19tR4zWr2yqsBRWNhFV1jKMiXAASRz2Et62k68-1r9Y,3290
9
+ fal/config.py,sha256=G3IOTLQuu_VAvzPFdx9v22NpJ9m4gU8qEHic7e7-WwU,3511
10
10
  fal/container.py,sha256=FTsa5hOW4ars-yV1lUoc0BNeIIvAZcpw7Ftyt3A4m_w,2000
11
- fal/files.py,sha256=iwR9jXWmAruP5tSS5-NkY-mZG53Pb80C40SqB0pYRrk,6819
11
+ fal/files.py,sha256=iWkOqCtdoz7_V-wOvV1iB1zg9x7fdGRcmGGyBkCuFXI,7449
12
12
  fal/flags.py,sha256=QonyDM7R2GqfAB1bJr46oriu-fHJCkpUwXuSdanePWg,987
13
13
  fal/project.py,sha256=QgfYfMKmNobMPufrAP_ga1FKcIAlSbw18Iar1-0qepo,2650
14
14
  fal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  fal/rest_client.py,sha256=kGBGmuyHfX1lR910EoKCYPjsyU8MdXawT_cW2q8Sajc,568
16
- fal/sdk.py,sha256=eX_OJVmD6AY5NsLS7VR-LemXTWNEMfsOEfZBgAqytoo,26158
16
+ fal/sdk.py,sha256=tUrwEohQz2B3LN-troH5FcON4VwRnV0zFjB0FRctDBA,26218
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
@@ -23,7 +23,7 @@ fal/auth/local.py,sha256=sndkM6vKpeVny6NHTacVlTbiIFqaksOmw0Viqs_RN1U,1790
23
23
  fal/cli/__init__.py,sha256=padK4o0BFqq61kxAA1qQ0jYr2SuhA2mf90B3AaRkmJA,37
24
24
  fal/cli/_utils.py,sha256=anFfy6qouB8QzH0Yho41GulGiJu3q1KKIwgyVQCzgRQ,1593
25
25
  fal/cli/api.py,sha256=ZuDE_PIC-czzneTAWMwvC7P7WnwIyluNZSuJqzCFhqI,2640
26
- fal/cli/apps.py,sha256=0ex4OWbxcopjEq_BGkwkxCBSTLqUIHmFDz1MWOv06zk,10479
26
+ fal/cli/apps.py,sha256=q0uxuD4h_5tft77QfyFbDz0kGmM51JT39du_OeFytPA,10565
27
27
  fal/cli/auth.py,sha256=Qe-Z3ycXJnOzHimz5PjCQYoni8MF4csmdL19yGN7a1o,5171
28
28
  fal/cli/cli_nested_json.py,sha256=veSZU8_bYV3Iu1PAoxt-4BMBraNIqgH5nughbs2UKvE,13539
29
29
  fal/cli/create.py,sha256=a8WDq-nJLFTeoIXqpb5cr7GR7YR9ZZrQCawNm34KXXE,627
@@ -34,7 +34,7 @@ fal/cli/files.py,sha256=pSgAnTm2eHdP-IPkMIVfnK_Ii7mkSSOVgvbsiFUVBC0,2936
34
34
  fal/cli/keys.py,sha256=7Sf4DT4le89G42eAOt0ltRjbZAtE70AVQ62hmjZhUy0,3059
35
35
  fal/cli/main.py,sha256=LnJCe83Fdr5-i3Fkpvrd9BZPjHtcX_H1EEmy6rVlCz8,3180
36
36
  fal/cli/parser.py,sha256=jYsGQ0BLQuKI7KtN1jnLVYKMbLtez7hPjwTNfG3UPSk,2964
37
- fal/cli/profile.py,sha256=9d6a8IEZhxKoJt4CmvRbqw1Js7HBNkJjng7I_3ggfTw,3941
37
+ fal/cli/profile.py,sha256=9Iz5Prk2mR2JmxBuNPcKAcQJVHlGGXIlKh_7MXDl7U4,5879
38
38
  fal/cli/run.py,sha256=nAC12Qss4Fg1XmV0qOS9RdGNLYcdoHeRgQMvbTN4P9I,1202
39
39
  fal/cli/runners.py,sha256=7efNX9vm6D1aBlg0M5-u5plw3HHC41Sj-N7eRNIHnqw,3689
40
40
  fal/cli/secrets.py,sha256=QKSmazu-wiNF6fOpGL9v2TDYxAjX9KTi7ot7vnv6f5E,2474
@@ -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=4K28gr--5q0nmsm3P76SFoKQj3bPROVwxXrdoMjIiUE,10197
63
63
  fal/toolkit/file/types.py,sha256=MMAH_AyLOhowQPesOv1V25wB4qgbJ3vYNlnTPbdSv1M,2304
64
- fal/toolkit/file/providers/fal.py,sha256=fB8dHO440IxO7PBHBW3XZXHCBBLSoP1oNsSkae7LzsU,47276
64
+ fal/toolkit/file/providers/fal.py,sha256=Ph8v3Cm_eFu1b1AXiPKZQ5r8AWUALD3Wk18uw3z8RDQ,46910
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
@@ -142,8 +142,8 @@ openapi_fal_rest/models/workflow_node_type.py,sha256=-FzyeY2bxcNmizKbJI8joG7byRi
142
142
  openapi_fal_rest/models/workflow_schema.py,sha256=4K5gsv9u9pxx2ItkffoyHeNjBBYf6ur5bN4m_zePZNY,2019
143
143
  openapi_fal_rest/models/workflow_schema_input.py,sha256=2OkOXWHTNsCXHWS6EGDFzcJKkW5FIap-2gfO233EvZQ,1191
144
144
  openapi_fal_rest/models/workflow_schema_output.py,sha256=EblwSPAGfWfYVWw_WSSaBzQVju296is9o28rMBAd0mc,1196
145
- fal-1.26.3.dist-info/METADATA,sha256=wg7eO8-SmdSLKvCnrhEgANa7ihLAwrMedxG4rkDd9tU,4089
146
- fal-1.26.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
- fal-1.26.3.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
148
- fal-1.26.3.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
149
- fal-1.26.3.dist-info/RECORD,,
145
+ fal-1.26.5.dist-info/METADATA,sha256=Z8d49heaHBesij9BvdMX_P9rYafB7562kKIiUSZeH5M,4089
146
+ fal-1.26.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
+ fal-1.26.5.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
148
+ fal-1.26.5.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
149
+ fal-1.26.5.dist-info/RECORD,,
File without changes