spaces 0.49b9__tar.gz → 0.50.dev0__tar.gz
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.
- spaces-0.50.dev0/PKG-INFO +24 -0
- spaces-0.50.dev0/pyproject.toml +127 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/__init__.py +12 -38
- spaces-0.50.dev0/spaces/_vendor/asgiref/typing.py +279 -0
- spaces-0.50.dev0/spaces/_vendor/sse_starlette/py.typed +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/config.py +0 -2
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/reloading/__init__.py +6 -2
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/reloading/server.py +20 -9
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/reloading/types.py +6 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/reloading/types.ts +6 -1
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/utils.py +5 -12
- spaces-0.50.dev0/spaces/zero/__init__.py +28 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/client.py +90 -96
- spaces-0.50.dev0/spaces/zero/context.py +114 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/decorator.py +2 -3
- spaces-0.50.dev0/spaces/zero/gradio.py +131 -0
- spaces-0.50.dev0/spaces/zero/lifecycle.py +30 -0
- spaces-0.50.dev0/spaces/zero/middleware.py +107 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/aoti.py +7 -141
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/patching.py +5 -4
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/static.py +1 -1
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/types.py +18 -10
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/utils.py +39 -1
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/wrappers.py +81 -94
- spaces-0.49b9/PKG-INFO +0 -32
- spaces-0.49b9/pyproject.toml +0 -101
- spaces-0.49b9/spaces/gradio.py +0 -53
- spaces-0.49b9/spaces/zero/__init__.py +0 -28
- spaces-0.49b9/spaces/zero/elf.py +0 -37
- spaces-0.49b9/spaces/zero/gradio.py +0 -189
- spaces-0.49b9/spaces/zero/torch/kernels.py +0 -65
- {spaces-0.49b9 → spaces-0.50.dev0}/README.md +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/__init__.py +0 -0
- /spaces-0.49b9/spaces/_vendor/ovld/py.typed → /spaces-0.50.dev0/spaces/_vendor/asgiref/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/codefind/LICENSE +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/codefind/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/codefind/registry.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/codefind/version.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/LICENSE +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/codetools.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/parse.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/register.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/utils.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/jurigged/version.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/LICENSE +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/abc.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/codegen.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/core.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/dependent.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/medley.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/mro.py +0 -0
- {spaces-0.49b9/spaces/_vendor/sse_starlette → spaces-0.50.dev0/spaces/_vendor/ovld}/py.typed +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/recode.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/signatures.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/typemap.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/types.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/utils.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/ovld/version.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/sse_starlette/LICENSE +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/sse_starlette/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/sse_starlette/event.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/sse_starlette/sse.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/sseclient/LICENSE +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/_vendor/sseclient/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/reloading/client.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/api.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/mmap.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/__init__.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/bitsandbytes.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/bitsandbytes_legacy.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/cudart.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/packing.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/patching_legacy.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/types.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/torch/utils.py +0 -0
- {spaces-0.49b9 → spaces-0.50.dev0}/spaces/zero/tqdm.py +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spaces
|
|
3
|
+
Version: 0.50.dev0
|
|
4
|
+
Summary: Utilities for Hugging Face Spaces
|
|
5
|
+
Author: Charles Bensimon
|
|
6
|
+
Author-email: Charles Bensimon <charles@huggingface.co>
|
|
7
|
+
License-Expression: Apache-2.0
|
|
8
|
+
Requires-Dist: packaging
|
|
9
|
+
Requires-Dist: typing-extensions>=4,<5
|
|
10
|
+
Requires-Dist: pydantic>=1,<3
|
|
11
|
+
Requires-Dist: httpx>=0.20
|
|
12
|
+
Requires-Dist: fastapi ; extra == 'serving'
|
|
13
|
+
Requires-Dist: uvicorn ; extra == 'serving'
|
|
14
|
+
Requires-Python: >=3.10, <3.15
|
|
15
|
+
Project-URL: Homepage, https://huggingface.co
|
|
16
|
+
Project-URL: Repository, https://github.com/huggingface/huggingface_hub
|
|
17
|
+
Provides-Extra: serving
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# Hugging Face Spaces
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
`pip install spaces`
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "spaces"
|
|
3
|
+
version = "0.50.dev0"
|
|
4
|
+
description = "Utilities for Hugging Face Spaces"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10,<3.15"
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Charles Bensimon", email = "charles@huggingface.co" },
|
|
10
|
+
]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"packaging",
|
|
13
|
+
"typing-extensions>=4,<5",
|
|
14
|
+
"pydantic>=1,<3",
|
|
15
|
+
"httpx>=0.20",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.optional-dependencies]
|
|
19
|
+
serving = [
|
|
20
|
+
"fastapi",
|
|
21
|
+
"uvicorn"
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://huggingface.co"
|
|
26
|
+
Repository = "https://github.com/huggingface/huggingface_hub"
|
|
27
|
+
|
|
28
|
+
[dependency-groups]
|
|
29
|
+
dev = [
|
|
30
|
+
"pytest>=7.3.1,<8",
|
|
31
|
+
"pytest-dotenv>=0.5.2,<0.6",
|
|
32
|
+
"pytest-mock>=3.10.0,<4",
|
|
33
|
+
"pytest-timeout>=2.1.0,<3",
|
|
34
|
+
"poethepoet>=0.20.0,<0.21",
|
|
35
|
+
"coverage>=7.2.6,<8",
|
|
36
|
+
"pyright>=1.1.403,<2",
|
|
37
|
+
"pytest-order>=1.1.0,<2",
|
|
38
|
+
"pynvml>=11.5.0,<12",
|
|
39
|
+
"pytest-asyncio>=0.21.1,<0.22",
|
|
40
|
+
"pytest-httpx>=0.27.0,<0.28",
|
|
41
|
+
"pydantic-to-typescript>=2.0.0,<3",
|
|
42
|
+
"requests>=2.19,<3",
|
|
43
|
+
"setuptools",
|
|
44
|
+
]
|
|
45
|
+
test = [
|
|
46
|
+
"gradio",
|
|
47
|
+
"diffusers",
|
|
48
|
+
"transformers",
|
|
49
|
+
"accelerate",
|
|
50
|
+
"bitsandbytes",
|
|
51
|
+
"torch==2.9.1",
|
|
52
|
+
"torchao>=0.10.0,<0.11",
|
|
53
|
+
"scipy",
|
|
54
|
+
"peft",
|
|
55
|
+
"kernels>=0.10.2,<0.11",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.uv]
|
|
59
|
+
constraint-dependencies = [
|
|
60
|
+
"numpy<2",
|
|
61
|
+
"peft<0.19",
|
|
62
|
+
"transformers<4.51",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
addopts = "-v"
|
|
67
|
+
testpaths = ["tests"]
|
|
68
|
+
env_files = ["tests/.env"]
|
|
69
|
+
|
|
70
|
+
[tool.coverage.run]
|
|
71
|
+
source = ["spaces"]
|
|
72
|
+
omit = [
|
|
73
|
+
"spaces/zero/api.py",
|
|
74
|
+
"spaces/zero/torch/patching_legacy.py",
|
|
75
|
+
"spaces/zero/torch/bitsandbytes_legacy.py",
|
|
76
|
+
"spaces/_vendor/*",
|
|
77
|
+
]
|
|
78
|
+
concurrency = ["thread", "multiprocessing"]
|
|
79
|
+
|
|
80
|
+
[tool.coverage.report]
|
|
81
|
+
fail_under = 100
|
|
82
|
+
exclude_also = [
|
|
83
|
+
"^\\s*if TYPE_CHECKING:\\s*$",
|
|
84
|
+
"^\\s*assert_never\\(.*\\)\\s*$",
|
|
85
|
+
"^\\s*debug\\(.*\\)\\s*$",
|
|
86
|
+
"^\\s*\\.\\.\\.\\s*$",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[tool.poe.tasks.test]
|
|
90
|
+
shell = """set -e
|
|
91
|
+
pyright
|
|
92
|
+
coverage erase
|
|
93
|
+
coverage run -m pytest tests/cpu
|
|
94
|
+
coverage run -m pytest tests/gpu
|
|
95
|
+
find e2e -name '*.py' | xargs -I {} coverage run {}
|
|
96
|
+
pytest tests/cpu/serving/test_middleware.py::test_fds_server_hang --fd-xfail
|
|
97
|
+
pytest tests/cpu/serving/test_middleware.py::test_fds_requests_hang --fd-xfail
|
|
98
|
+
coverage combine -q
|
|
99
|
+
coverage xml || true
|
|
100
|
+
coverage html || true
|
|
101
|
+
coverage report -m
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
[tool.poe.tasks.publish]
|
|
105
|
+
shell = """set -e
|
|
106
|
+
git diff --quiet
|
|
107
|
+
rm -rf dist
|
|
108
|
+
uv build
|
|
109
|
+
uv publish
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
[tool.pyright]
|
|
113
|
+
include = ["spaces", "tests"]
|
|
114
|
+
exclude = ["spaces/_vendor"]
|
|
115
|
+
pythonVersion = "3.10"
|
|
116
|
+
reportMatchNotExhaustive = "error"
|
|
117
|
+
reportPossiblyUnboundVariable = "error"
|
|
118
|
+
reportUnnecessaryComparison = true
|
|
119
|
+
reportPrivateImportUsage = "information"
|
|
120
|
+
|
|
121
|
+
[build-system]
|
|
122
|
+
requires = ["uv_build>=0.11.6,<0.12"]
|
|
123
|
+
build-backend = "uv_build"
|
|
124
|
+
|
|
125
|
+
[tool.uv.build-backend]
|
|
126
|
+
module-name = "spaces"
|
|
127
|
+
module-root = ""
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""
|
|
2
2
|
"""
|
|
3
|
+
|
|
3
4
|
import sys
|
|
5
|
+
import warnings
|
|
4
6
|
from types import FunctionType
|
|
5
7
|
from typing import TYPE_CHECKING
|
|
6
8
|
from typing import Callable
|
|
@@ -15,9 +17,16 @@ if (gr := sys.modules.get('gradio')) is not None: # pragma: no cover
|
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
from .zero.decorator import GPU
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def gradio_auto_wrap(*args, **kwargs): # pragma: no cover
|
|
23
|
+
warnings.warn("gradio_auto_wrap has no effect and is deprecated")
|
|
24
|
+
|
|
25
|
+
def disable_gradio_auto_wrap(*args, **kwargs): # pragma: no cover
|
|
26
|
+
warnings.warn("gradio_auto_wrap has no effect and is deprecated")
|
|
27
|
+
|
|
28
|
+
def enable_gradio_auto_wrap(*args, **kwargs): # pragma: no cover
|
|
29
|
+
warnings.warn("gradio_auto_wrap has no effect and is deprecated")
|
|
21
30
|
|
|
22
31
|
|
|
23
32
|
class LazyImported:
|
|
@@ -50,30 +59,10 @@ def _aoti_compile():
|
|
|
50
59
|
from .zero.torch.aoti import aoti_compile
|
|
51
60
|
return aoti_compile
|
|
52
61
|
|
|
53
|
-
def _aoti_compile_and_save():
|
|
54
|
-
from .zero.torch.aoti import aoti_compile_and_save
|
|
55
|
-
return aoti_compile_and_save
|
|
56
|
-
|
|
57
62
|
def _aoti_apply():
|
|
58
63
|
from .zero.torch.aoti import aoti_apply
|
|
59
64
|
return aoti_apply
|
|
60
65
|
|
|
61
|
-
def _aoti_patch():
|
|
62
|
-
from .zero.torch.aoti import aoti_patch
|
|
63
|
-
return aoti_patch
|
|
64
|
-
|
|
65
|
-
def _aoti_load():
|
|
66
|
-
from .zero.torch.aoti import aoti_load
|
|
67
|
-
return aoti_load
|
|
68
|
-
|
|
69
|
-
def _aoti_load_call_source():
|
|
70
|
-
from .zero.torch.aoti import aoti_load_call_source
|
|
71
|
-
return aoti_load_call_source
|
|
72
|
-
|
|
73
|
-
def _aoti_load_from_package_dir():
|
|
74
|
-
from .zero.torch.aoti import aoti_load_from_package_dir
|
|
75
|
-
return aoti_load_from_package_dir
|
|
76
|
-
|
|
77
66
|
def _aoti_blocks_load():
|
|
78
67
|
from .zero.torch.aoti import aoti_blocks_load
|
|
79
68
|
return aoti_blocks_load
|
|
@@ -81,24 +70,14 @@ def _aoti_blocks_load():
|
|
|
81
70
|
|
|
82
71
|
aoti_capture = LazyImported(_aoti_capture)
|
|
83
72
|
aoti_compile = LazyImported(_aoti_compile)
|
|
84
|
-
aoti_compile_and_save = LazyImported(_aoti_compile_and_save)
|
|
85
73
|
aoti_apply = LazyImported(_aoti_apply)
|
|
86
|
-
aoti_patch = LazyImported(_aoti_patch)
|
|
87
|
-
aoti_load = LazyImported(_aoti_load)
|
|
88
|
-
aoti_load_call_source = LazyImported(_aoti_load_call_source)
|
|
89
|
-
aoti_load_from_package_dir = LazyImported(_aoti_load_from_package_dir)
|
|
90
74
|
aoti_blocks_load = LazyImported(_aoti_blocks_load)
|
|
91
75
|
|
|
92
76
|
|
|
93
77
|
if TYPE_CHECKING:
|
|
94
78
|
from .zero.torch.aoti import aoti_capture
|
|
95
79
|
from .zero.torch.aoti import aoti_compile
|
|
96
|
-
from .zero.torch.aoti import aoti_compile_and_save
|
|
97
80
|
from .zero.torch.aoti import aoti_apply
|
|
98
|
-
from .zero.torch.aoti import aoti_patch
|
|
99
|
-
from .zero.torch.aoti import aoti_load
|
|
100
|
-
from .zero.torch.aoti import aoti_load_call_source
|
|
101
|
-
from .zero.torch.aoti import aoti_load_from_package_dir
|
|
102
81
|
from .zero.torch.aoti import aoti_blocks_load
|
|
103
82
|
|
|
104
83
|
|
|
@@ -109,11 +88,6 @@ __all__ = [
|
|
|
109
88
|
'enable_gradio_auto_wrap',
|
|
110
89
|
'aoti_capture',
|
|
111
90
|
'aoti_compile',
|
|
112
|
-
'aoti_compile_and_save',
|
|
113
91
|
'aoti_apply',
|
|
114
|
-
'aoti_patch',
|
|
115
|
-
'aoti_load',
|
|
116
|
-
'aoti_load_call_source',
|
|
117
|
-
'aoti_load_from_package_dir',
|
|
118
92
|
'aoti_blocks_load',
|
|
119
93
|
]
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
Awaitable,
|
|
5
|
+
Callable,
|
|
6
|
+
Dict,
|
|
7
|
+
Iterable,
|
|
8
|
+
Literal,
|
|
9
|
+
Optional,
|
|
10
|
+
Protocol,
|
|
11
|
+
Tuple,
|
|
12
|
+
Type,
|
|
13
|
+
TypedDict,
|
|
14
|
+
Union,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if sys.version_info >= (3, 11):
|
|
18
|
+
from typing import NotRequired
|
|
19
|
+
else:
|
|
20
|
+
from typing_extensions import NotRequired
|
|
21
|
+
|
|
22
|
+
__all__ = (
|
|
23
|
+
"ASGIVersions",
|
|
24
|
+
"HTTPScope",
|
|
25
|
+
"WebSocketScope",
|
|
26
|
+
"LifespanScope",
|
|
27
|
+
"WWWScope",
|
|
28
|
+
"Scope",
|
|
29
|
+
"HTTPRequestEvent",
|
|
30
|
+
"HTTPResponseStartEvent",
|
|
31
|
+
"HTTPResponseBodyEvent",
|
|
32
|
+
"HTTPResponseTrailersEvent",
|
|
33
|
+
"HTTPResponsePathsendEvent",
|
|
34
|
+
"HTTPServerPushEvent",
|
|
35
|
+
"HTTPDisconnectEvent",
|
|
36
|
+
"WebSocketConnectEvent",
|
|
37
|
+
"WebSocketAcceptEvent",
|
|
38
|
+
"WebSocketReceiveEvent",
|
|
39
|
+
"WebSocketSendEvent",
|
|
40
|
+
"WebSocketResponseStartEvent",
|
|
41
|
+
"WebSocketResponseBodyEvent",
|
|
42
|
+
"WebSocketDisconnectEvent",
|
|
43
|
+
"WebSocketCloseEvent",
|
|
44
|
+
"LifespanStartupEvent",
|
|
45
|
+
"LifespanShutdownEvent",
|
|
46
|
+
"LifespanStartupCompleteEvent",
|
|
47
|
+
"LifespanStartupFailedEvent",
|
|
48
|
+
"LifespanShutdownCompleteEvent",
|
|
49
|
+
"LifespanShutdownFailedEvent",
|
|
50
|
+
"ASGIReceiveEvent",
|
|
51
|
+
"ASGISendEvent",
|
|
52
|
+
"ASGIReceiveCallable",
|
|
53
|
+
"ASGISendCallable",
|
|
54
|
+
"ASGI2Protocol",
|
|
55
|
+
"ASGI2Application",
|
|
56
|
+
"ASGI3Application",
|
|
57
|
+
"ASGIApplication",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ASGIVersions(TypedDict):
|
|
62
|
+
spec_version: str
|
|
63
|
+
version: Union[Literal["2.0"], Literal["3.0"]]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class HTTPScope(TypedDict):
|
|
67
|
+
type: Literal["http"]
|
|
68
|
+
asgi: ASGIVersions
|
|
69
|
+
http_version: str
|
|
70
|
+
method: str
|
|
71
|
+
scheme: str
|
|
72
|
+
path: str
|
|
73
|
+
raw_path: bytes
|
|
74
|
+
query_string: bytes
|
|
75
|
+
root_path: str
|
|
76
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
77
|
+
client: Optional[Tuple[str, int]]
|
|
78
|
+
server: Optional[Tuple[str, Optional[int]]]
|
|
79
|
+
state: NotRequired[Dict[str, Any]]
|
|
80
|
+
extensions: Optional[Dict[str, Dict[object, object]]]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class WebSocketScope(TypedDict):
|
|
84
|
+
type: Literal["websocket"]
|
|
85
|
+
asgi: ASGIVersions
|
|
86
|
+
http_version: str
|
|
87
|
+
scheme: str
|
|
88
|
+
path: str
|
|
89
|
+
raw_path: bytes
|
|
90
|
+
query_string: bytes
|
|
91
|
+
root_path: str
|
|
92
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
93
|
+
client: Optional[Tuple[str, int]]
|
|
94
|
+
server: Optional[Tuple[str, Optional[int]]]
|
|
95
|
+
subprotocols: Iterable[str]
|
|
96
|
+
state: NotRequired[Dict[str, Any]]
|
|
97
|
+
extensions: Optional[Dict[str, Dict[object, object]]]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class LifespanScope(TypedDict):
|
|
101
|
+
type: Literal["lifespan"]
|
|
102
|
+
asgi: ASGIVersions
|
|
103
|
+
state: NotRequired[Dict[str, Any]]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
WWWScope = Union[HTTPScope, WebSocketScope]
|
|
107
|
+
Scope = Union[HTTPScope, WebSocketScope, LifespanScope]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class HTTPRequestEvent(TypedDict):
|
|
111
|
+
type: Literal["http.request"]
|
|
112
|
+
body: bytes
|
|
113
|
+
more_body: bool
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class HTTPResponseDebugEvent(TypedDict):
|
|
117
|
+
type: Literal["http.response.debug"]
|
|
118
|
+
info: Dict[str, object]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class HTTPResponseStartEvent(TypedDict):
|
|
122
|
+
type: Literal["http.response.start"]
|
|
123
|
+
status: int
|
|
124
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
125
|
+
trailers: bool
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class HTTPResponseBodyEvent(TypedDict):
|
|
129
|
+
type: Literal["http.response.body"]
|
|
130
|
+
body: bytes
|
|
131
|
+
more_body: bool
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class HTTPResponseTrailersEvent(TypedDict):
|
|
135
|
+
type: Literal["http.response.trailers"]
|
|
136
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
137
|
+
more_trailers: bool
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class HTTPResponsePathsendEvent(TypedDict):
|
|
141
|
+
type: Literal["http.response.pathsend"]
|
|
142
|
+
path: str
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class HTTPServerPushEvent(TypedDict):
|
|
146
|
+
type: Literal["http.response.push"]
|
|
147
|
+
path: str
|
|
148
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class HTTPDisconnectEvent(TypedDict):
|
|
152
|
+
type: Literal["http.disconnect"]
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class WebSocketConnectEvent(TypedDict):
|
|
156
|
+
type: Literal["websocket.connect"]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class WebSocketAcceptEvent(TypedDict):
|
|
160
|
+
type: Literal["websocket.accept"]
|
|
161
|
+
subprotocol: Optional[str]
|
|
162
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class WebSocketReceiveEvent(TypedDict):
|
|
166
|
+
type: Literal["websocket.receive"]
|
|
167
|
+
bytes: Optional[bytes]
|
|
168
|
+
text: Optional[str]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class WebSocketSendEvent(TypedDict):
|
|
172
|
+
type: Literal["websocket.send"]
|
|
173
|
+
bytes: Optional[bytes]
|
|
174
|
+
text: Optional[str]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class WebSocketResponseStartEvent(TypedDict):
|
|
178
|
+
type: Literal["websocket.http.response.start"]
|
|
179
|
+
status: int
|
|
180
|
+
headers: Iterable[Tuple[bytes, bytes]]
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class WebSocketResponseBodyEvent(TypedDict):
|
|
184
|
+
type: Literal["websocket.http.response.body"]
|
|
185
|
+
body: bytes
|
|
186
|
+
more_body: bool
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class WebSocketDisconnectEvent(TypedDict):
|
|
190
|
+
type: Literal["websocket.disconnect"]
|
|
191
|
+
code: int
|
|
192
|
+
reason: Optional[str]
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class WebSocketCloseEvent(TypedDict):
|
|
196
|
+
type: Literal["websocket.close"]
|
|
197
|
+
code: int
|
|
198
|
+
reason: Optional[str]
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class LifespanStartupEvent(TypedDict):
|
|
202
|
+
type: Literal["lifespan.startup"]
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class LifespanShutdownEvent(TypedDict):
|
|
206
|
+
type: Literal["lifespan.shutdown"]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class LifespanStartupCompleteEvent(TypedDict):
|
|
210
|
+
type: Literal["lifespan.startup.complete"]
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class LifespanStartupFailedEvent(TypedDict):
|
|
214
|
+
type: Literal["lifespan.startup.failed"]
|
|
215
|
+
message: str
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class LifespanShutdownCompleteEvent(TypedDict):
|
|
219
|
+
type: Literal["lifespan.shutdown.complete"]
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class LifespanShutdownFailedEvent(TypedDict):
|
|
223
|
+
type: Literal["lifespan.shutdown.failed"]
|
|
224
|
+
message: str
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
ASGIReceiveEvent = Union[
|
|
228
|
+
HTTPRequestEvent,
|
|
229
|
+
HTTPDisconnectEvent,
|
|
230
|
+
WebSocketConnectEvent,
|
|
231
|
+
WebSocketReceiveEvent,
|
|
232
|
+
WebSocketDisconnectEvent,
|
|
233
|
+
LifespanStartupEvent,
|
|
234
|
+
LifespanShutdownEvent,
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
ASGISendEvent = Union[
|
|
239
|
+
HTTPResponseStartEvent,
|
|
240
|
+
HTTPResponseBodyEvent,
|
|
241
|
+
HTTPResponseTrailersEvent,
|
|
242
|
+
HTTPServerPushEvent,
|
|
243
|
+
HTTPDisconnectEvent,
|
|
244
|
+
WebSocketAcceptEvent,
|
|
245
|
+
WebSocketSendEvent,
|
|
246
|
+
WebSocketResponseStartEvent,
|
|
247
|
+
WebSocketResponseBodyEvent,
|
|
248
|
+
WebSocketCloseEvent,
|
|
249
|
+
LifespanStartupCompleteEvent,
|
|
250
|
+
LifespanStartupFailedEvent,
|
|
251
|
+
LifespanShutdownCompleteEvent,
|
|
252
|
+
LifespanShutdownFailedEvent,
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
ASGIReceiveCallable = Callable[[], Awaitable[ASGIReceiveEvent]]
|
|
257
|
+
ASGISendCallable = Callable[[ASGISendEvent], Awaitable[None]]
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class ASGI2Protocol(Protocol):
|
|
261
|
+
def __init__(self, scope: Scope) -> None:
|
|
262
|
+
...
|
|
263
|
+
|
|
264
|
+
async def __call__(
|
|
265
|
+
self, receive: ASGIReceiveCallable, send: ASGISendCallable
|
|
266
|
+
) -> None:
|
|
267
|
+
...
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
ASGI2Application = Type[ASGI2Protocol]
|
|
271
|
+
ASGI3Application = Callable[
|
|
272
|
+
[
|
|
273
|
+
Scope,
|
|
274
|
+
ASGIReceiveCallable,
|
|
275
|
+
ASGISendCallable,
|
|
276
|
+
],
|
|
277
|
+
Awaitable[None],
|
|
278
|
+
]
|
|
279
|
+
ASGIApplication = Union[ASGI2Application, ASGI3Application]
|
|
File without changes
|
|
@@ -18,8 +18,6 @@ class Settings:
|
|
|
18
18
|
os.getenv('SPACES_ZERO_GPU'))
|
|
19
19
|
self.zero_device_api_url = (
|
|
20
20
|
os.getenv('SPACES_ZERO_DEVICE_API_URL'))
|
|
21
|
-
self.gradio_auto_wrap = boolean(
|
|
22
|
-
os.getenv('SPACES_GRADIO_AUTO_WRAP'))
|
|
23
21
|
self.zero_patch_torch_device = boolean(
|
|
24
22
|
os.getenv('ZERO_GPU_PATCH_TORCH_DEVICE'))
|
|
25
23
|
self.zero_gpu_v2 = boolean(
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
2
|
"""
|
|
3
|
+
|
|
3
4
|
import threading
|
|
4
5
|
from typing import Any
|
|
5
6
|
from typing import Callable
|
|
7
|
+
from uuid import uuid4
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
reload_server_ports: set[int] = set()
|
|
@@ -14,6 +16,7 @@ def start_reload_server(
|
|
|
14
16
|
stop_event: threading.Event,
|
|
15
17
|
port: int = 7887,
|
|
16
18
|
):
|
|
19
|
+
from ..zero.context import GlobalContext
|
|
17
20
|
from .server import ReloadServer
|
|
18
21
|
|
|
19
22
|
reload_server = ReloadServer(
|
|
@@ -22,8 +25,9 @@ def start_reload_server(
|
|
|
22
25
|
stop_event=stop_event,
|
|
23
26
|
)
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
server_port_uuid = uuid4()
|
|
29
|
+
GlobalContext.server_ports[server_port_uuid] = port
|
|
26
30
|
try:
|
|
27
31
|
reload_server.run(port=port)
|
|
28
32
|
finally:
|
|
29
|
-
|
|
33
|
+
del GlobalContext.server_ports[server_port_uuid]
|
|
@@ -12,6 +12,11 @@ from typing_extensions import assert_type
|
|
|
12
12
|
from typing_extensions import Never
|
|
13
13
|
from uuid import uuid4
|
|
14
14
|
|
|
15
|
+
try:
|
|
16
|
+
import fastapi, uvicorn
|
|
17
|
+
except ModuleNotFoundError: # pragma: no cover
|
|
18
|
+
raise RuntimeError("spaces.reloading.server requires FastAPI and uvicorn")
|
|
19
|
+
|
|
15
20
|
from fastapi import APIRouter
|
|
16
21
|
from fastapi import FastAPI
|
|
17
22
|
from fastapi import HTTPException
|
|
@@ -55,6 +60,7 @@ from .types import ApiFetchContentsResponseSuccess
|
|
|
55
60
|
from .types import ReloadRegion
|
|
56
61
|
from .types import ReloadOperationError
|
|
57
62
|
from .types import ReloadOperationException
|
|
63
|
+
from .types import ReloadOperationFile
|
|
58
64
|
from .types import ReloadOperationObject
|
|
59
65
|
from .types import ReloadOperationRun
|
|
60
66
|
from .types import ReloadOperationUI
|
|
@@ -62,7 +68,6 @@ from .types import ReloadOperationUI
|
|
|
62
68
|
|
|
63
69
|
class ReloadRun(NamedTuple):
|
|
64
70
|
activity: EventSource
|
|
65
|
-
thread: threading.Thread
|
|
66
71
|
|
|
67
72
|
|
|
68
73
|
class ReloadServer:
|
|
@@ -115,16 +120,22 @@ class ReloadServer:
|
|
|
115
120
|
return ApiCreateReloadResponseError(status='alreadyReloading')
|
|
116
121
|
|
|
117
122
|
filepath = (Path.cwd() / req.filepath).resolve()
|
|
118
|
-
if not filepath.is_relative_to(Path.cwd())
|
|
123
|
+
if not filepath.is_relative_to(Path.cwd()):
|
|
119
124
|
return ApiCreateReloadResponseError(status='fileNotFound')
|
|
120
125
|
|
|
121
|
-
|
|
126
|
+
created = not filepath.exists()
|
|
127
|
+
filepath.write_text(req.contents)
|
|
122
128
|
activity = EventSource(save_history=True) # TODO: Generic EventSource[ApiGetReloadEventSourceMessage]
|
|
123
|
-
|
|
129
|
+
reload_id = str(uuid4()) if req.reloadId is None else req.reloadId
|
|
130
|
+
self.reload_runs[reload_id] = ReloadRun(activity)
|
|
124
131
|
|
|
132
|
+
if (code_file := self.registry.get(str(filepath))) is None:
|
|
133
|
+
activity.emit(ApiGetReloadEventSourceData(data=ReloadOperationFile(kind='file', created=created)))
|
|
134
|
+
activity.emit(None)
|
|
135
|
+
return ApiCreateReloadResponseSuccess(status='created', reloadId=reload_id)
|
|
136
|
+
|
|
137
|
+
code_file.activity = activity
|
|
125
138
|
thread = create_thread(self.run_reload, code_file)
|
|
126
|
-
reload_id = str(uuid4()) if req.reloadId is None else req.reloadId
|
|
127
|
-
self.reload_runs[reload_id] = ReloadRun(activity, thread)
|
|
128
139
|
self.active_reload_id = reload_id
|
|
129
140
|
thread.start()
|
|
130
141
|
|
|
@@ -149,7 +160,7 @@ class ReloadServer:
|
|
|
149
160
|
|
|
150
161
|
reload_id = req.reloadId
|
|
151
162
|
if (run := self.reload_runs.get(reload_id, None)) is None:
|
|
152
|
-
raise HTTPException(
|
|
163
|
+
raise HTTPException(204, f"{reload_id=} not found")
|
|
153
164
|
|
|
154
165
|
queue = Queue()
|
|
155
166
|
run.activity.register(queue.put, apply_history=True)
|
|
@@ -166,7 +177,7 @@ class ReloadServer:
|
|
|
166
177
|
for data in activity_stream(queue):
|
|
167
178
|
yield data.model_dump_json()
|
|
168
179
|
|
|
169
|
-
return EventSourceResponse(event_source_stream())
|
|
180
|
+
return EventSourceResponse(event_source_stream(), ping=5)
|
|
170
181
|
|
|
171
182
|
|
|
172
183
|
def run_reload(self, code_file: CodeFile):
|
|
@@ -211,7 +222,7 @@ def serialize_code_operation(cf_operation: CodeFileOperation):
|
|
|
211
222
|
if isinstance(cf_operation, AddOperation):
|
|
212
223
|
kind = 'add'
|
|
213
224
|
elif isinstance(cf_operation, UpdateOperation):
|
|
214
|
-
if not isinstance(defn, FunctionDefinition):
|
|
225
|
+
if not isinstance(defn, (ClassDefinition, FunctionDefinition)):
|
|
215
226
|
return None
|
|
216
227
|
kind = 'update'
|
|
217
228
|
else:
|
|
@@ -43,6 +43,11 @@ class ReloadOperationUI(BaseModel):
|
|
|
43
43
|
updated: bool
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
class ReloadOperationFile(BaseModel):
|
|
47
|
+
kind: Literal['file']
|
|
48
|
+
created: bool
|
|
49
|
+
|
|
50
|
+
|
|
46
51
|
class ApiCreateReloadRequest(BaseModel):
|
|
47
52
|
filepath: str
|
|
48
53
|
contents: str
|
|
@@ -72,6 +77,7 @@ class ApiGetReloadEventSourceData(BaseModel):
|
|
|
72
77
|
| ReloadOperationObject \
|
|
73
78
|
| ReloadOperationRun \
|
|
74
79
|
| ReloadOperationUI \
|
|
80
|
+
| ReloadOperationFile \
|
|
75
81
|
|
|
76
82
|
|
|
77
83
|
class ApiGetStatusRequest(BaseModel):
|
|
@@ -39,7 +39,8 @@ export interface ApiGetReloadEventSourceData {
|
|
|
39
39
|
| ReloadOperationException
|
|
40
40
|
| ReloadOperationObject
|
|
41
41
|
| ReloadOperationRun
|
|
42
|
-
| ReloadOperationUI
|
|
42
|
+
| ReloadOperationUI
|
|
43
|
+
| ReloadOperationFile;
|
|
43
44
|
}
|
|
44
45
|
export interface ReloadOperationError {
|
|
45
46
|
kind: "error";
|
|
@@ -73,6 +74,10 @@ export interface ReloadOperationUI {
|
|
|
73
74
|
kind: "ui";
|
|
74
75
|
updated: boolean;
|
|
75
76
|
}
|
|
77
|
+
export interface ReloadOperationFile {
|
|
78
|
+
kind: "file";
|
|
79
|
+
created: boolean;
|
|
80
|
+
}
|
|
76
81
|
export interface ApiGetReloadRequest {
|
|
77
82
|
reloadId: string;
|
|
78
83
|
}
|