Skip to content

Conversation

@kmcgrady
Copy link
Collaborator

@kmcgrady kmcgrady commented Oct 19, 2025

Describe your changes

Added support for rendering TransientNode elements in the RenderNodeVisitor class. This implementation:

  • Adds a new visitTransientNode method that properly renders both transient elements and their anchor
  • Ensures transient elements get unique keys with a transient-{n} format
  • Maintains proper element collection order in the visitor
  • Supports both cases where an anchor may or may not be present

Updated the OptionalReactElement type to OptionalReactElements to better handle arrays of elements that can be returned from visitor methods.

Testing Plan

  • Added comprehensive unit tests for the new visitTransientNode method
  • Tests cover key generation, element ordering, multiple transient node handling, and different anchor scenarios
  • Existing tests were updated to accommodate the type changes

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

@snyk-io
Copy link
Contributor

snyk-io bot commented Oct 19, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 19, 2025

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-12825/streamlit-1.51.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-12825.streamlit.app (☁️ Deploy here if not accessible)

@kmcgrady kmcgrady added security-assessment-completed Security assessment has been completed for PR change:refactor PR contains code refactoring without behavior change impact:internal PR changes only affect internal code labels Oct 19, 2025 — with Graphite App
@github-actions
Copy link
Contributor

github-actions bot commented Oct 19, 2025

📈 Frontend coverage change detected

The frontend unit test (vitest) coverage has increased by 0.0100%

  • Current PR: 89.2300% (51657 lines, 5561 missed)
  • Latest develop: 89.2200% (51633 lines, 5562 missed)

✅ Coverage change is within normal range.

📊 View detailed coverage comparison

@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from f495729 to df55dda Compare October 24, 2025 15:05
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from fd2949a to a08f533 Compare October 24, 2025 15:05
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from df55dda to b29ab22 Compare October 24, 2025 16:42
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch 2 times, most recently from 25fb3a2 to ab774d5 Compare October 24, 2025 16:56
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from b29ab22 to 2494645 Compare October 24, 2025 16:56
@github-actions
Copy link
Contributor

github-actions bot commented Oct 24, 2025

📉 Python coverage change detected

The Python unit test coverage has decreased by 0.0049%

  • Current PR: 92.8575% (20609 statements, 1472 missed)
  • Latest develop: 92.8623% (20609 statements, 1471 missed)

✅ Coverage change is within normal range.

Coverage by files
Name Stmts Miss Cover
streamlit/__init__.py 142 0 100%
streamlit/__main__.py 3 3 0%
streamlit/auth_util.py 100 25 75%
streamlit/cli_util.py 39 6 85%
streamlit/column_config.py 3 0 100%
streamlit/commands/__init__.py 0 0 100%
streamlit/commands/echo.py 54 11 80%
streamlit/commands/execution_control.py 70 10 86%
streamlit/commands/experimental_query_params.py 40 2 95%
streamlit/commands/logo.py 41 6 85%
streamlit/commands/navigation.py 106 2 98%
streamlit/commands/page_config.py 101 4 96%
streamlit/components/__init__.py 0 0 100%
streamlit/components/lib/__init__.py 0 0 100%
streamlit/components/lib/local_component_registry.py 35 2 94%
streamlit/components/types/__init__.py 0 0 100%
streamlit/components/types/base_component_registry.py 14 0 100%
streamlit/components/types/base_custom_component.py 49 6 88%
streamlit/components/v1/__init__.py 5 0 100%
streamlit/components/v1/component_arrow.py 33 8 76%
streamlit/components/v1/component_registry.py 41 3 93%
streamlit/components/v1/components.py 4 4 0%
streamlit/components/v1/custom_component.py 85 7 92%
streamlit/components/v2/__init__.py 24 0 100%
streamlit/components/v2/bidi_component/__init__.py 4 0 100%
streamlit/components/v2/bidi_component/constants.py 5 0 100%
streamlit/components/v2/bidi_component/main.py 152 17 89%
streamlit/components/v2/bidi_component/serialization.py 81 2 98%
streamlit/components/v2/bidi_component/state.py 13 0 100%
streamlit/components/v2/component_definition_resolver.py 30 0 100%
streamlit/components/v2/component_file_watcher.py 117 9 92%
streamlit/components/v2/component_manager.py 97 13 87%
streamlit/components/v2/component_manifest_handler.py 24 0 100%
streamlit/components/v2/component_path_utils.py 68 5 93%
streamlit/components/v2/component_registry.py 121 8 93%
streamlit/components/v2/get_bidi_component_manager.py 8 1 88%
streamlit/components/v2/manifest_scanner.py 224 25 89%
streamlit/components/v2/presentation.py 84 19 77%
streamlit/components/v2/types.py 8 8 0%
streamlit/config.py 412 12 97%
streamlit/config_option.py 79 3 96%
streamlit/config_util.py 288 7 98%
streamlit/connections/__init__.py 6 0 100%
streamlit/connections/base_connection.py 45 0 100%
streamlit/connections/snowflake_connection.py 60 13 78%
streamlit/connections/snowpark_connection.py 44 3 93%
streamlit/connections/sql_connection.py 56 6 89%
streamlit/connections/util.py 33 0 100%
streamlit/cursor.py 82 2 98%
streamlit/dataframe_util.py 501 47 91%
streamlit/delta_generator.py 208 6 97%
streamlit/delta_generator_singletons.py 70 4 94%
streamlit/deprecation_util.py 59 4 93%
streamlit/development.py 1 0 100%
streamlit/elements/__init__.py 0 0 100%
streamlit/elements/alert.py 60 0 100%
streamlit/elements/arrow.py 201 15 93%
streamlit/elements/balloons.py 10 0 100%
streamlit/elements/bokeh_chart.py 9 0 100%
streamlit/elements/code.py 20 1 95%
streamlit/elements/deck_gl_json_chart.py 104 10 90%
streamlit/elements/dialog_decorator.py 38 0 100%
streamlit/elements/doc_string.py 227 9 96%
streamlit/elements/empty.py 16 4 75%
streamlit/elements/exception.py 101 10 90%
streamlit/elements/form.py 54 2 96%
streamlit/elements/graphviz_chart.py 35 1 97%
streamlit/elements/heading.py 56 0 100%
streamlit/elements/html.py 49 0 100%
streamlit/elements/iframe.py 29 0 100%
streamlit/elements/image.py 32 0 100%
streamlit/elements/json.py 39 2 95%
streamlit/elements/layouts.py 140 3 98%
streamlit/elements/lib/__init__.py 0 0 100%
streamlit/elements/lib/built_in_chart_utils.py 390 26 93%
streamlit/elements/lib/color_util.py 100 4 96%
streamlit/elements/lib/column_config_utils.py 169 1 99%
streamlit/elements/lib/column_types.py 189 4 98%
streamlit/elements/lib/dialog.py 67 1 99%
streamlit/elements/lib/dicttools.py 39 2 95%
streamlit/elements/lib/file_uploader_utils.py 30 0 100%
streamlit/elements/lib/form_utils.py 26 0 100%
streamlit/elements/lib/image_utils.py 176 21 88%
streamlit/elements/lib/js_number.py 28 3 89%
streamlit/elements/lib/layout_utils.py 121 1 99%
streamlit/elements/lib/mutable_status_container.py 73 4 95%
streamlit/elements/lib/options_selector_utils.py 90 0 100%
streamlit/elements/lib/pandas_styler_utils.py 80 2 98%
streamlit/elements/lib/policies.py 56 1 98%
streamlit/elements/lib/shortcut_utils.py 42 2 95%
streamlit/elements/lib/streamlit_plotly_theme.py 49 0 100%
streamlit/elements/lib/subtitle_utils.py 76 13 83%
streamlit/elements/lib/utils.py 76 5 93%
streamlit/elements/map.py 110 1 99%
streamlit/elements/markdown.py 65 2 97%
streamlit/elements/media.py 181 8 96%
streamlit/elements/metric.py 104 0 100%
streamlit/elements/pdf.py 49 2 96%
streamlit/elements/plotly_chart.py 129 6 95%
streamlit/elements/progress.py 36 0 100%
streamlit/elements/pyplot.py 39 2 95%
streamlit/elements/snow.py 10 0 100%
streamlit/elements/space.py 12 0 100%
streamlit/elements/spinner.py 34 0 100%
streamlit/elements/text.py 16 0 100%
streamlit/elements/toast.py 26 0 100%
streamlit/elements/vega_charts.py 228 3 99%
streamlit/elements/widgets/__init__.py 0 0 100%
streamlit/elements/widgets/audio_input.py 68 10 85%
streamlit/elements/widgets/button.py 225 5 98%
streamlit/elements/widgets/button_group.py 171 1 99%
streamlit/elements/widgets/camera_input.py 62 10 84%
streamlit/elements/widgets/chat.py 233 58 75%
streamlit/elements/widgets/checkbox.py 52 0 100%
streamlit/elements/widgets/color_picker.py 59 2 97%
streamlit/elements/widgets/data_editor.py 246 14 94%
streamlit/elements/widgets/file_uploader.py 103 18 83%
streamlit/elements/widgets/multiselect.py 105 4 96%
streamlit/elements/widgets/number_input.py 143 5 97%
streamlit/elements/widgets/radio.py 83 5 94%
streamlit/elements/widgets/select_slider.py 97 0 100%
streamlit/elements/widgets/selectbox.py 91 2 98%
streamlit/elements/widgets/slider.py 241 8 97%
streamlit/elements/widgets/text_widgets.py 130 6 95%
streamlit/elements/widgets/time_widgets.py 390 19 95%
streamlit/elements/write.py 166 32 81%
streamlit/emojis.py 4 0 100%
streamlit/env_util.py 21 3 86%
streamlit/error_util.py 33 2 94%
streamlit/errors.py 194 25 87%
streamlit/external/__init__.py 0 0 100%
streamlit/external/langchain/__init__.py 2 0 100%
streamlit/external/langchain/streamlit_callback_handler.py 141 82 42%
streamlit/file_util.py 84 8 90%
streamlit/git_util.py 100 5 95%
streamlit/logger.py 54 0 100%
streamlit/material_icon_names.py 1 0 100%
streamlit/navigation/__init__.py 0 0 100%
streamlit/navigation/page.py 78 2 97%
streamlit/net_util.py 55 3 95%
streamlit/platform.py 10 1 90%
streamlit/runtime/__init__.py 8 0 100%
streamlit/runtime/app_session.py 460 91 80%
streamlit/runtime/caching/__init__.py 19 0 100%
streamlit/runtime/caching/cache_data_api.py 164 3 98%
streamlit/runtime/caching/cache_errors.py 45 4 91%
streamlit/runtime/caching/cache_resource_api.py 122 0 100%
streamlit/runtime/caching/cache_type.py 11 1 91%
streamlit/runtime/caching/cache_utils.py 165 9 95%
streamlit/runtime/caching/cached_message_replay.py 108 1 99%
streamlit/runtime/caching/hashing.py 311 25 92%
streamlit/runtime/caching/legacy_cache_api.py 14 0 100%
streamlit/runtime/caching/storage/__init__.py 2 0 100%
streamlit/runtime/caching/storage/cache_storage_protocol.py 31 2 94%
streamlit/runtime/caching/storage/dummy_cache_storage.py 21 0 100%
streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py 60 0 100%
streamlit/runtime/caching/storage/local_disk_cache_storage.py 86 4 95%
streamlit/runtime/connection_factory.py 85 9 89%
streamlit/runtime/context.py 140 0 100%
streamlit/runtime/context_util.py 18 0 100%
streamlit/runtime/credentials.py 139 4 97%
streamlit/runtime/download_data_util.py 27 0 100%
streamlit/runtime/forward_msg_cache.py 23 2 91%
streamlit/runtime/forward_msg_queue.py 63 4 94%
streamlit/runtime/fragment.py 112 2 98%
streamlit/runtime/media_file_manager.py 110 7 94%
streamlit/runtime/media_file_storage.py 15 0 100%
streamlit/runtime/memory_media_file_storage.py 68 0 100%
streamlit/runtime/memory_session_storage.py 15 0 100%
streamlit/runtime/memory_uploaded_file_manager.py 41 1 98%
streamlit/runtime/metrics_util.py 193 12 94%
streamlit/runtime/pages_manager.py 59 2 97%
streamlit/runtime/runtime.py 248 18 93%
streamlit/runtime/runtime_util.py 30 1 97%
streamlit/runtime/script_data.py 16 0 100%
streamlit/runtime/scriptrunner/__init__.py 5 0 100%
streamlit/runtime/scriptrunner/exec_code.py 49 5 90%
streamlit/runtime/scriptrunner/magic.py 83 1 99%
streamlit/runtime/scriptrunner/magic_funcs.py 10 1 90%
streamlit/runtime/scriptrunner/script_cache.py 27 0 100%
streamlit/runtime/scriptrunner/script_runner.py 230 27 88%
streamlit/runtime/scriptrunner_utils/__init__.py 0 0 100%
streamlit/runtime/scriptrunner_utils/exceptions.py 11 1 91%
streamlit/runtime/scriptrunner_utils/script_requests.py 106 5 95%
streamlit/runtime/scriptrunner_utils/script_run_context.py 135 2 99%
streamlit/runtime/secrets.py 242 26 89%
streamlit/runtime/session_manager.py 60 1 98%
streamlit/runtime/state/__init__.py 7 0 100%
streamlit/runtime/state/common.py 52 2 96%
streamlit/runtime/state/presentation.py 19 4 79%
streamlit/runtime/state/query_params.py 134 5 96%
streamlit/runtime/state/query_params_proxy.py 71 0 100%
streamlit/runtime/state/safe_session_state.py 77 9 88%
streamlit/runtime/state/session_state.py 433 29 93%
streamlit/runtime/state/session_state_proxy.py 62 8 87%
streamlit/runtime/state/widgets.py 15 1 93%
streamlit/runtime/stats.py 42 0 100%
streamlit/runtime/theme_util.py 46 1 98%
streamlit/runtime/uploaded_file_manager.py 39 3 92%
streamlit/runtime/websocket_session_manager.py 66 0 100%
streamlit/source_util.py 36 1 97%
streamlit/string_util.py 92 8 91%
streamlit/temporary_directory.py 18 1 94%
streamlit/testing/__init__.py 0 0 100%
streamlit/testing/v1/__init__.py 2 0 100%
streamlit/testing/v1/app_test.py 242 6 98%
streamlit/testing/v1/element_tree.py 1371 87 94%
streamlit/testing/v1/local_script_runner.py 71 2 97%
streamlit/testing/v1/util.py 17 0 100%
streamlit/time_util.py 28 1 96%
streamlit/type_util.py 138 12 91%
streamlit/url_util.py 39 5 87%
streamlit/user_info.py 87 8 91%
streamlit/util.py 38 1 97%
streamlit/version.py 3 0 100%
streamlit/watcher/__init__.py 3 0 100%
streamlit/watcher/event_based_path_watcher.py 181 24 87%
streamlit/watcher/folder_black_list.py 14 1 93%
streamlit/watcher/local_sources_watcher.py 127 9 93%
streamlit/watcher/path_watcher.py 43 3 93%
streamlit/watcher/polling_path_watcher.py 55 2 96%
streamlit/watcher/util.py 49 1 98%
streamlit/web/__init__.py 0 0 100%
streamlit/web/bootstrap.py 153 20 87%
streamlit/web/cache_storage_manager_config.py 5 0 100%
streamlit/web/cli.py 186 17 91%
streamlit/web/server/__init__.py 5 0 100%
streamlit/web/server/app_static_file_handler.py 29 3 90%
streamlit/web/server/authlib_tornado_integration.py 18 1 94%
streamlit/web/server/bidi_component_request_handler.py 65 8 88%
streamlit/web/server/browser_websocket_handler.py 115 31 73%
streamlit/web/server/component_file_utils.py 24 0 100%
streamlit/web/server/component_request_handler.py 55 4 93%
streamlit/web/server/media_file_handler.py 65 9 86%
streamlit/web/server/oauth_authlib_routes.py 118 18 85%
streamlit/web/server/oidc_mixin.py 44 0 100%
streamlit/web/server/routes.py 90 7 92%
streamlit/web/server/server.py 188 11 94%
streamlit/web/server/server_util.py 67 5 93%
streamlit/web/server/stats_request_handler.py 53 4 92%
streamlit/web/server/upload_file_request_handler.py 59 14 76%
streamlit/web/server/websocket_headers.py 19 1 95%
TOTAL 20609 1472 93%

📊 View detailed coverage comparison

@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from 2494645 to ddb5f47 Compare October 24, 2025 17:47
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from ab774d5 to ce454a9 Compare October 24, 2025 17:47
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 4701026 to 311e7f7 Compare November 3, 2025 00:35
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from a685eb1 to 21742c2 Compare November 3, 2025 00:35
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements rendering support for TransientNode elements in the RenderNodeVisitor class. Previously, transient nodes were not rendered (the method returned null), but now they are properly rendered with their transient elements and anchor node.

Key changes:

  • Updated visitTransientNode to render both transient child elements and the anchor element
  • Added support for an optional elementKeyOverride parameter to control React keys for transient elements
  • Changed return types from OptionalReactElement to OptionalReactElements to support returning arrays of elements

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
RenderNodeVisitor.tsx Implements transient node rendering logic, adds key override mechanism, and updates type signatures to support arrays
RenderNodeVisitor.test.tsx Adds comprehensive test coverage for the new visitTransientNode functionality

@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from 21742c2 to d31f7d6 Compare November 3, 2025 02:07
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 311e7f7 to 98489a8 Compare November 3, 2025 02:07
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from d31f7d6 to c243fdb Compare November 4, 2025 00:50
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 98489a8 to 9733c23 Compare November 4, 2025 00:50
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from c243fdb to ef039c6 Compare November 4, 2025 01:45
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch 2 times, most recently from 901f681 to a48d051 Compare November 4, 2025 02:00
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch 2 times, most recently from d576da1 to 5656d58 Compare November 4, 2025 02:15
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from a48d051 to 652f605 Compare November 4, 2025 02:16
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from 5656d58 to d739b88 Compare November 5, 2025 03:50
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 652f605 to 79af71b Compare November 5, 2025 03:50
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 79af71b to 4230417 Compare November 23, 2025 01:50
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from d739b88 to 1572978 Compare November 23, 2025 01:50
@github-actions
Copy link
Contributor

📈 Significant wheel size change detected

The wheel file size has increased by 11.37% (threshold: 0.25%)

  • Current PR: 9873.66 KB
  • Latest develop: 8865.57 KB

Please verify this change is expected.

Copy link
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 4230417 to fc88b4d Compare December 1, 2025 15:28
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from 1572978 to 4cf1b51 Compare December 1, 2025 15:28
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from fc88b4d to 3ba5eb9 Compare December 1, 2025 15:47
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor branch from 4cf1b51 to c6876b6 Compare December 1, 2025 15:47
Base automatically changed from 10-19-implement_visittransientnode_on_setnodebydeltapathvisitor to develop December 1, 2025 16:55
@kmcgrady kmcgrady force-pushed the 10-19-implement_visittransientnode_on_rendernodevisitor branch from 3ba5eb9 to c7891e9 Compare December 1, 2025 16:55
@sfc-gh-kmcgrady sfc-gh-kmcgrady merged commit 684508c into develop Dec 1, 2025
42 checks passed
@sfc-gh-kmcgrady sfc-gh-kmcgrady deleted the 10-19-implement_visittransientnode_on_rendernodevisitor branch December 1, 2025 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:refactor PR contains code refactoring without behavior change impact:internal PR changes only affect internal code security-assessment-completed Security assessment has been completed for PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants