fal 1.5.0__py3-none-any.whl → 1.5.2__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 +7 -0
- fal/app.py +4 -2
- fal/toolkit/file/file.py +33 -2
- fal/toolkit/file/providers/fal.py +60 -5
- fal/toolkit/file/types.py +11 -4
- fal/toolkit/image/image.py +5 -0
- {fal-1.5.0.dist-info → fal-1.5.2.dist-info}/METADATA +1 -1
- {fal-1.5.0.dist-info → fal-1.5.2.dist-info}/RECORD +12 -12
- {fal-1.5.0.dist-info → fal-1.5.2.dist-info}/WHEEL +0 -0
- {fal-1.5.0.dist-info → fal-1.5.2.dist-info}/entry_points.txt +0 -0
- {fal-1.5.0.dist-info → fal-1.5.2.dist-info}/top_level.txt +0 -0
fal/_fal_version.py
CHANGED
fal/api.py
CHANGED
|
@@ -971,6 +971,8 @@ class RouteSignature(NamedTuple):
|
|
|
971
971
|
|
|
972
972
|
|
|
973
973
|
class BaseServable:
|
|
974
|
+
version: ClassVar[str] = "unknown"
|
|
975
|
+
|
|
974
976
|
def collect_routes(self) -> dict[RouteSignature, Callable[..., Any]]:
|
|
975
977
|
raise NotImplementedError
|
|
976
978
|
|
|
@@ -1099,9 +1101,14 @@ class BaseServable:
|
|
|
1099
1101
|
def serve(self) -> None:
|
|
1100
1102
|
import asyncio
|
|
1101
1103
|
|
|
1104
|
+
from prometheus_client import Gauge
|
|
1102
1105
|
from starlette_exporter import handle_metrics
|
|
1103
1106
|
from uvicorn import Config
|
|
1104
1107
|
|
|
1108
|
+
# NOTE: this uses the global prometheus registry
|
|
1109
|
+
app_info = Gauge("fal_app_info", "Fal application information", ["version"])
|
|
1110
|
+
app_info.labels(version=self.version).set(1)
|
|
1111
|
+
|
|
1105
1112
|
app = self._build_app()
|
|
1106
1113
|
server = Server(
|
|
1107
1114
|
config=Config(app, host="0.0.0.0", port=8080, timeout_keep_alive=300)
|
fal/app.py
CHANGED
|
@@ -189,7 +189,6 @@ class App(fal.api.BaseServable):
|
|
|
189
189
|
}
|
|
190
190
|
app_name: ClassVar[str]
|
|
191
191
|
app_auth: ClassVar[Literal["private", "public", "shared"]] = "private"
|
|
192
|
-
version: ClassVar[str] = "unknown"
|
|
193
192
|
request_timeout: ClassVar[int | None] = None
|
|
194
193
|
|
|
195
194
|
def __init_subclass__(cls, **kwargs):
|
|
@@ -403,7 +402,10 @@ def _fal_websocket_template(
|
|
|
403
402
|
batch.append(next_input)
|
|
404
403
|
|
|
405
404
|
t0 = loop.time()
|
|
406
|
-
|
|
405
|
+
if inspect.iscoroutinefunction(func):
|
|
406
|
+
output = await func(self, *batch)
|
|
407
|
+
else:
|
|
408
|
+
output = await loop.run_in_executor(None, func, self, *batch) # type: ignore
|
|
407
409
|
total_time = loop.time() - t0
|
|
408
410
|
if not isinstance(output, dict):
|
|
409
411
|
# Handle pydantic output modal
|
fal/toolkit/file/file.py
CHANGED
|
@@ -8,6 +8,7 @@ from urllib.parse import urlparse
|
|
|
8
8
|
from zipfile import ZipFile
|
|
9
9
|
|
|
10
10
|
import pydantic
|
|
11
|
+
from fastapi import Request
|
|
11
12
|
|
|
12
13
|
# https://github.com/pydantic/pydantic/pull/2573
|
|
13
14
|
if not hasattr(pydantic, "__version__") or pydantic.__version__.startswith("1."):
|
|
@@ -24,6 +25,7 @@ from fal.toolkit.file.providers.fal import (
|
|
|
24
25
|
FalCDNFileRepository,
|
|
25
26
|
FalFileRepository,
|
|
26
27
|
FalFileRepositoryV2,
|
|
28
|
+
FalFileRepositoryV3,
|
|
27
29
|
InMemoryRepository,
|
|
28
30
|
)
|
|
29
31
|
from fal.toolkit.file.providers.gcp import GoogleStorageRepository
|
|
@@ -36,6 +38,7 @@ FileRepositoryFactory = Callable[[], FileRepository]
|
|
|
36
38
|
BUILT_IN_REPOSITORIES: dict[RepositoryId, FileRepositoryFactory] = {
|
|
37
39
|
"fal": lambda: FalFileRepository(),
|
|
38
40
|
"fal_v2": lambda: FalFileRepositoryV2(),
|
|
41
|
+
"fal_v3": lambda: FalFileRepositoryV3(),
|
|
39
42
|
"in_memory": lambda: InMemoryRepository(),
|
|
40
43
|
"gcp_storage": lambda: GoogleStorageRepository(),
|
|
41
44
|
"r2": lambda: R2Repository(),
|
|
@@ -53,6 +56,7 @@ get_builtin_repository.__module__ = "__main__"
|
|
|
53
56
|
|
|
54
57
|
DEFAULT_REPOSITORY: FileRepository | RepositoryId = "fal_v2"
|
|
55
58
|
FALLBACK_REPOSITORY: FileRepository | RepositoryId = "cdn"
|
|
59
|
+
OBJECT_LIFECYCLE_PREFERENCE_KEY = "x-fal-object-lifecycle-preference"
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
class File(BaseModel):
|
|
@@ -130,6 +134,7 @@ class File(BaseModel):
|
|
|
130
134
|
fallback_repository: Optional[
|
|
131
135
|
FileRepository | RepositoryId
|
|
132
136
|
] = FALLBACK_REPOSITORY,
|
|
137
|
+
request: Optional[Request] = None,
|
|
133
138
|
) -> File:
|
|
134
139
|
repo = (
|
|
135
140
|
repository
|
|
@@ -139,8 +144,10 @@ class File(BaseModel):
|
|
|
139
144
|
|
|
140
145
|
fdata = FileData(data, content_type, file_name)
|
|
141
146
|
|
|
147
|
+
object_lifecycle_preference = _get_lifecycle_preference(request)
|
|
148
|
+
|
|
142
149
|
try:
|
|
143
|
-
url = repo.save(fdata)
|
|
150
|
+
url = repo.save(fdata, object_lifecycle_preference)
|
|
144
151
|
except Exception:
|
|
145
152
|
if not fallback_repository:
|
|
146
153
|
raise
|
|
@@ -151,7 +158,7 @@ class File(BaseModel):
|
|
|
151
158
|
else get_builtin_repository(fallback_repository)
|
|
152
159
|
)
|
|
153
160
|
|
|
154
|
-
url = fallback_repo.save(fdata)
|
|
161
|
+
url = fallback_repo.save(fdata, object_lifecycle_preference)
|
|
155
162
|
|
|
156
163
|
return cls(
|
|
157
164
|
url=url,
|
|
@@ -171,6 +178,7 @@ class File(BaseModel):
|
|
|
171
178
|
fallback_repository: Optional[
|
|
172
179
|
FileRepository | RepositoryId
|
|
173
180
|
] = FALLBACK_REPOSITORY,
|
|
181
|
+
request: Optional[Request] = None,
|
|
174
182
|
) -> File:
|
|
175
183
|
file_path = Path(path)
|
|
176
184
|
if not file_path.exists():
|
|
@@ -183,12 +191,14 @@ class File(BaseModel):
|
|
|
183
191
|
)
|
|
184
192
|
|
|
185
193
|
content_type = content_type or "application/octet-stream"
|
|
194
|
+
object_lifecycle_preference = _get_lifecycle_preference(request)
|
|
186
195
|
|
|
187
196
|
try:
|
|
188
197
|
url, data = repo.save_file(
|
|
189
198
|
file_path,
|
|
190
199
|
content_type=content_type,
|
|
191
200
|
multipart=multipart,
|
|
201
|
+
object_lifecycle_preference=object_lifecycle_preference,
|
|
192
202
|
)
|
|
193
203
|
except Exception:
|
|
194
204
|
if not fallback_repository:
|
|
@@ -204,6 +214,7 @@ class File(BaseModel):
|
|
|
204
214
|
file_path,
|
|
205
215
|
content_type=content_type,
|
|
206
216
|
multipart=multipart,
|
|
217
|
+
object_lifecycle_preference=object_lifecycle_preference,
|
|
207
218
|
)
|
|
208
219
|
|
|
209
220
|
return cls(
|
|
@@ -261,3 +272,23 @@ class CompressedFile(File):
|
|
|
261
272
|
def __del__(self):
|
|
262
273
|
if self.extract_dir:
|
|
263
274
|
shutil.rmtree(self.extract_dir)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _get_lifecycle_preference(request: Request) -> dict[str, str] | None:
|
|
278
|
+
import json
|
|
279
|
+
|
|
280
|
+
preference_str = (
|
|
281
|
+
request.headers.get(OBJECT_LIFECYCLE_PREFERENCE_KEY)
|
|
282
|
+
if request is not None
|
|
283
|
+
else None
|
|
284
|
+
)
|
|
285
|
+
if preference_str is None:
|
|
286
|
+
return None
|
|
287
|
+
|
|
288
|
+
object_lifecycle_preference = {}
|
|
289
|
+
try:
|
|
290
|
+
object_lifecycle_preference = json.loads(preference_str)
|
|
291
|
+
return object_lifecycle_preference
|
|
292
|
+
except Exception as e:
|
|
293
|
+
print(f"Failed to parse object lifecycle preference: {e}")
|
|
294
|
+
return None
|
|
@@ -19,6 +19,7 @@ from fal.toolkit.file.types import FileData, FileRepository
|
|
|
19
19
|
from fal.toolkit.utils.retry import retry
|
|
20
20
|
|
|
21
21
|
_FAL_CDN = "https://fal.media"
|
|
22
|
+
_FAL_CDN_V3 = "https://v3.fal.media"
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
@dataclass
|
|
@@ -91,11 +92,11 @@ fal_v2_token_manager = FalV2TokenManager()
|
|
|
91
92
|
|
|
92
93
|
@dataclass
|
|
93
94
|
class ObjectLifecyclePreference:
|
|
94
|
-
|
|
95
|
+
expiration_duration_seconds: int
|
|
95
96
|
|
|
96
97
|
|
|
97
98
|
GLOBAL_LIFECYCLE_PREFERENCE = ObjectLifecyclePreference(
|
|
98
|
-
|
|
99
|
+
expiration_duration_seconds=86400
|
|
99
100
|
)
|
|
100
101
|
|
|
101
102
|
|
|
@@ -158,7 +159,9 @@ class FalFileRepositoryBase(FileRepository):
|
|
|
158
159
|
|
|
159
160
|
@dataclass
|
|
160
161
|
class FalFileRepository(FalFileRepositoryBase):
|
|
161
|
-
def save(
|
|
162
|
+
def save(
|
|
163
|
+
self, file: FileData, object_lifecycle_preference: dict[str, str] | None = None
|
|
164
|
+
) -> str:
|
|
162
165
|
return self._save(file, "gcs")
|
|
163
166
|
|
|
164
167
|
|
|
@@ -275,7 +278,9 @@ class MultipartUpload:
|
|
|
275
278
|
@dataclass
|
|
276
279
|
class FalFileRepositoryV2(FalFileRepositoryBase):
|
|
277
280
|
@retry(max_retries=3, base_delay=1, backoff_type="exponential", jitter=True)
|
|
278
|
-
def save(
|
|
281
|
+
def save(
|
|
282
|
+
self, file: FileData, object_lifecycle_preference: dict[str, str] | None = None
|
|
283
|
+
) -> str:
|
|
279
284
|
token = fal_v2_token_manager.get_token()
|
|
280
285
|
headers = {
|
|
281
286
|
"Authorization": f"{token.token_type} {token.token}",
|
|
@@ -327,6 +332,7 @@ class FalFileRepositoryV2(FalFileRepositoryBase):
|
|
|
327
332
|
multipart_threshold: int | None = None,
|
|
328
333
|
multipart_chunk_size: int | None = None,
|
|
329
334
|
multipart_max_concurrency: int | None = None,
|
|
335
|
+
object_lifecycle_preference: dict[str, str] | None = None,
|
|
330
336
|
) -> tuple[str, FileData | None]:
|
|
331
337
|
if multipart is None:
|
|
332
338
|
threshold = multipart_threshold or MultipartUpload.MULTIPART_THRESHOLD
|
|
@@ -347,7 +353,7 @@ class FalFileRepositoryV2(FalFileRepositoryBase):
|
|
|
347
353
|
content_type=content_type,
|
|
348
354
|
file_name=os.path.basename(file_path),
|
|
349
355
|
)
|
|
350
|
-
url = self.save(data)
|
|
356
|
+
url = self.save(data, object_lifecycle_preference)
|
|
351
357
|
|
|
352
358
|
return url, data
|
|
353
359
|
|
|
@@ -357,6 +363,7 @@ class InMemoryRepository(FileRepository):
|
|
|
357
363
|
def save(
|
|
358
364
|
self,
|
|
359
365
|
file: FileData,
|
|
366
|
+
object_lifecycle_preference: dict[str, str] | None = None,
|
|
360
367
|
) -> str:
|
|
361
368
|
return f'data:{file.content_type};base64,{b64encode(file.data).decode("utf-8")}'
|
|
362
369
|
|
|
@@ -367,6 +374,7 @@ class FalCDNFileRepository(FileRepository):
|
|
|
367
374
|
def save(
|
|
368
375
|
self,
|
|
369
376
|
file: FileData,
|
|
377
|
+
object_lifecycle_preference: dict[str, str] | None = None,
|
|
370
378
|
) -> str:
|
|
371
379
|
headers = {
|
|
372
380
|
**self.auth_headers,
|
|
@@ -401,3 +409,50 @@ class FalCDNFileRepository(FileRepository):
|
|
|
401
409
|
"Authorization": f"Bearer {key_id}:{key_secret}",
|
|
402
410
|
"User-Agent": "fal/0.1.0",
|
|
403
411
|
}
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@dataclass
|
|
415
|
+
class FalFileRepositoryV3(FileRepository):
|
|
416
|
+
@retry(max_retries=3, base_delay=1, backoff_type="exponential", jitter=True)
|
|
417
|
+
def save(
|
|
418
|
+
self, file: FileData, user_lifecycle_preference: dict[str, str] | None
|
|
419
|
+
) -> str:
|
|
420
|
+
object_lifecycle_preference = dataclasses.asdict(GLOBAL_LIFECYCLE_PREFERENCE)
|
|
421
|
+
|
|
422
|
+
if user_lifecycle_preference is not None:
|
|
423
|
+
object_lifecycle_preference = {
|
|
424
|
+
key: user_lifecycle_preference[key]
|
|
425
|
+
if key in user_lifecycle_preference
|
|
426
|
+
else value
|
|
427
|
+
for key, value in object_lifecycle_preference.items()
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
headers = {
|
|
431
|
+
**self.auth_headers,
|
|
432
|
+
"Accept": "application/json",
|
|
433
|
+
"Content-Type": file.content_type,
|
|
434
|
+
"X-Fal-File-Name": file.file_name,
|
|
435
|
+
"X-Fal-Object-Lifecycle-Preference": json.dumps(
|
|
436
|
+
object_lifecycle_preference
|
|
437
|
+
),
|
|
438
|
+
}
|
|
439
|
+
url = os.getenv("FAL_CDN_V3_HOST", _FAL_CDN_V3) + "/files/upload"
|
|
440
|
+
request = Request(url, headers=headers, method="POST", data=file.data)
|
|
441
|
+
try:
|
|
442
|
+
with urlopen(request) as response:
|
|
443
|
+
result = json.load(response)
|
|
444
|
+
except HTTPError as e:
|
|
445
|
+
raise FileUploadException(
|
|
446
|
+
f"Error initiating upload. Status {e.status}: {e.reason}"
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
access_url = result["access_url"]
|
|
450
|
+
return access_url
|
|
451
|
+
|
|
452
|
+
@property
|
|
453
|
+
def auth_headers(self) -> dict[str, str]:
|
|
454
|
+
token = fal_v2_token_manager.get_token()
|
|
455
|
+
return {
|
|
456
|
+
"Authorization": f"{token.token_type} {token.token}",
|
|
457
|
+
"User-Agent": "fal/0.1.0",
|
|
458
|
+
}
|
fal/toolkit/file/types.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from mimetypes import guess_extension, guess_type
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Literal
|
|
6
|
+
from typing import Literal, Optional
|
|
7
7
|
from uuid import uuid4
|
|
8
8
|
|
|
9
9
|
|
|
@@ -29,12 +29,18 @@ class FileData:
|
|
|
29
29
|
self.file_name = file_name
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
RepositoryId = Literal[
|
|
32
|
+
RepositoryId = Literal[
|
|
33
|
+
"fal", "fal_v2", "fal_v3", "in_memory", "gcp_storage", "r2", "cdn"
|
|
34
|
+
]
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
@dataclass
|
|
36
38
|
class FileRepository:
|
|
37
|
-
def save(
|
|
39
|
+
def save(
|
|
40
|
+
self,
|
|
41
|
+
data: FileData,
|
|
42
|
+
object_lifecycle_preference: Optional[dict[str, str]] = None,
|
|
43
|
+
) -> str:
|
|
38
44
|
raise NotImplementedError()
|
|
39
45
|
|
|
40
46
|
def save_file(
|
|
@@ -45,6 +51,7 @@ class FileRepository:
|
|
|
45
51
|
multipart_threshold: int | None = None,
|
|
46
52
|
multipart_chunk_size: int | None = None,
|
|
47
53
|
multipart_max_concurrency: int | None = None,
|
|
54
|
+
object_lifecycle_preference: Optional[dict[str, str]] = None,
|
|
48
55
|
) -> tuple[str, FileData | None]:
|
|
49
56
|
if multipart:
|
|
50
57
|
raise NotImplementedError()
|
|
@@ -52,4 +59,4 @@ class FileRepository:
|
|
|
52
59
|
with open(file_path, "rb") as fobj:
|
|
53
60
|
data = FileData(fobj.read(), content_type, Path(file_path).name)
|
|
54
61
|
|
|
55
|
-
return self.save(data), data
|
|
62
|
+
return self.save(data, object_lifecycle_preference), data
|
fal/toolkit/image/image.py
CHANGED
|
@@ -4,6 +4,7 @@ import io
|
|
|
4
4
|
from tempfile import NamedTemporaryFile
|
|
5
5
|
from typing import TYPE_CHECKING, Literal, Optional, Union
|
|
6
6
|
|
|
7
|
+
from fastapi import Request
|
|
7
8
|
from pydantic import BaseModel, Field
|
|
8
9
|
|
|
9
10
|
from fal.toolkit.file.file import DEFAULT_REPOSITORY, FALLBACK_REPOSITORY, File
|
|
@@ -82,6 +83,7 @@ class Image(File):
|
|
|
82
83
|
fallback_repository: Optional[
|
|
83
84
|
FileRepository | RepositoryId
|
|
84
85
|
] = FALLBACK_REPOSITORY,
|
|
86
|
+
request: Optional[Request] = None,
|
|
85
87
|
) -> Image:
|
|
86
88
|
obj = super().from_bytes(
|
|
87
89
|
data,
|
|
@@ -89,6 +91,7 @@ class Image(File):
|
|
|
89
91
|
file_name=file_name,
|
|
90
92
|
repository=repository,
|
|
91
93
|
fallback_repository=fallback_repository,
|
|
94
|
+
request=request,
|
|
92
95
|
)
|
|
93
96
|
obj.width = size.width if size else None
|
|
94
97
|
obj.height = size.height if size else None
|
|
@@ -104,6 +107,7 @@ class Image(File):
|
|
|
104
107
|
fallback_repository: Optional[
|
|
105
108
|
FileRepository | RepositoryId
|
|
106
109
|
] = FALLBACK_REPOSITORY,
|
|
110
|
+
request: Optional[Request] = None,
|
|
107
111
|
) -> Image:
|
|
108
112
|
size = ImageSize(width=pil_image.width, height=pil_image.height)
|
|
109
113
|
if format is None:
|
|
@@ -133,6 +137,7 @@ class Image(File):
|
|
|
133
137
|
file_name,
|
|
134
138
|
repository,
|
|
135
139
|
fallback_repository=fallback_repository,
|
|
140
|
+
request=request,
|
|
136
141
|
)
|
|
137
142
|
|
|
138
143
|
def to_pil(self, mode: str = "RGB") -> PILImage.Image:
|
|
@@ -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=
|
|
3
|
+
fal/_fal_version.py,sha256=P-JlE1bO3FGbbntvKHqxjgKk7ORvjFhybkK-h8R2s5g,411
|
|
4
4
|
fal/_serialization.py,sha256=rD2YiSa8iuzCaZohZwN_MPEB-PpSKbWRDeaIDpTEjyY,7653
|
|
5
5
|
fal/_version.py,sha256=EBGqrknaf1WygENX-H4fBefLvHryvJBBGtVJetaB0NY,266
|
|
6
|
-
fal/api.py,sha256=
|
|
7
|
-
fal/app.py,sha256=
|
|
6
|
+
fal/api.py,sha256=wmXywHvkdKe0AlsPmXt8_nidPhoC_Ho4BrUi7In4Hek,43278
|
|
7
|
+
fal/app.py,sha256=u25k-MLKU_7eux4PuN24iq1zZf5hSeUeYkO7kUIA6uI,18021
|
|
8
8
|
fal/apps.py,sha256=lge7-HITzI20l1oXdlkAzqxdMVtXRfnACIylKRWgCNQ,7151
|
|
9
9
|
fal/container.py,sha256=V7riyyq8AZGwEX9QaqRQDZyDN_bUKeRKV1OOZArXjL0,622
|
|
10
10
|
fal/files.py,sha256=QgfYfMKmNobMPufrAP_ga1FKcIAlSbw18Iar1-0qepo,2650
|
|
@@ -47,13 +47,13 @@ fal/toolkit/__init__.py,sha256=sV95wiUzKoiDqF9vDgq4q-BLa2sD6IpuKSqp5kdTQNE,658
|
|
|
47
47
|
fal/toolkit/exceptions.py,sha256=elHZ7dHCJG5zlHGSBbz-ilkZe9QUvQMomJFi8Pt91LA,198
|
|
48
48
|
fal/toolkit/optimize.py,sha256=p75sovF0SmRP6zxzpIaaOmqlxvXB_xEz3XPNf59EF7w,1339
|
|
49
49
|
fal/toolkit/file/__init__.py,sha256=FbNl6wD-P0aSSTUwzHt4HujBXrbC3ABmaigPQA4hRfg,70
|
|
50
|
-
fal/toolkit/file/file.py,sha256=
|
|
51
|
-
fal/toolkit/file/types.py,sha256=
|
|
52
|
-
fal/toolkit/file/providers/fal.py,sha256=
|
|
50
|
+
fal/toolkit/file/file.py,sha256=GuY4zTqYMod2e9pLorZdPJqmGQ2CmmxaYxmtBm4J7vQ,8913
|
|
51
|
+
fal/toolkit/file/types.py,sha256=MjZ6xAhKPv4rowLo2Vcbho0sX7AQ3lm3KFyYDcw0dL4,1845
|
|
52
|
+
fal/toolkit/file/providers/fal.py,sha256=W3XKbAsRuCKPDHwVK1IBen_Tdp23Pi8qhgfiVbsPc4s,14777
|
|
53
53
|
fal/toolkit/file/providers/gcp.py,sha256=cxG1j3yuOpFl_Dl_nCEibFE4677qkdXZhuKgb65PnjQ,2126
|
|
54
54
|
fal/toolkit/file/providers/r2.py,sha256=Y3DjhpmrbESUTDUtVcKtg0NMKamMTevf6cJA7OgvalI,2750
|
|
55
55
|
fal/toolkit/image/__init__.py,sha256=aLcU8HzD7HyOxx-C-Bbx9kYCMHdBhy9tR98FSVJ6gSA,1830
|
|
56
|
-
fal/toolkit/image/image.py,sha256=
|
|
56
|
+
fal/toolkit/image/image.py,sha256=ZSkozciP4XxaGnvrR_mP4utqE3_QhoPN0dau9FJ2Xco,5033
|
|
57
57
|
fal/toolkit/image/safety_checker.py,sha256=S7ow-HuoVxC6ixHWWcBrAUm2dIlgq3sTAIull6xIbAg,3105
|
|
58
58
|
fal/toolkit/image/nsfw_filter/__init__.py,sha256=0d9D51EhcnJg8cZLYJjgvQJDZT74CfQu6mpvinRYRpA,216
|
|
59
59
|
fal/toolkit/image/nsfw_filter/env.py,sha256=iAP2Q3vzIl--DD8nr8o3o0goAwhExN2v0feYE0nIQjs,212
|
|
@@ -126,8 +126,8 @@ openapi_fal_rest/models/workflow_node_type.py,sha256=-FzyeY2bxcNmizKbJI8joG7byRi
|
|
|
126
126
|
openapi_fal_rest/models/workflow_schema.py,sha256=4K5gsv9u9pxx2ItkffoyHeNjBBYf6ur5bN4m_zePZNY,2019
|
|
127
127
|
openapi_fal_rest/models/workflow_schema_input.py,sha256=2OkOXWHTNsCXHWS6EGDFzcJKkW5FIap-2gfO233EvZQ,1191
|
|
128
128
|
openapi_fal_rest/models/workflow_schema_output.py,sha256=EblwSPAGfWfYVWw_WSSaBzQVju296is9o28rMBAd0mc,1196
|
|
129
|
-
fal-1.5.
|
|
130
|
-
fal-1.5.
|
|
131
|
-
fal-1.5.
|
|
132
|
-
fal-1.5.
|
|
133
|
-
fal-1.5.
|
|
129
|
+
fal-1.5.2.dist-info/METADATA,sha256=hOKSZaGlMc6uIwV8Te50B9vaqRBxE2YjCeALzTpveRo,3787
|
|
130
|
+
fal-1.5.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
131
|
+
fal-1.5.2.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
|
|
132
|
+
fal-1.5.2.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
|
|
133
|
+
fal-1.5.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|