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.
@@ -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
- main_script_path = os.path.join(os.getcwd(), ctx.main_script_path)
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 and ensure leading / doesn't refer to root directory
145
- page = os.path.normpath(page.strip("/"))
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 plotly.graph_objects as go
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
- # Template.data is for changing specific graph properties in a general aspect
22
- # such as Contour plots or Waterfall plots.
18
+ def configure_streamlit_plotly_theme() -> None:
19
+ """Configure the Streamlit chart theme for Plotly.
23
20
 
24
- # Template.layout is for changing things such as the x axis and fonts and other
25
- # general layout properties for general graphs.
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
- # We pass in temporary colors to the frontend and the frontend will replace
28
- # those colors because we want to change colors based on the background color.
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
- # Start at #0000001 because developers may be likely to use #000000
31
- CATEGORY_0 = "#000001"
32
- CATEGORY_1 = "#000002"
33
- CATEGORY_2 = "#000003"
34
- CATEGORY_3 = "#000004"
35
- CATEGORY_4 = "#000005"
36
- CATEGORY_5 = "#000006"
37
- CATEGORY_6 = "#000007"
38
- CATEGORY_7 = "#000008"
39
- CATEGORY_8 = "#000009"
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
- SEQUENTIAL_0 = "#000011"
43
- SEQUENTIAL_1 = "#000012"
44
- SEQUENTIAL_2 = "#000013"
45
- SEQUENTIAL_3 = "#000014"
46
- SEQUENTIAL_4 = "#000015"
47
- SEQUENTIAL_5 = "#000016"
48
- SEQUENTIAL_6 = "#000017"
49
- SEQUENTIAL_7 = "#000018"
50
- SEQUENTIAL_8 = "#000019"
51
- SEQUENTIAL_9 = "#000020"
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
- DIVERGING_0 = "#000021"
54
- DIVERGING_1 = "#000022"
55
- DIVERGING_2 = "#000023"
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
- INCREASING = "#000032"
66
- DECREASING = "#000033"
67
- TOTAL = "#000034"
75
+ GRAY_70 = "#000036"
76
+ GRAY_90 = "#000037"
77
+ BG_COLOR = "#000038"
78
+ FADED_TEXT_05 = "#000039"
79
+ BG_MIX = "#000040"
68
80
 
69
- GRAY_30 = "#000035"
70
- GRAY_70 = "#000036"
71
- GRAY_90 = "#000037"
72
- BG_COLOR = "#000038"
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
- # Plotly represents continuous colorscale through an array of pairs.
78
- # The pair's first index is the starting point and the next pair's first index is the end point.
79
- # The pair's second index is the starting color and the next pair's second index is the end color.
80
- # For more information, please refer to https://plotly.com/python/colorscales/
81
-
82
- streamlit_colorscale = [
83
- [0.0, SEQUENTIAL_0],
84
- [0.1111111111111111, SEQUENTIAL_1],
85
- [0.2222222222222222, SEQUENTIAL_2],
86
- [0.3333333333333333, SEQUENTIAL_3],
87
- [0.4444444444444444, SEQUENTIAL_4],
88
- [0.5555555555555556, SEQUENTIAL_5],
89
- [0.6666666666666666, SEQUENTIAL_6],
90
- [0.7777777777777778, SEQUENTIAL_7],
91
- [0.8888888888888888, SEQUENTIAL_8],
92
- [1.0, SEQUENTIAL_9],
93
- ]
94
-
95
- pio.templates["streamlit"] = go.layout.Template(
96
- data=go.layout.template.Data(
97
- candlestick=[
98
- go.layout.template.data.Candlestick(
99
- decreasing=go.candlestick.Decreasing(
100
- line=go.candlestick.decreasing.Line(color=DECREASING)
101
- ),
102
- increasing=go.candlestick.Increasing(
103
- line=go.candlestick.increasing.Line(color=INCREASING)
104
- ),
105
- )
106
- ],
107
- contour=[go.layout.template.data.Contour(colorscale=streamlit_colorscale)],
108
- contourcarpet=[
109
- go.layout.template.data.Contourcarpet(colorscale=streamlit_colorscale)
110
- ],
111
- heatmap=[go.layout.template.data.Heatmap(colorscale=streamlit_colorscale)],
112
- histogram2d=[
113
- go.layout.template.data.Histogram2d(colorscale=streamlit_colorscale)
114
- ],
115
- icicle=[
116
- go.layout.template.data.Icicle(textfont=go.icicle.Textfont(color="white"))
117
- ],
118
- sankey=[
119
- go.layout.template.data.Sankey(textfont=go.sankey.Textfont(color=GRAY_70))
120
- ],
121
- scatter=[
122
- go.layout.template.data.Scatter(
123
- marker=go.scatter.Marker(line=go.scatter.marker.Line(width=0))
124
- )
125
- ],
126
- table=[
127
- go.layout.template.data.Table(
128
- cells=go.table.Cells(
129
- fill=go.table.cells.Fill(color=BG_COLOR),
130
- font=go.table.cells.Font(color=GRAY_90),
131
- line=go.table.cells.Line(color=FADED_TEXT_05),
132
- ),
133
- header=go.table.Header(
134
- font=go.table.header.Font(color=GRAY_70),
135
- line=go.table.header.Line(color=FADED_TEXT_05),
136
- fill=go.table.header.Fill(color=BG_MIX),
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
- waterfall=[
141
- go.layout.template.data.Waterfall(
142
- increasing=go.waterfall.Increasing(
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 Final, Literal, TypeAlias
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
- try:
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: Union[None, Literal["streamlit"]] = "streamlit",
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: Union[None, Literal["streamlit"]],
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
- main_script_path = os.path.join(os.getcwd(), ctx_main_script)
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 and ensure leading / doesn't refer to root directory
671
- page = os.path.normpath(page.strip("/"))
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"].replace("_", " ")
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 = full_path
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] - relativedelta.relativedelta(years=10)
131
+ parsed_min_date = _adjust_years(parsed_dates[0], years=-10)
116
132
  else:
117
- parsed_min_date = date.today() - relativedelta.relativedelta(years=10)
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] + relativedelta.relativedelta(years=10)
152
+ parsed_max_date = _adjust_years(parsed_dates[-1], years=10)
137
153
  else:
138
- parsed_max_date = date.today() + relativedelta.relativedelta(years=10)
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: DateValue
655
- | Literal["today"]
656
- | Literal["default_value_today"] = "default_value_today",
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,