streamlit-nightly 1.31.2.dev20240213__py2.py3-none-any.whl → 1.31.2.dev20240214__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.
Files changed (153) hide show
  1. streamlit/case_converters.py +9 -4
  2. streamlit/cli_util.py +2 -0
  3. streamlit/code_util.py +5 -2
  4. streamlit/color_util.py +2 -0
  5. streamlit/column_config.py +2 -0
  6. streamlit/commands/execution_control.py +4 -2
  7. streamlit/commands/experimental_query_params.py +7 -4
  8. streamlit/commands/page_config.py +11 -9
  9. streamlit/components/v1/components.py +23 -16
  10. streamlit/config.py +3 -5
  11. streamlit/config_option.py +12 -11
  12. streamlit/connections/base_connection.py +4 -2
  13. streamlit/connections/snowflake_connection.py +4 -4
  14. streamlit/connections/snowpark_connection.py +3 -3
  15. streamlit/connections/sql_connection.py +6 -6
  16. streamlit/connections/util.py +8 -5
  17. streamlit/constants.py +2 -0
  18. streamlit/cursor.py +16 -14
  19. streamlit/delta_generator.py +10 -13
  20. streamlit/deprecation_util.py +4 -3
  21. streamlit/echo.py +5 -3
  22. streamlit/elements/alert.py +16 -14
  23. streamlit/elements/altair_utils.py +8 -6
  24. streamlit/elements/arrow.py +4 -4
  25. streamlit/elements/arrow_altair.py +24 -34
  26. streamlit/elements/arrow_vega_lite.py +9 -14
  27. streamlit/elements/balloons.py +4 -2
  28. streamlit/elements/bokeh_chart.py +7 -7
  29. streamlit/elements/code.py +6 -4
  30. streamlit/elements/deck_gl_json_chart.py +8 -8
  31. streamlit/elements/doc_string.py +5 -9
  32. streamlit/elements/empty.py +4 -2
  33. streamlit/elements/exception.py +10 -10
  34. streamlit/elements/form.py +1 -3
  35. streamlit/elements/graphviz_chart.py +5 -6
  36. streamlit/elements/heading.py +16 -14
  37. streamlit/elements/iframe.py +14 -12
  38. streamlit/elements/image.py +8 -8
  39. streamlit/elements/json.py +6 -4
  40. streamlit/elements/layouts.py +12 -10
  41. streamlit/elements/lib/column_config_utils.py +2 -2
  42. streamlit/elements/lib/column_types.py +23 -23
  43. streamlit/elements/lib/dicttools.py +10 -6
  44. streamlit/elements/lib/mutable_status_container.py +7 -7
  45. streamlit/elements/lib/pandas_styler_utils.py +6 -6
  46. streamlit/elements/lib/streamlit_plotly_theme.py +2 -0
  47. streamlit/elements/map.py +11 -22
  48. streamlit/elements/markdown.py +16 -14
  49. streamlit/elements/media.py +16 -16
  50. streamlit/elements/metric.py +9 -7
  51. streamlit/elements/plotly_chart.py +5 -5
  52. streamlit/elements/progress.py +6 -6
  53. streamlit/elements/pyplot.py +10 -13
  54. streamlit/elements/snow.py +4 -2
  55. streamlit/elements/spinner.py +2 -0
  56. streamlit/elements/text.py +7 -5
  57. streamlit/elements/toast.py +6 -4
  58. streamlit/elements/utils.py +15 -28
  59. streamlit/elements/widgets/button.py +39 -39
  60. streamlit/elements/widgets/camera_input.py +21 -17
  61. streamlit/elements/widgets/chat.py +6 -7
  62. streamlit/elements/widgets/checkbox.py +21 -19
  63. streamlit/elements/widgets/color_picker.py +18 -16
  64. streamlit/elements/widgets/data_editor.py +7 -7
  65. streamlit/elements/widgets/file_uploader.py +59 -55
  66. streamlit/elements/widgets/multiselect.py +33 -42
  67. streamlit/elements/widgets/number_input.py +10 -5
  68. streamlit/elements/widgets/radio.py +1 -1
  69. streamlit/elements/widgets/select_slider.py +25 -34
  70. streamlit/elements/widgets/selectbox.py +1 -1
  71. streamlit/elements/widgets/slider.py +28 -36
  72. streamlit/elements/widgets/text_widgets.py +6 -6
  73. streamlit/elements/widgets/time_widgets.py +13 -13
  74. streamlit/elements/write.py +8 -19
  75. streamlit/env_util.py +5 -3
  76. streamlit/error_util.py +7 -3
  77. streamlit/errors.py +3 -1
  78. streamlit/external/langchain/streamlit_callback_handler.py +26 -24
  79. streamlit/file_util.py +18 -14
  80. streamlit/folder_black_list.py +3 -1
  81. streamlit/git_util.py +5 -3
  82. streamlit/js_number.py +10 -13
  83. streamlit/logger.py +5 -5
  84. streamlit/net_util.py +14 -11
  85. streamlit/platform.py +2 -0
  86. streamlit/runtime/__init__.py +2 -0
  87. streamlit/runtime/app_session.py +42 -42
  88. streamlit/runtime/caching/__init__.py +4 -4
  89. streamlit/runtime/caching/cache_data_api.py +3 -3
  90. streamlit/runtime/caching/cache_errors.py +5 -3
  91. streamlit/runtime/caching/cache_type.py +2 -0
  92. streamlit/runtime/caching/cache_utils.py +2 -4
  93. streamlit/runtime/caching/cached_message_replay.py +12 -5
  94. streamlit/runtime/caching/storage/cache_storage_protocol.py +1 -2
  95. streamlit/runtime/caching/storage/local_disk_cache_storage.py +6 -5
  96. streamlit/runtime/connection_factory.py +8 -8
  97. streamlit/runtime/forward_msg_cache.py +20 -18
  98. streamlit/runtime/forward_msg_queue.py +8 -9
  99. streamlit/runtime/legacy_caching/caching.py +32 -42
  100. streamlit/runtime/media_file_manager.py +16 -14
  101. streamlit/runtime/media_file_storage.py +8 -8
  102. streamlit/runtime/memory_media_file_storage.py +12 -14
  103. streamlit/runtime/memory_session_storage.py +4 -3
  104. streamlit/runtime/memory_uploaded_file_manager.py +9 -10
  105. streamlit/runtime/metrics_util.py +20 -20
  106. streamlit/runtime/runtime.py +25 -27
  107. streamlit/runtime/runtime_util.py +5 -3
  108. streamlit/runtime/script_data.py +2 -0
  109. streamlit/runtime/scriptrunner/magic.py +17 -11
  110. streamlit/runtime/scriptrunner/magic_funcs.py +2 -0
  111. streamlit/runtime/scriptrunner/script_requests.py +6 -4
  112. streamlit/runtime/scriptrunner/script_run_context.py +17 -17
  113. streamlit/runtime/scriptrunner/script_runner.py +7 -5
  114. streamlit/runtime/secrets.py +4 -6
  115. streamlit/runtime/session_manager.py +14 -14
  116. streamlit/runtime/state/common.py +5 -4
  117. streamlit/runtime/state/query_params.py +8 -6
  118. streamlit/runtime/state/query_params_proxy.py +7 -5
  119. streamlit/runtime/state/safe_session_state.py +7 -5
  120. streamlit/runtime/state/session_state.py +3 -4
  121. streamlit/runtime/state/session_state_proxy.py +5 -5
  122. streamlit/runtime/state/widgets.py +20 -18
  123. streamlit/runtime/uploaded_file_manager.py +6 -5
  124. streamlit/runtime/websocket_session_manager.py +14 -14
  125. streamlit/source_util.py +13 -11
  126. streamlit/string_util.py +13 -9
  127. streamlit/temporary_directory.py +3 -1
  128. streamlit/testing/v1/element_tree.py +1 -2
  129. streamlit/type_util.py +21 -25
  130. streamlit/url_util.py +6 -4
  131. streamlit/user_info.py +8 -6
  132. streamlit/util.py +23 -37
  133. streamlit/watcher/event_based_path_watcher.py +10 -10
  134. streamlit/watcher/local_sources_watcher.py +15 -13
  135. streamlit/watcher/path_watcher.py +0 -3
  136. streamlit/watcher/polling_path_watcher.py +9 -8
  137. streamlit/watcher/util.py +3 -2
  138. streamlit/web/cache_storage_manager_config.py +2 -0
  139. streamlit/web/server/app_static_file_handler.py +6 -5
  140. streamlit/web/server/browser_websocket_handler.py +10 -8
  141. streamlit/web/server/component_request_handler.py +7 -4
  142. streamlit/web/server/media_file_handler.py +5 -4
  143. streamlit/web/server/routes.py +6 -3
  144. streamlit/web/server/server.py +31 -31
  145. streamlit/web/server/server_util.py +4 -2
  146. streamlit/web/server/upload_file_request_handler.py +7 -8
  147. streamlit/web/server/websocket_headers.py +2 -2
  148. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/METADATA +1 -1
  149. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/RECORD +153 -153
  150. {streamlit_nightly-1.31.2.dev20240213.data → streamlit_nightly-1.31.2.dev20240214.data}/scripts/streamlit.cmd +0 -0
  151. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/WHEEL +0 -0
  152. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/entry_points.txt +0 -0
  153. {streamlit_nightly-1.31.2.dev20240213.dist-info → streamlit_nightly-1.31.2.dev20240214.dist-info}/top_level.txt +0 -0
@@ -27,13 +27,15 @@ compatible API continues to exist.
27
27
 
28
28
  Any major change to the StreamlitCallbackHandler should be tested by importing
29
29
  the API *from LangChain itself*.
30
+
31
+ This module is lazy-loaded.
30
32
  """
31
33
 
32
34
  from __future__ import annotations
33
35
 
34
36
  import time
35
37
  from enum import Enum
36
- from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, Optional
38
+ from typing import TYPE_CHECKING, Any, NamedTuple
37
39
 
38
40
  from langchain.callbacks.base import ( # type: ignore[import-not-found, unused-ignore]
39
41
  BaseCallbackHandler,
@@ -150,18 +152,18 @@ class LLMThought:
150
152
 
151
153
  self._state = LLMThoughtState.THINKING
152
154
  self._llm_token_stream = ""
153
- self._llm_token_stream_placeholder: Optional[DeltaGenerator] = None
154
- self._last_tool: Optional[ToolRecord] = None
155
+ self._llm_token_stream_placeholder: DeltaGenerator | None = None
156
+ self._last_tool: ToolRecord | None = None
155
157
  self._collapse_on_complete = collapse_on_complete
156
158
  self._labeler = labeler
157
159
 
158
160
  @property
159
- def container(self) -> "StatusContainer":
161
+ def container(self) -> StatusContainer:
160
162
  """The container we're writing into."""
161
163
  return self._container
162
164
 
163
165
  @property
164
- def last_tool(self) -> Optional[ToolRecord]:
166
+ def last_tool(self) -> ToolRecord | None:
165
167
  """The last tool executed by this thought"""
166
168
  return self._last_tool
167
169
 
@@ -172,7 +174,7 @@ class LLMThought:
172
174
  self._llm_token_stream = ""
173
175
  self._llm_token_stream_placeholder = None
174
176
 
175
- def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str]) -> None:
177
+ def on_llm_start(self, serialized: dict[str, Any], prompts: list[str]) -> None:
176
178
  self._reset_llm_token_stream()
177
179
 
178
180
  def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
@@ -194,7 +196,7 @@ class LLMThought:
194
196
  self._state = LLMThoughtState.ERROR
195
197
 
196
198
  def on_tool_start(
197
- self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
199
+ self, serialized: dict[str, Any], input_str: str, **kwargs: Any
198
200
  ) -> None:
199
201
  # Called with the name of the tool we're about to run (in `serialized[name]`),
200
202
  # and its input. We change our container's label to be the tool name.
@@ -212,9 +214,9 @@ class LLMThought:
212
214
  def on_tool_end(
213
215
  self,
214
216
  output: str,
215
- color: Optional[str] = None,
216
- observation_prefix: Optional[str] = None,
217
- llm_prefix: Optional[str] = None,
217
+ color: str | None = None,
218
+ observation_prefix: str | None = None,
219
+ llm_prefix: str | None = None,
218
220
  **kwargs: Any,
219
221
  ) -> None:
220
222
  self._container.markdown(output)
@@ -225,7 +227,7 @@ class LLMThought:
225
227
  self._container.update(state="error")
226
228
 
227
229
  def on_agent_action(
228
- self, action: AgentAction, color: Optional[str] = None, **kwargs: Any
230
+ self, action: AgentAction, color: str | None = None, **kwargs: Any
229
231
  ) -> Any:
230
232
  # Called when we're about to kick off a new tool. The `action` data
231
233
  # tells us the tool we're about to use, and the input we'll give it.
@@ -233,7 +235,7 @@ class LLMThought:
233
235
  # when `on_tool_start` is called immediately after.
234
236
  pass
235
237
 
236
- def complete(self, final_label: Optional[str] = None) -> None:
238
+ def complete(self, final_label: str | None = None) -> None:
237
239
  """Finish the thought."""
238
240
  if final_label is None and self._state == LLMThoughtState.RUNNING_TOOL:
239
241
  assert (
@@ -268,7 +270,7 @@ class StreamlitCallbackHandler(BaseCallbackHandler):
268
270
  max_thought_containers: int = 4,
269
271
  expand_new_thoughts: bool = False,
270
272
  collapse_completed_thoughts: bool = False,
271
- thought_labeler: Optional[LLMThoughtLabeler] = None,
273
+ thought_labeler: LLMThoughtLabeler | None = None,
272
274
  ):
273
275
  """Construct a new StreamlitCallbackHandler. This CallbackHandler is geared
274
276
  towards use with a LangChain Agent; it displays the Agent's LLM and tool-usage
@@ -305,8 +307,8 @@ class StreamlitCallbackHandler(BaseCallbackHandler):
305
307
  """
306
308
  self._parent_container = parent_container
307
309
  self._history_parent = parent_container.container()
308
- self._current_thought: Optional[LLMThought] = None
309
- self._completed_thoughts: List[LLMThought] = []
310
+ self._current_thought: LLMThought | None = None
311
+ self._completed_thoughts: list[LLMThought] = []
310
312
  self._max_thought_containers = max(max_thought_containers, 1)
311
313
  self._expand_new_thoughts = expand_new_thoughts
312
314
  self._collapse_completed_thoughts = collapse_completed_thoughts
@@ -320,13 +322,13 @@ class StreamlitCallbackHandler(BaseCallbackHandler):
320
322
  raise RuntimeError("Current LLMThought is unexpectedly None!")
321
323
  return self._current_thought
322
324
 
323
- def _get_last_completed_thought(self) -> Optional[LLMThought]:
325
+ def _get_last_completed_thought(self) -> LLMThought | None:
324
326
  """Return our most recent completed LLMThought, or None if we don't have one."""
325
327
  if len(self._completed_thoughts) > 0:
326
328
  return self._completed_thoughts[len(self._completed_thoughts) - 1]
327
329
  return None
328
330
 
329
- def _complete_current_thought(self, final_label: Optional[str] = None) -> None:
331
+ def _complete_current_thought(self, final_label: str | None = None) -> None:
330
332
  """Complete the current thought, optionally assigning it a new label.
331
333
  Add it to our _completed_thoughts list.
332
334
  """
@@ -336,7 +338,7 @@ class StreamlitCallbackHandler(BaseCallbackHandler):
336
338
  self._current_thought = None
337
339
 
338
340
  def on_llm_start(
339
- self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
341
+ self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any
340
342
  ) -> None:
341
343
  if self._current_thought is None:
342
344
  self._current_thought = LLMThought(
@@ -361,16 +363,16 @@ class StreamlitCallbackHandler(BaseCallbackHandler):
361
363
  self._require_current_thought().on_llm_error(error, **kwargs)
362
364
 
363
365
  def on_tool_start(
364
- self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
366
+ self, serialized: dict[str, Any], input_str: str, **kwargs: Any
365
367
  ) -> None:
366
368
  self._require_current_thought().on_tool_start(serialized, input_str, **kwargs)
367
369
 
368
370
  def on_tool_end(
369
371
  self,
370
372
  output: str,
371
- color: Optional[str] = None,
372
- observation_prefix: Optional[str] = None,
373
- llm_prefix: Optional[str] = None,
373
+ color: str | None = None,
374
+ observation_prefix: str | None = None,
375
+ llm_prefix: str | None = None,
374
376
  **kwargs: Any,
375
377
  ) -> None:
376
378
  self._require_current_thought().on_tool_end(
@@ -382,12 +384,12 @@ class StreamlitCallbackHandler(BaseCallbackHandler):
382
384
  self._require_current_thought().on_tool_error(error, **kwargs)
383
385
 
384
386
  def on_agent_action(
385
- self, action: AgentAction, color: Optional[str] = None, **kwargs: Any
387
+ self, action: AgentAction, color: str | None = None, **kwargs: Any
386
388
  ) -> Any:
387
389
  self._require_current_thought().on_agent_action(action, color, **kwargs)
388
390
 
389
391
  def on_agent_finish(
390
- self, finish: AgentFinish, color: Optional[str] = None, **kwargs: Any
392
+ self, finish: AgentFinish, color: str | None = None, **kwargs: Any
391
393
  ) -> None:
392
394
  if self._current_thought is not None:
393
395
  self._current_thought.complete(
streamlit/file_util.py CHANGED
@@ -12,9 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import contextlib
16
18
  import errno
17
- import fnmatch
18
19
  import io
19
20
  import os
20
21
  from pathlib import Path
@@ -29,7 +30,9 @@ CONFIG_FOLDER_NAME = ".streamlit"
29
30
  APP_STATIC_FOLDER_NAME = "static"
30
31
 
31
32
 
32
- def get_encoded_file_data(data, encoding="auto"):
33
+ def get_encoded_file_data(
34
+ data: bytes, encoding: str = "auto"
35
+ ) -> io.StringIO | io.BytesIO:
33
36
  """Coerce bytes to a BytesIO or a StringIO.
34
37
 
35
38
  Parameters
@@ -45,16 +48,15 @@ def get_encoded_file_data(data, encoding="auto"):
45
48
 
46
49
  """
47
50
  if encoding == "auto":
48
- if is_binary_string(data):
49
- encoding = None
50
- else:
51
- # If the file does not look like a pure binary file, assume
52
- # it's utf-8. It would be great if we could guess it a little
53
- # more smartly here, but it is what it is!
54
- encoding = "utf-8"
51
+ # If the file does not look like a pure binary file, assume
52
+ # it's utf-8. It would be great if we could guess it a little
53
+ # more smartly here, but it is what it is!
54
+ data_encoding = None if is_binary_string(data) else "utf-8"
55
+ else:
56
+ data_encoding = encoding
55
57
 
56
- if encoding:
57
- return io.StringIO(data.decode(encoding))
58
+ if data_encoding:
59
+ return io.StringIO(data.decode(data_encoding))
58
60
 
59
61
  return io.BytesIO(data)
60
62
 
@@ -116,7 +118,7 @@ def streamlit_write(path, binary=False):
116
118
  raise util.Error("\n".join(msg))
117
119
 
118
120
 
119
- def get_static_dir():
121
+ def get_static_dir() -> str:
120
122
  """Get the folder where static HTML/JS/CSS files live."""
121
123
  dirname = os.path.dirname(os.path.normpath(__file__))
122
124
  return os.path.normpath(os.path.join(dirname, "static"))
@@ -150,7 +152,7 @@ def get_project_streamlit_file_path(*filepath):
150
152
  return os.path.join(os.getcwd(), CONFIG_FOLDER_NAME, *filepath)
151
153
 
152
154
 
153
- def file_is_in_folder_glob(filepath, folderpath_glob) -> bool:
155
+ def file_is_in_folder_glob(filepath: str, folderpath_glob: str) -> bool:
154
156
  """Test whether a file is in some folder with globbing support.
155
157
 
156
158
  Parameters
@@ -169,6 +171,8 @@ def file_is_in_folder_glob(filepath, folderpath_glob) -> bool:
169
171
  else:
170
172
  folderpath_glob += "/*"
171
173
 
174
+ import fnmatch
175
+
172
176
  file_dir = os.path.dirname(filepath) + "/"
173
177
  return fnmatch.fnmatch(file_dir, folderpath_glob)
174
178
 
@@ -183,7 +187,7 @@ def get_directory_size(directory: str) -> int:
183
187
  return total_size
184
188
 
185
189
 
186
- def file_in_pythonpath(filepath) -> bool:
190
+ def file_in_pythonpath(filepath: str) -> bool:
187
191
  """Test whether a filepath is in the same folder of a path specified in the PYTHONPATH env variable.
188
192
 
189
193
 
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import os
16
18
 
17
19
  from streamlit import config, file_util, util
@@ -34,7 +36,7 @@ DEFAULT_FOLDER_BLACKLIST = [
34
36
  ]
35
37
 
36
38
 
37
- class FolderBlackList(object):
39
+ class FolderBlackList:
38
40
  """Implement a black list object with globbing.
39
41
 
40
42
  Note
streamlit/git_util.py CHANGED
@@ -12,9 +12,11 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import os
16
18
  import re
17
- from typing import Any, Optional, Tuple
19
+ from typing import Any
18
20
 
19
21
  from streamlit import util
20
22
 
@@ -32,7 +34,7 @@ class GitRepo:
32
34
  def __init__(self, path):
33
35
  # If we have a valid repo, git_version will be a tuple of 3+ ints:
34
36
  # (major, minor, patch, possible_additional_patch_number)
35
- self.git_version: Optional[Tuple[int, ...]] = None
37
+ self.git_version: tuple[int, ...] | None = None
36
38
 
37
39
  try:
38
40
  import git
@@ -124,7 +126,7 @@ class GitRepo:
124
126
 
125
127
  return self.repo.remote(remote_name), branch_name
126
128
 
127
- def is_github_repo(self):
129
+ def is_github_repo(self) -> bool:
128
130
  if not self.is_valid():
129
131
  return False
130
132
 
streamlit/js_number.py CHANGED
@@ -12,15 +12,16 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import numbers
16
- from typing import Optional, Union
17
18
 
18
19
 
19
20
  class JSNumberBoundsException(Exception):
20
21
  pass
21
22
 
22
23
 
23
- class JSNumber(object):
24
+ class JSNumber:
24
25
  """Utility class for exposing JavaScript Number constants."""
25
26
 
26
27
  # The largest int that can be represented with perfect precision
@@ -41,7 +42,7 @@ class JSNumber(object):
41
42
  MIN_NEGATIVE_VALUE = -MAX_VALUE
42
43
 
43
44
  @classmethod
44
- def validate_int_bounds(cls, value: int, value_name: Optional[str] = None) -> None:
45
+ def validate_int_bounds(cls, value: int, value_name: str | None = None) -> None:
45
46
  """Validate that an int value can be represented with perfect precision
46
47
  by a JavaScript Number.
47
48
 
@@ -64,17 +65,15 @@ class JSNumber(object):
64
65
 
65
66
  if value < cls.MIN_SAFE_INTEGER:
66
67
  raise JSNumberBoundsException(
67
- "%s (%s) must be >= -((1 << 53) - 1)" % (value_name, value)
68
+ f"{value_name} ({value}) must be >= -((1 << 53) - 1)"
68
69
  )
69
70
  elif value > cls.MAX_SAFE_INTEGER:
70
71
  raise JSNumberBoundsException(
71
- "%s (%s) must be <= (1 << 53) - 1" % (value_name, value)
72
+ f"{value_name} ({value}) must be <= (1 << 53) - 1"
72
73
  )
73
74
 
74
75
  @classmethod
75
- def validate_float_bounds(
76
- cls, value: Union[int, float], value_name: Optional[str]
77
- ) -> None:
76
+ def validate_float_bounds(cls, value: int | float, value_name: str | None) -> None:
78
77
  """Validate that a float value can be represented by a JavaScript Number.
79
78
 
80
79
  Parameters
@@ -95,14 +94,12 @@ class JSNumber(object):
95
94
  value_name = "value"
96
95
 
97
96
  if not isinstance(value, (numbers.Integral, float)):
98
- raise JSNumberBoundsException(
99
- "%s (%s) is not a float" % (value_name, value)
100
- )
97
+ raise JSNumberBoundsException(f"{value_name} ({value}) is not a float")
101
98
  elif value < cls.MIN_NEGATIVE_VALUE:
102
99
  raise JSNumberBoundsException(
103
- "%s (%s) must be >= -1.797e+308" % (value_name, value)
100
+ f"{value_name} ({value}) must be >= -1.797e+308"
104
101
  )
105
102
  elif value > cls.MAX_VALUE:
106
103
  raise JSNumberBoundsException(
107
- "%s (%s) must be <= 1.797e+308" % (value_name, value)
104
+ f"{value_name} ({value}) must be <= 1.797e+308"
108
105
  )
streamlit/logger.py CHANGED
@@ -14,22 +14,22 @@
14
14
 
15
15
  """Logging module."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import logging
18
20
  import sys
19
- from typing import Dict, Union
20
-
21
- from typing_extensions import Final
21
+ from typing import Final
22
22
 
23
23
  DEFAULT_LOG_MESSAGE: Final = "%(asctime)s %(levelname) -7s " "%(name)s: %(message)s"
24
24
 
25
25
  # Loggers for each name are saved here.
26
- _loggers: Dict[str, logging.Logger] = {}
26
+ _loggers: dict[str, logging.Logger] = {}
27
27
 
28
28
  # The global log level is set here across all names.
29
29
  _global_log_level = logging.INFO
30
30
 
31
31
 
32
- def set_log_level(level: Union[str, int]) -> None:
32
+ def set_log_level(level: str | int) -> None:
33
33
  """Set log level."""
34
34
  logger = get_logger(__name__)
35
35
 
streamlit/net_util.py CHANGED
@@ -12,25 +12,24 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import socket
16
- from typing import Optional
15
+ from __future__ import annotations
17
16
 
18
- from typing_extensions import Final
17
+ from typing import Final
19
18
 
20
19
  from streamlit import util
21
20
  from streamlit.logger import get_logger
22
21
 
23
- LOGGER = get_logger(__name__)
22
+ _LOGGER: Final = get_logger(__name__)
24
23
 
25
24
  # URLs for checking the current machine's external IP address.
26
25
  _AWS_CHECK_IP: Final = "http://checkip.amazonaws.com"
27
26
  _AWS_CHECK_IP_HTTPS: Final = "https://checkip.amazonaws.com"
28
27
 
29
- _external_ip: Optional[str] = None
30
- _internal_ip: Optional[str] = None
28
+ _external_ip: str | None = None
29
+ _internal_ip: str | None = None
31
30
 
32
31
 
33
- def get_external_ip() -> Optional[str]:
32
+ def get_external_ip() -> str | None:
34
33
  """Get the *external* IP address of the current machine.
35
34
 
36
35
  Returns
@@ -52,7 +51,7 @@ def get_external_ip() -> Optional[str]:
52
51
  if _looks_like_an_ip_adress(response):
53
52
  _external_ip = response
54
53
  else:
55
- LOGGER.warning(
54
+ _LOGGER.warning(
56
55
  # fmt: off
57
56
  "Did not auto detect external IP.\n"
58
57
  "Please go to %s for debugging hints.",
@@ -64,7 +63,7 @@ def get_external_ip() -> Optional[str]:
64
63
  return _external_ip
65
64
 
66
65
 
67
- def get_internal_ip() -> Optional[str]:
66
+ def get_internal_ip() -> str | None:
68
67
  """Get the *local* IP address of the current machine.
69
68
 
70
69
  From: https://stackoverflow.com/a/28950776
@@ -80,6 +79,8 @@ def get_internal_ip() -> Optional[str]:
80
79
  if _internal_ip is not None:
81
80
  return _internal_ip
82
81
 
82
+ import socket
83
+
83
84
  with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
84
85
  try:
85
86
  # Doesn't even have to be reachable
@@ -91,7 +92,7 @@ def get_internal_ip() -> Optional[str]:
91
92
  return _internal_ip
92
93
 
93
94
 
94
- def _make_blocking_http_get(url: str, timeout: float = 5) -> Optional[str]:
95
+ def _make_blocking_http_get(url: str, timeout: float = 5) -> str | None:
95
96
  import requests
96
97
 
97
98
  try:
@@ -103,10 +104,12 @@ def _make_blocking_http_get(url: str, timeout: float = 5) -> Optional[str]:
103
104
  return None
104
105
 
105
106
 
106
- def _looks_like_an_ip_adress(address: Optional[str]) -> bool:
107
+ def _looks_like_an_ip_adress(address: str | None) -> bool:
107
108
  if address is None:
108
109
  return False
109
110
 
111
+ import socket
112
+
110
113
  try:
111
114
  socket.inet_pton(socket.AF_INET, address)
112
115
  return True # Yup, this is an IPv4 address!
streamlit/platform.py CHANGED
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Platform module."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
18
20
  from streamlit.runtime.scriptrunner import get_script_run_ctx
19
21
 
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from streamlit.runtime.runtime import Runtime, RuntimeConfig, RuntimeState
16
18
  from streamlit.runtime.session_manager import (
17
19
  SessionClient,