streamlit-nightly 1.31.1.dev20240207__py2.py3-none-any.whl → 1.31.1.dev20240208__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/commands/execution_control.py +5 -4
- streamlit/elements/lib/streamlit_plotly_theme.py +179 -163
- streamlit/elements/plotly_chart.py +11 -18
- streamlit/elements/widgets/button.py +8 -7
- streamlit/elements/widgets/time_widgets.py +24 -8
- streamlit/emojis.py +14 -1
- streamlit/runtime/caching/cache_resource_api.py +5 -3
- streamlit/runtime/legacy_caching/caching.py +5 -2
- streamlit/runtime/scriptrunner/script_runner.py +194 -187
- streamlit/runtime/state/session_state.py +6 -2
- streamlit/string_util.py +30 -10
- streamlit/watcher/event_based_path_watcher.py +26 -21
- streamlit/watcher/path_watcher.py +43 -41
- {streamlit_nightly-1.31.1.dev20240207.dist-info → streamlit_nightly-1.31.1.dev20240208.dist-info}/METADATA +1 -3
- {streamlit_nightly-1.31.1.dev20240207.dist-info → streamlit_nightly-1.31.1.dev20240208.dist-info}/RECORD +19 -19
- {streamlit_nightly-1.31.1.dev20240207.data → streamlit_nightly-1.31.1.dev20240208.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.31.1.dev20240207.dist-info → streamlit_nightly-1.31.1.dev20240208.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.31.1.dev20240207.dist-info → streamlit_nightly-1.31.1.dev20240208.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.31.1.dev20240207.dist-info → streamlit_nightly-1.31.1.dev20240208.dist-info}/top_level.txt +0 -0
@@ -138,11 +138,12 @@ def switch_page(page: str) -> NoReturn: # type: ignore[misc]
|
|
138
138
|
# This should never be the case
|
139
139
|
raise NoSessionContext()
|
140
140
|
|
141
|
-
|
141
|
+
normalized_ctx_main_script_path = os.path.normpath(ctx.main_script_path)
|
142
|
+
main_script_path = os.path.join(os.getcwd(), normalized_ctx_main_script_path)
|
142
143
|
main_script_directory = os.path.dirname(main_script_path)
|
143
144
|
|
144
|
-
# Convenience for handling ./ notation
|
145
|
-
page = os.path.normpath(page
|
145
|
+
# Convenience for handling ./ notation
|
146
|
+
page = os.path.normpath(page)
|
146
147
|
|
147
148
|
# Build full path
|
148
149
|
requested_page = os.path.join(main_script_directory, page)
|
@@ -152,7 +153,7 @@ def switch_page(page: str) -> NoReturn: # type: ignore[misc]
|
|
152
153
|
|
153
154
|
if len(matched_pages) == 0:
|
154
155
|
raise StreamlitAPIException(
|
155
|
-
f"Could not find page: '{page}'. Must be the file path relative to the main script, from the directory: {os.path.basename(main_script_directory)}."
|
156
|
+
f"Could not find page: '{page}'. Must be the file path relative to the main script, from the directory: {os.path.basename(main_script_directory)}. Only the main app file and files in the `pages/` directory are supported."
|
156
157
|
)
|
157
158
|
|
158
159
|
ctx.script_requests.request_rerun(
|
@@ -12,178 +12,194 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
import
|
16
|
-
import plotly.io as pio
|
15
|
+
import contextlib
|
17
16
|
|
18
|
-
# This is the streamlit theme for plotly where we pass in a template.data
|
19
|
-
# and a template.layout.
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
def configure_streamlit_plotly_theme() -> None:
|
19
|
+
"""Configure the Streamlit chart theme for Plotly.
|
23
20
|
|
24
|
-
|
25
|
-
|
21
|
+
The theme is only configured if Plotly is installed.
|
22
|
+
"""
|
23
|
+
# We do nothing if Plotly is not installed. This is expected since Plotly is an optional dependency.
|
24
|
+
with contextlib.suppress(ImportError):
|
25
|
+
import plotly.graph_objects as go
|
26
|
+
import plotly.io as pio
|
26
27
|
|
27
|
-
#
|
28
|
-
#
|
28
|
+
# This is the streamlit theme for plotly where we pass in a template.data
|
29
|
+
# and a template.layout.
|
30
|
+
# Template.data is for changing specific graph properties in a general aspect
|
31
|
+
# such as Contour plots or Waterfall plots.
|
32
|
+
# Template.layout is for changing things such as the x axis and fonts and other
|
33
|
+
# general layout properties for general graphs.
|
34
|
+
# We pass in temporary colors to the frontend and the frontend will replace
|
35
|
+
# those colors because we want to change colors based on the background color.
|
36
|
+
# Start at #0000001 because developers may be likely to use #000000
|
37
|
+
CATEGORY_0 = "#000001"
|
38
|
+
CATEGORY_1 = "#000002"
|
39
|
+
CATEGORY_2 = "#000003"
|
40
|
+
CATEGORY_3 = "#000004"
|
41
|
+
CATEGORY_4 = "#000005"
|
42
|
+
CATEGORY_5 = "#000006"
|
43
|
+
CATEGORY_6 = "#000007"
|
44
|
+
CATEGORY_7 = "#000008"
|
45
|
+
CATEGORY_8 = "#000009"
|
46
|
+
CATEGORY_9 = "#000010"
|
29
47
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
CATEGORY_9 = "#000010"
|
48
|
+
SEQUENTIAL_0 = "#000011"
|
49
|
+
SEQUENTIAL_1 = "#000012"
|
50
|
+
SEQUENTIAL_2 = "#000013"
|
51
|
+
SEQUENTIAL_3 = "#000014"
|
52
|
+
SEQUENTIAL_4 = "#000015"
|
53
|
+
SEQUENTIAL_5 = "#000016"
|
54
|
+
SEQUENTIAL_6 = "#000017"
|
55
|
+
SEQUENTIAL_7 = "#000018"
|
56
|
+
SEQUENTIAL_8 = "#000019"
|
57
|
+
SEQUENTIAL_9 = "#000020"
|
41
58
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
59
|
+
DIVERGING_0 = "#000021"
|
60
|
+
DIVERGING_1 = "#000022"
|
61
|
+
DIVERGING_2 = "#000023"
|
62
|
+
DIVERGING_3 = "#000024"
|
63
|
+
DIVERGING_4 = "#000025"
|
64
|
+
DIVERGING_5 = "#000026"
|
65
|
+
DIVERGING_6 = "#000027"
|
66
|
+
DIVERGING_7 = "#000028"
|
67
|
+
DIVERGING_8 = "#000029"
|
68
|
+
DIVERGING_9 = "#000030"
|
69
|
+
DIVERGING_10 = "#000031"
|
52
70
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
DIVERGING_3 = "#000024"
|
57
|
-
DIVERGING_4 = "#000025"
|
58
|
-
DIVERGING_5 = "#000026"
|
59
|
-
DIVERGING_6 = "#000027"
|
60
|
-
DIVERGING_7 = "#000028"
|
61
|
-
DIVERGING_8 = "#000029"
|
62
|
-
DIVERGING_9 = "#000030"
|
63
|
-
DIVERGING_10 = "#000031"
|
71
|
+
INCREASING = "#000032"
|
72
|
+
DECREASING = "#000033"
|
73
|
+
TOTAL = "#000034"
|
64
74
|
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
GRAY_70 = "#000036"
|
76
|
+
GRAY_90 = "#000037"
|
77
|
+
BG_COLOR = "#000038"
|
78
|
+
FADED_TEXT_05 = "#000039"
|
79
|
+
BG_MIX = "#000040"
|
68
80
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
FADED_TEXT_05 = "#000039"
|
74
|
-
BG_MIX = "#000040"
|
81
|
+
# Plotly represents continuous colorscale through an array of pairs.
|
82
|
+
# The pair's first index is the starting point and the next pair's first index is the end point.
|
83
|
+
# The pair's second index is the starting color and the next pair's second index is the end color.
|
84
|
+
# For more information, please refer to https://plotly.com/python/colorscales/
|
75
85
|
|
86
|
+
streamlit_colorscale = [
|
87
|
+
[0.0, SEQUENTIAL_0],
|
88
|
+
[0.1111111111111111, SEQUENTIAL_1],
|
89
|
+
[0.2222222222222222, SEQUENTIAL_2],
|
90
|
+
[0.3333333333333333, SEQUENTIAL_3],
|
91
|
+
[0.4444444444444444, SEQUENTIAL_4],
|
92
|
+
[0.5555555555555556, SEQUENTIAL_5],
|
93
|
+
[0.6666666666666666, SEQUENTIAL_6],
|
94
|
+
[0.7777777777777778, SEQUENTIAL_7],
|
95
|
+
[0.8888888888888888, SEQUENTIAL_8],
|
96
|
+
[1.0, SEQUENTIAL_9],
|
97
|
+
]
|
76
98
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
99
|
+
pio.templates["streamlit"] = go.layout.Template(
|
100
|
+
data=go.layout.template.Data(
|
101
|
+
candlestick=[
|
102
|
+
go.layout.template.data.Candlestick(
|
103
|
+
decreasing=go.candlestick.Decreasing(
|
104
|
+
line=go.candlestick.decreasing.Line(color=DECREASING)
|
105
|
+
),
|
106
|
+
increasing=go.candlestick.Increasing(
|
107
|
+
line=go.candlestick.increasing.Line(color=INCREASING)
|
108
|
+
),
|
109
|
+
)
|
110
|
+
],
|
111
|
+
contour=[
|
112
|
+
go.layout.template.data.Contour(colorscale=streamlit_colorscale)
|
113
|
+
],
|
114
|
+
contourcarpet=[
|
115
|
+
go.layout.template.data.Contourcarpet(
|
116
|
+
colorscale=streamlit_colorscale
|
117
|
+
)
|
118
|
+
],
|
119
|
+
heatmap=[
|
120
|
+
go.layout.template.data.Heatmap(colorscale=streamlit_colorscale)
|
121
|
+
],
|
122
|
+
histogram2d=[
|
123
|
+
go.layout.template.data.Histogram2d(colorscale=streamlit_colorscale)
|
124
|
+
],
|
125
|
+
icicle=[
|
126
|
+
go.layout.template.data.Icicle(
|
127
|
+
textfont=go.icicle.Textfont(color="white")
|
128
|
+
)
|
129
|
+
],
|
130
|
+
sankey=[
|
131
|
+
go.layout.template.data.Sankey(
|
132
|
+
textfont=go.sankey.Textfont(color=GRAY_70)
|
133
|
+
)
|
134
|
+
],
|
135
|
+
scatter=[
|
136
|
+
go.layout.template.data.Scatter(
|
137
|
+
marker=go.scatter.Marker(line=go.scatter.marker.Line(width=0))
|
138
|
+
)
|
139
|
+
],
|
140
|
+
table=[
|
141
|
+
go.layout.template.data.Table(
|
142
|
+
cells=go.table.Cells(
|
143
|
+
fill=go.table.cells.Fill(color=BG_COLOR),
|
144
|
+
font=go.table.cells.Font(color=GRAY_90),
|
145
|
+
line=go.table.cells.Line(color=FADED_TEXT_05),
|
146
|
+
),
|
147
|
+
header=go.table.Header(
|
148
|
+
font=go.table.header.Font(color=GRAY_70),
|
149
|
+
line=go.table.header.Line(color=FADED_TEXT_05),
|
150
|
+
fill=go.table.header.Fill(color=BG_MIX),
|
151
|
+
),
|
152
|
+
)
|
153
|
+
],
|
154
|
+
waterfall=[
|
155
|
+
go.layout.template.data.Waterfall(
|
156
|
+
increasing=go.waterfall.Increasing(
|
157
|
+
marker=go.waterfall.increasing.Marker(color=INCREASING)
|
158
|
+
),
|
159
|
+
decreasing=go.waterfall.Decreasing(
|
160
|
+
marker=go.waterfall.decreasing.Marker(color=DECREASING)
|
161
|
+
),
|
162
|
+
totals=go.waterfall.Totals(
|
163
|
+
marker=go.waterfall.totals.Marker(color=TOTAL)
|
164
|
+
),
|
165
|
+
connector=go.waterfall.Connector(
|
166
|
+
line=go.waterfall.connector.Line(color=GRAY_70, width=2)
|
167
|
+
),
|
168
|
+
)
|
169
|
+
],
|
170
|
+
),
|
171
|
+
layout=go.Layout(
|
172
|
+
colorway=[
|
173
|
+
CATEGORY_0,
|
174
|
+
CATEGORY_1,
|
175
|
+
CATEGORY_2,
|
176
|
+
CATEGORY_3,
|
177
|
+
CATEGORY_4,
|
178
|
+
CATEGORY_5,
|
179
|
+
CATEGORY_6,
|
180
|
+
CATEGORY_7,
|
181
|
+
CATEGORY_8,
|
182
|
+
CATEGORY_9,
|
183
|
+
],
|
184
|
+
colorscale=go.layout.Colorscale(
|
185
|
+
sequential=streamlit_colorscale,
|
186
|
+
sequentialminus=streamlit_colorscale,
|
187
|
+
diverging=[
|
188
|
+
[0.0, DIVERGING_0],
|
189
|
+
[0.1, DIVERGING_1],
|
190
|
+
[0.2, DIVERGING_2],
|
191
|
+
[0.3, DIVERGING_3],
|
192
|
+
[0.4, DIVERGING_4],
|
193
|
+
[0.5, DIVERGING_5],
|
194
|
+
[0.6, DIVERGING_6],
|
195
|
+
[0.7, DIVERGING_7],
|
196
|
+
[0.8, DIVERGING_8],
|
197
|
+
[0.9, DIVERGING_9],
|
198
|
+
[1.0, DIVERGING_10],
|
199
|
+
],
|
137
200
|
),
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
marker=go.waterfall.increasing.Marker(color=INCREASING)
|
144
|
-
),
|
145
|
-
decreasing=go.waterfall.Decreasing(
|
146
|
-
marker=go.waterfall.decreasing.Marker(color=DECREASING)
|
147
|
-
),
|
148
|
-
totals=go.waterfall.Totals(
|
149
|
-
marker=go.waterfall.totals.Marker(color=TOTAL)
|
150
|
-
),
|
151
|
-
connector=go.waterfall.Connector(
|
152
|
-
line=go.waterfall.connector.Line(color=GRAY_70, width=2)
|
153
|
-
),
|
154
|
-
)
|
155
|
-
],
|
156
|
-
),
|
157
|
-
layout=go.Layout(
|
158
|
-
colorway=[
|
159
|
-
CATEGORY_0,
|
160
|
-
CATEGORY_1,
|
161
|
-
CATEGORY_2,
|
162
|
-
CATEGORY_3,
|
163
|
-
CATEGORY_4,
|
164
|
-
CATEGORY_5,
|
165
|
-
CATEGORY_6,
|
166
|
-
CATEGORY_7,
|
167
|
-
CATEGORY_8,
|
168
|
-
CATEGORY_9,
|
169
|
-
],
|
170
|
-
colorscale=go.layout.Colorscale(
|
171
|
-
sequential=streamlit_colorscale,
|
172
|
-
sequentialminus=streamlit_colorscale,
|
173
|
-
diverging=[
|
174
|
-
[0.0, DIVERGING_0],
|
175
|
-
[0.1, DIVERGING_1],
|
176
|
-
[0.2, DIVERGING_2],
|
177
|
-
[0.3, DIVERGING_3],
|
178
|
-
[0.4, DIVERGING_4],
|
179
|
-
[0.5, DIVERGING_5],
|
180
|
-
[0.6, DIVERGING_6],
|
181
|
-
[0.7, DIVERGING_7],
|
182
|
-
[0.8, DIVERGING_8],
|
183
|
-
[0.9, DIVERGING_9],
|
184
|
-
[1.0, DIVERGING_10],
|
185
|
-
],
|
186
|
-
),
|
187
|
-
coloraxis=go.layout.Coloraxis(colorscale=streamlit_colorscale),
|
188
|
-
),
|
189
|
-
)
|
201
|
+
coloraxis=go.layout.Coloraxis(colorscale=streamlit_colorscale),
|
202
|
+
),
|
203
|
+
)
|
204
|
+
|
205
|
+
pio.templates.default = "streamlit"
|
@@ -14,15 +14,19 @@
|
|
14
14
|
|
15
15
|
"""Streamlit support for Plotly charts."""
|
16
16
|
|
17
|
+
from __future__ import annotations
|
18
|
+
|
17
19
|
import json
|
18
20
|
import urllib.parse
|
19
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Set, Union, cast
|
21
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Set, Union, cast
|
20
22
|
|
21
|
-
from typing_extensions import
|
23
|
+
from typing_extensions import TypeAlias
|
22
24
|
|
23
25
|
from streamlit import type_util
|
26
|
+
from streamlit.elements.lib.streamlit_plotly_theme import (
|
27
|
+
configure_streamlit_plotly_theme,
|
28
|
+
)
|
24
29
|
from streamlit.errors import StreamlitAPIException
|
25
|
-
from streamlit.logger import get_logger
|
26
30
|
from streamlit.proto.PlotlyChart_pb2 import PlotlyChart as PlotlyChartProto
|
27
31
|
from streamlit.runtime.legacy_caching import caching
|
28
32
|
from streamlit.runtime.metrics_util import gather_metrics
|
@@ -34,19 +38,8 @@ if TYPE_CHECKING:
|
|
34
38
|
|
35
39
|
from streamlit.delta_generator import DeltaGenerator
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
import plotly.io as pio
|
40
|
-
|
41
|
-
import streamlit.elements.lib.streamlit_plotly_theme
|
42
|
-
|
43
|
-
pio.templates.default = "streamlit"
|
44
|
-
except ModuleNotFoundError:
|
45
|
-
# We have imports here because it takes too loo long to load the template default for the first graph to load
|
46
|
-
# We do nothing if Plotly is not installed. This is expected since Plotly is an optional dependency.
|
47
|
-
pass
|
48
|
-
|
49
|
-
LOGGER: Final = get_logger(__name__)
|
41
|
+
# We need to configure the Plotly theme before any Plotly figures are created:
|
42
|
+
configure_streamlit_plotly_theme()
|
50
43
|
|
51
44
|
SharingMode: TypeAlias = Literal["streamlit", "private", "public", "secret"]
|
52
45
|
|
@@ -84,7 +77,7 @@ class PlotlyMixin:
|
|
84
77
|
figure_or_data: FigureOrData,
|
85
78
|
use_container_width: bool = False,
|
86
79
|
sharing: SharingMode = "streamlit",
|
87
|
-
theme:
|
80
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
88
81
|
**kwargs: Any,
|
89
82
|
) -> "DeltaGenerator":
|
90
83
|
"""Display an interactive Plotly chart.
|
@@ -181,7 +174,7 @@ def marshall(
|
|
181
174
|
figure_or_data: FigureOrData,
|
182
175
|
use_container_width: bool,
|
183
176
|
sharing: SharingMode,
|
184
|
-
theme:
|
177
|
+
theme: Literal["streamlit"] | None,
|
185
178
|
**kwargs: Any,
|
186
179
|
) -> None:
|
187
180
|
"""Marshall a proto with a Plotly spec.
|
@@ -664,11 +664,12 @@ class ButtonMixin:
|
|
664
664
|
if ctx:
|
665
665
|
ctx_main_script = ctx.main_script_path
|
666
666
|
|
667
|
-
|
667
|
+
normalized_ctx_main_script_path = os.path.normpath(ctx_main_script)
|
668
|
+
main_script_path = os.path.join(os.getcwd(), normalized_ctx_main_script_path)
|
668
669
|
main_script_directory = os.path.dirname(main_script_path)
|
669
670
|
|
670
|
-
# Convenience for handling ./ notation
|
671
|
-
page = os.path.normpath(page
|
671
|
+
# Convenience for handling ./ notation
|
672
|
+
page = os.path.normpath(page)
|
672
673
|
|
673
674
|
# Build full path
|
674
675
|
requested_page = os.path.join(main_script_directory, page)
|
@@ -677,17 +678,17 @@ class ButtonMixin:
|
|
677
678
|
# Handle retrieving the page_script_hash & page
|
678
679
|
for page_data in all_app_pages:
|
679
680
|
full_path = page_data["script_path"]
|
680
|
-
page_name = page_data["page_name"]
|
681
|
+
page_name = page_data["page_name"]
|
681
682
|
if requested_page == full_path:
|
682
683
|
if label is None:
|
683
|
-
page_link_proto.label = page_name
|
684
|
+
page_link_proto.label = page_name.replace("_", " ")
|
684
685
|
page_link_proto.page_script_hash = page_data["page_script_hash"]
|
685
|
-
page_link_proto.page =
|
686
|
+
page_link_proto.page = page_name
|
686
687
|
break
|
687
688
|
|
688
689
|
if page_link_proto.page_script_hash == "":
|
689
690
|
raise StreamlitAPIException(
|
690
|
-
f"Could not find page: '{page}'. Must be the file path relative to the main script, from the directory: {os.path.basename(main_script_directory)}."
|
691
|
+
f"Could not find page: '{page}'. Must be the file path relative to the main script, from the directory: {os.path.basename(main_script_directory)}. Only the main app file and files in the `pages/` directory are supported."
|
691
692
|
)
|
692
693
|
|
693
694
|
return self.dg._enqueue("page_link", page_link_proto)
|
@@ -29,7 +29,6 @@ from typing import (
|
|
29
29
|
overload,
|
30
30
|
)
|
31
31
|
|
32
|
-
from dateutil import relativedelta
|
33
32
|
from typing_extensions import TypeAlias
|
34
33
|
|
35
34
|
from streamlit.elements.form import current_form_id
|
@@ -68,6 +67,23 @@ ALLOWED_DATE_FORMATS = re.compile(
|
|
68
67
|
)
|
69
68
|
|
70
69
|
|
70
|
+
def _adjust_years(input_date: date, years: int) -> date:
|
71
|
+
"""Add or subtract years from a date."""
|
72
|
+
try:
|
73
|
+
# Attempt to directly add/subtract years
|
74
|
+
return input_date.replace(year=input_date.year + years)
|
75
|
+
except ValueError as err:
|
76
|
+
# Handle case for leap year date (February 29) that doesn't exist in the target year
|
77
|
+
# by moving the date to February 28
|
78
|
+
if input_date.month == 2 and input_date.day == 29:
|
79
|
+
return input_date.replace(year=input_date.year + years, month=2, day=28)
|
80
|
+
|
81
|
+
raise StreamlitAPIException(
|
82
|
+
f"Date {input_date} does not exist in the target year {input_date.year + years}. "
|
83
|
+
"This should never happen. Please report this bug."
|
84
|
+
) from err
|
85
|
+
|
86
|
+
|
71
87
|
def _parse_date_value(
|
72
88
|
value: DateValue | Literal["today"] | Literal["default_value_today"],
|
73
89
|
) -> Tuple[List[date] | None, bool]:
|
@@ -112,9 +128,9 @@ def _parse_min_date(
|
|
112
128
|
parsed_min_date = min_value
|
113
129
|
elif min_value is None:
|
114
130
|
if parsed_dates:
|
115
|
-
parsed_min_date = parsed_dates[0]
|
131
|
+
parsed_min_date = _adjust_years(parsed_dates[0], years=-10)
|
116
132
|
else:
|
117
|
-
parsed_min_date = date.today()
|
133
|
+
parsed_min_date = _adjust_years(date.today(), years=-10)
|
118
134
|
else:
|
119
135
|
raise StreamlitAPIException(
|
120
136
|
"DateInput min should either be a date/datetime or None"
|
@@ -133,9 +149,9 @@ def _parse_max_date(
|
|
133
149
|
parsed_max_date = max_value
|
134
150
|
elif max_value is None:
|
135
151
|
if parsed_dates:
|
136
|
-
parsed_max_date = parsed_dates[-1]
|
152
|
+
parsed_max_date = _adjust_years(parsed_dates[-1], years=10)
|
137
153
|
else:
|
138
|
-
parsed_max_date = date.today()
|
154
|
+
parsed_max_date = _adjust_years(date.today(), years=10)
|
139
155
|
else:
|
140
156
|
raise StreamlitAPIException(
|
141
157
|
"DateInput max should either be a date/datetime or None"
|
@@ -651,9 +667,9 @@ class TimeWidgetsMixin:
|
|
651
667
|
def _date_input(
|
652
668
|
self,
|
653
669
|
label: str,
|
654
|
-
value:
|
655
|
-
|
656
|
-
|
670
|
+
value: (
|
671
|
+
DateValue | Literal["today"] | Literal["default_value_today"]
|
672
|
+
) = "default_value_today",
|
657
673
|
min_value: SingleDateValue = None,
|
658
674
|
max_value: SingleDateValue = None,
|
659
675
|
key: Key | None = None,
|