streamlit-nightly 1.37.2.dev20240810__py2.py3-none-any.whl → 1.37.2.dev20240812__py2.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.
- streamlit/dataframe_util.py +61 -2
- streamlit/delta_generator.py +3 -158
- streamlit/elements/arrow.py +146 -2
- streamlit/elements/deck_gl_json_chart.py +2 -2
- streamlit/elements/image.py +12 -7
- streamlit/elements/lib/built_in_chart_utils.py +12 -5
- streamlit/elements/lib/column_config_utils.py +8 -0
- streamlit/elements/lib/dialog.py +6 -3
- streamlit/elements/lib/mutable_status_container.py +3 -2
- streamlit/elements/media.py +11 -9
- streamlit/elements/metric.py +2 -2
- streamlit/runtime/caching/hashing.py +16 -5
- streamlit/runtime/scriptrunner/__init__.py +2 -0
- streamlit/runtime/scriptrunner/exec_code.py +1 -1
- streamlit/runtime/scriptrunner/script_run_context.py +18 -6
- streamlit/source_util.py +2 -7
- streamlit/static/asset-manifest.json +2 -2
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{main.80efcd23.js → main.d1c1e1f9.js} +2 -2
- streamlit/type_util.py +5 -0
- {streamlit_nightly-1.37.2.dev20240810.dist-info → streamlit_nightly-1.37.2.dev20240812.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.37.2.dev20240810.dist-info → streamlit_nightly-1.37.2.dev20240812.dist-info}/RECORD +27 -27
- /streamlit/static/static/js/{main.80efcd23.js.LICENSE.txt → main.d1c1e1f9.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.37.2.dev20240810.data → streamlit_nightly-1.37.2.dev20240812.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.37.2.dev20240810.dist-info → streamlit_nightly-1.37.2.dev20240812.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.37.2.dev20240810.dist-info → streamlit_nightly-1.37.2.dev20240812.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.37.2.dev20240810.dist-info → streamlit_nightly-1.37.2.dev20240812.dist-info}/top_level.txt +0 -0
streamlit/elements/lib/dialog.py
CHANGED
@@ -19,11 +19,14 @@ from typing import TYPE_CHECKING, Literal, cast
|
|
19
19
|
|
20
20
|
from typing_extensions import Self, TypeAlias
|
21
21
|
|
22
|
-
from streamlit.delta_generator import DeltaGenerator
|
22
|
+
from streamlit.delta_generator import DeltaGenerator
|
23
23
|
from streamlit.errors import StreamlitAPIException
|
24
24
|
from streamlit.proto.Block_pb2 import Block as BlockProto
|
25
25
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
26
|
-
from streamlit.runtime.scriptrunner import
|
26
|
+
from streamlit.runtime.scriptrunner.script_run_context import (
|
27
|
+
enqueue_message,
|
28
|
+
get_script_run_ctx,
|
29
|
+
)
|
27
30
|
|
28
31
|
if TYPE_CHECKING:
|
29
32
|
from types import TracebackType
|
@@ -127,7 +130,7 @@ class Dialog(DeltaGenerator):
|
|
127
130
|
# We add a sleep here to give the web app time to react to the update. Otherwise,
|
128
131
|
# we might run into issues where the dialog cannot be opened again after closing
|
129
132
|
time.sleep(0.05)
|
130
|
-
|
133
|
+
enqueue_message(msg)
|
131
134
|
|
132
135
|
def open(self) -> None:
|
133
136
|
self._update(True)
|
@@ -19,10 +19,11 @@ from typing import TYPE_CHECKING, Literal, cast
|
|
19
19
|
|
20
20
|
from typing_extensions import Self, TypeAlias
|
21
21
|
|
22
|
-
from streamlit.delta_generator import DeltaGenerator
|
22
|
+
from streamlit.delta_generator import DeltaGenerator
|
23
23
|
from streamlit.errors import StreamlitAPIException
|
24
24
|
from streamlit.proto.Block_pb2 import Block as BlockProto
|
25
25
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
26
|
+
from streamlit.runtime.scriptrunner.script_run_context import enqueue_message
|
26
27
|
|
27
28
|
if TYPE_CHECKING:
|
28
29
|
from types import TracebackType
|
@@ -150,7 +151,7 @@ class StatusContainer(DeltaGenerator):
|
|
150
151
|
self._current_state = state
|
151
152
|
|
152
153
|
self._current_proto = msg.delta.add_block
|
153
|
-
|
154
|
+
enqueue_message(msg)
|
154
155
|
|
155
156
|
def __enter__(self) -> Self: # type: ignore[override]
|
156
157
|
# This is a little dubious: we're returning a different type than
|
streamlit/elements/media.py
CHANGED
@@ -33,6 +33,7 @@ from streamlit.runtime.metrics_util import gather_metrics
|
|
33
33
|
from streamlit.runtime.scriptrunner import get_script_run_ctx
|
34
34
|
from streamlit.runtime.state.common import compute_widget_id
|
35
35
|
from streamlit.time_util import time_to_seconds
|
36
|
+
from streamlit.type_util import NumpyShape
|
36
37
|
|
37
38
|
if TYPE_CHECKING:
|
38
39
|
from typing import Any
|
@@ -41,6 +42,7 @@ if TYPE_CHECKING:
|
|
41
42
|
|
42
43
|
from streamlit.delta_generator import DeltaGenerator
|
43
44
|
|
45
|
+
|
44
46
|
MediaData: TypeAlias = Union[
|
45
47
|
str, bytes, io.BytesIO, io.RawIOBase, io.BufferedReader, "npt.NDArray[Any]", None
|
46
48
|
]
|
@@ -633,29 +635,29 @@ def _validate_and_normalize(data: npt.NDArray[Any]) -> tuple[bytes, int]:
|
|
633
635
|
# to st.audio data)
|
634
636
|
import numpy as np
|
635
637
|
|
636
|
-
|
638
|
+
transformed_data: npt.NDArray[Any] = np.array(data, dtype=float)
|
637
639
|
|
638
|
-
if len(
|
640
|
+
if len(cast(NumpyShape, transformed_data.shape)) == 1:
|
639
641
|
nchan = 1
|
640
|
-
elif len(
|
642
|
+
elif len(transformed_data.shape) == 2:
|
641
643
|
# In wave files,channels are interleaved. E.g.,
|
642
644
|
# "L1R1L2R2..." for stereo. See
|
643
645
|
# http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
|
644
646
|
# for channel ordering
|
645
|
-
nchan =
|
646
|
-
|
647
|
+
nchan = transformed_data.shape[0]
|
648
|
+
transformed_data = transformed_data.T.ravel()
|
647
649
|
else:
|
648
650
|
raise StreamlitAPIException("Numpy array audio input must be a 1D or 2D array.")
|
649
651
|
|
650
|
-
if
|
651
|
-
return
|
652
|
+
if transformed_data.size == 0:
|
653
|
+
return transformed_data.astype(np.int16).tobytes(), nchan
|
652
654
|
|
653
|
-
max_abs_value = np.max(np.abs(
|
655
|
+
max_abs_value = np.max(np.abs(transformed_data))
|
654
656
|
# 16-bit samples are stored as 2's-complement signed integers,
|
655
657
|
# ranging from -32768 to 32767.
|
656
658
|
# scaled_data is PCM 16 bit numpy array, that's why we multiply [-1, 1] float
|
657
659
|
# values to 32_767 == 2 ** 15 - 1.
|
658
|
-
np_array = (
|
660
|
+
np_array = (transformed_data / max_abs_value) * 32767
|
659
661
|
scaled_data = np_array.astype(np.int16)
|
660
662
|
return scaled_data.tobytes(), nchan
|
661
663
|
|
streamlit/elements/metric.py
CHANGED
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
16
16
|
|
17
17
|
from dataclasses import dataclass
|
18
18
|
from textwrap import dedent
|
19
|
-
from typing import TYPE_CHECKING, Literal, Union, cast
|
19
|
+
from typing import TYPE_CHECKING, Any, Literal, Union, cast
|
20
20
|
|
21
21
|
from typing_extensions import TypeAlias
|
22
22
|
|
@@ -36,7 +36,7 @@ if TYPE_CHECKING:
|
|
36
36
|
from streamlit.delta_generator import DeltaGenerator
|
37
37
|
|
38
38
|
|
39
|
-
Value: TypeAlias = Union["np.integer", "np.floating", float, int, str, None]
|
39
|
+
Value: TypeAlias = Union["np.integer[Any]", "np.floating[Any]", float, int, str, None]
|
40
40
|
Delta: TypeAlias = Union[float, int, str, None]
|
41
41
|
DeltaColor: TypeAlias = Literal["normal", "inverse", "off"]
|
42
42
|
|
@@ -17,6 +17,7 @@
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
19
|
import collections
|
20
|
+
import collections.abc
|
20
21
|
import dataclasses
|
21
22
|
import datetime
|
22
23
|
import functools
|
@@ -31,7 +32,8 @@ import threading
|
|
31
32
|
import uuid
|
32
33
|
import weakref
|
33
34
|
from enum import Enum
|
34
|
-
from
|
35
|
+
from types import MappingProxyType
|
36
|
+
from typing import Any, Callable, Dict, Final, Pattern, Type, Union, cast
|
35
37
|
|
36
38
|
from typing_extensions import TypeAlias
|
37
39
|
|
@@ -405,15 +407,15 @@ class _CacheFuncHasher:
|
|
405
407
|
elif obj is False:
|
406
408
|
return b"0"
|
407
409
|
|
408
|
-
elif dataclasses.is_dataclass(obj):
|
410
|
+
elif not isinstance(obj, type) and dataclasses.is_dataclass(obj):
|
409
411
|
return self.to_bytes(dataclasses.asdict(obj))
|
410
|
-
|
411
412
|
elif isinstance(obj, Enum):
|
412
413
|
return str(obj).encode()
|
413
414
|
|
414
415
|
elif type_util.is_type(obj, "pandas.core.series.Series"):
|
415
416
|
import pandas as pd
|
416
417
|
|
418
|
+
obj = cast(pd.Series, obj)
|
417
419
|
self.update(h, obj.size)
|
418
420
|
self.update(h, obj.dtype.name)
|
419
421
|
|
@@ -431,6 +433,7 @@ class _CacheFuncHasher:
|
|
431
433
|
elif type_util.is_type(obj, "pandas.core.frame.DataFrame"):
|
432
434
|
import pandas as pd
|
433
435
|
|
436
|
+
obj = cast(pd.DataFrame, obj)
|
434
437
|
self.update(h, obj.shape)
|
435
438
|
|
436
439
|
if len(obj) >= _PANDAS_ROWS_LARGE:
|
@@ -449,6 +452,11 @@ class _CacheFuncHasher:
|
|
449
452
|
return b"%s" % pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
|
450
453
|
|
451
454
|
elif type_util.is_type(obj, "numpy.ndarray"):
|
455
|
+
import numpy as np
|
456
|
+
|
457
|
+
# write cast type as string to make it work with our Python 3.8 tests
|
458
|
+
# - can be removed once we sunset support for Python 3.8
|
459
|
+
obj = cast("np.ndarray[Any, Any]", obj)
|
452
460
|
self.update(h, obj.shape)
|
453
461
|
self.update(h, str(obj.dtype))
|
454
462
|
|
@@ -462,6 +470,9 @@ class _CacheFuncHasher:
|
|
462
470
|
return h.digest()
|
463
471
|
elif type_util.is_type(obj, "PIL.Image.Image"):
|
464
472
|
import numpy as np
|
473
|
+
from PIL.Image import Image
|
474
|
+
|
475
|
+
obj = cast(Image, obj)
|
465
476
|
|
466
477
|
# we don't just hash the results of obj.tobytes() because we want to use
|
467
478
|
# the sampling logic for numpy data
|
@@ -471,8 +482,8 @@ class _CacheFuncHasher:
|
|
471
482
|
elif inspect.isbuiltin(obj):
|
472
483
|
return bytes(obj.__name__.encode())
|
473
484
|
|
474
|
-
elif
|
475
|
-
obj,
|
485
|
+
elif isinstance(obj, MappingProxyType) or isinstance(
|
486
|
+
obj, collections.abc.ItemsView
|
476
487
|
):
|
477
488
|
return self.to_bytes(dict(obj))
|
478
489
|
|
@@ -17,6 +17,7 @@ from streamlit.runtime.scriptrunner.script_requests import RerunData
|
|
17
17
|
from streamlit.runtime.scriptrunner.script_run_context import (
|
18
18
|
ScriptRunContext,
|
19
19
|
add_script_run_ctx,
|
20
|
+
enqueue_message,
|
20
21
|
get_script_run_ctx,
|
21
22
|
)
|
22
23
|
from streamlit.runtime.scriptrunner.script_runner import ScriptRunner, ScriptRunnerEvent
|
@@ -26,6 +27,7 @@ __all__ = [
|
|
26
27
|
"ScriptRunContext",
|
27
28
|
"add_script_run_ctx",
|
28
29
|
"get_script_run_ctx",
|
30
|
+
"enqueue_message",
|
29
31
|
"RerunException",
|
30
32
|
"ScriptRunner",
|
31
33
|
"ScriptRunnerEvent",
|
@@ -22,8 +22,7 @@ from urllib import parse
|
|
22
22
|
|
23
23
|
from typing_extensions import TypeAlias
|
24
24
|
|
25
|
-
from streamlit import
|
26
|
-
from streamlit.errors import StreamlitAPIException
|
25
|
+
from streamlit.errors import NoSessionContext, StreamlitAPIException
|
27
26
|
from streamlit.logger import get_logger
|
28
27
|
|
29
28
|
if TYPE_CHECKING:
|
@@ -224,15 +223,28 @@ def get_script_run_ctx(suppress_warning: bool = False) -> ScriptRunContext | Non
|
|
224
223
|
"""
|
225
224
|
thread = threading.current_thread()
|
226
225
|
ctx: ScriptRunContext | None = getattr(thread, SCRIPT_RUN_CONTEXT_ATTR_NAME, None)
|
227
|
-
if ctx is None and
|
226
|
+
if ctx is None and not suppress_warning:
|
228
227
|
# Only warn about a missing ScriptRunContext if suppress_warning is False, and
|
229
228
|
# we were started via `streamlit run`. Otherwise, the user is likely running a
|
230
229
|
# script "bare", and doesn't need to be warned about streamlit
|
231
230
|
# bits that are irrelevant when not connected to a session.
|
232
|
-
_LOGGER.warning(
|
231
|
+
_LOGGER.warning(
|
232
|
+
"Thread '%s': missing ScriptRunContext! This warning can be ignored when "
|
233
|
+
"running in bare mode.",
|
234
|
+
thread.name,
|
235
|
+
)
|
233
236
|
|
234
237
|
return ctx
|
235
238
|
|
236
239
|
|
237
|
-
|
238
|
-
|
240
|
+
def enqueue_message(msg: ForwardMsg) -> None:
|
241
|
+
"""Enqueues a ForwardMsg proto to send to the app."""
|
242
|
+
ctx = get_script_run_ctx()
|
243
|
+
|
244
|
+
if ctx is None:
|
245
|
+
raise NoSessionContext()
|
246
|
+
|
247
|
+
if ctx.current_fragment_id and msg.WhichOneof("type") == "delta":
|
248
|
+
msg.delta.fragment_id = ctx.current_fragment_id
|
249
|
+
|
250
|
+
ctx.enqueue(msg)
|
streamlit/source_util.py
CHANGED
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
17
17
|
import re
|
18
18
|
import threading
|
19
19
|
from pathlib import Path
|
20
|
-
from typing import
|
20
|
+
from typing import Callable, Final, TypedDict
|
21
21
|
|
22
22
|
from blinker import Signal
|
23
23
|
from typing_extensions import NotRequired, TypeAlias
|
@@ -88,15 +88,10 @@ def page_icon_and_name(script_path: Path) -> tuple[str, str]:
|
|
88
88
|
URL-encode them. To solve this, we only swap the underscores for spaces
|
89
89
|
right before we render page names.
|
90
90
|
"""
|
91
|
-
extraction = re.search(PAGE_FILENAME_REGEX, script_path.name)
|
91
|
+
extraction: re.Match[str] | None = re.search(PAGE_FILENAME_REGEX, script_path.name)
|
92
92
|
if extraction is None:
|
93
93
|
return "", ""
|
94
94
|
|
95
|
-
# This cast to Any+type annotation weirdness is done because
|
96
|
-
# cast(re.Match[str], ...) explodes at runtime since Python interprets it
|
97
|
-
# as an attempt to index into re.Match instead of as a type annotation.
|
98
|
-
extraction: re.Match[str] = cast(Any, extraction)
|
99
|
-
|
100
95
|
icon_and_name = re.sub(
|
101
96
|
r"[_ ]+", "_", extraction.group(2)
|
102
97
|
).strip() or extraction.group(1)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"files": {
|
3
3
|
"main.css": "./static/css/main.554f96d9.css",
|
4
|
-
"main.js": "./static/js/main.
|
4
|
+
"main.js": "./static/js/main.d1c1e1f9.js",
|
5
5
|
"static/js/9336.3e046ad7.chunk.js": "./static/js/9336.3e046ad7.chunk.js",
|
6
6
|
"static/js/9330.2b4c99e0.chunk.js": "./static/js/9330.2b4c99e0.chunk.js",
|
7
7
|
"static/js/2736.7d516fcc.chunk.js": "./static/js/2736.7d516fcc.chunk.js",
|
@@ -153,6 +153,6 @@
|
|
153
153
|
},
|
154
154
|
"entrypoints": [
|
155
155
|
"static/css/main.554f96d9.css",
|
156
|
-
"static/js/main.
|
156
|
+
"static/js/main.d1c1e1f9.js"
|
157
157
|
]
|
158
158
|
}
|
streamlit/static/index.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><link rel="shortcut icon" href="./favicon.png"/><link rel="preload" href="./static/media/SourceSansPro-Regular.0d69e5ff5e92ac64a0c9.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-SemiBold.abed79cd0df1827e18cf.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-Bold.118dea98980e20a81ced.woff2" as="font" type="font/woff2" crossorigin><title>Streamlit</title><script>window.prerenderReady=!1</script><script defer="defer" src="./static/js/main.
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><link rel="shortcut icon" href="./favicon.png"/><link rel="preload" href="./static/media/SourceSansPro-Regular.0d69e5ff5e92ac64a0c9.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-SemiBold.abed79cd0df1827e18cf.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="./static/media/SourceSansPro-Bold.118dea98980e20a81ced.woff2" as="font" type="font/woff2" crossorigin><title>Streamlit</title><script>window.prerenderReady=!1</script><script defer="defer" src="./static/js/main.d1c1e1f9.js"></script><link href="./static/css/main.554f96d9.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|