-
Notifications
You must be signed in to change notification settings - Fork 17.6k
chore(export): Added ability to export chart YAML files with Unicode characters, fix #20331 #28008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 3 commits
8a8524f
32a723e
a526bf9
a274ae4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -507,6 +507,29 @@ def test_export_dashboard_command_no_related(self, mock_g1, mock_g2): | |
| } | ||
| assert expected_paths == set(contents.keys()) | ||
|
|
||
| @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") | ||
| @patch("superset.security.manager.g") | ||
| @patch("superset.views.base.g") | ||
| def test_export_dashboard_command_unicode_chars(self, mock_g1, mock_g2): | ||
| mock_g1.user = security_manager.find_user("admin") | ||
| mock_g2.user = security_manager.find_user("admin") | ||
| db.session.query(Dashboard).filter_by(slug="world_health").update( | ||
| {"dashboard_title": "中文"}, | ||
| ) | ||
| example_dashboard = ( | ||
| db.session.query(Dashboard).filter_by(dashboard_title="中文").one() | ||
| ) | ||
|
|
||
| command = ExportDashboardsCommand([example_dashboard.id]) | ||
| contents = dict(command.run()) | ||
|
|
||
| path = f"dashboards/{example_dashboard.id}.yaml" | ||
| assert path in set(contents.keys()) | ||
| yaml_content = contents[path]() | ||
| metadata = yaml.safe_load(yaml_content) | ||
| assert metadata["dashboard_title"] == "中文" | ||
| assert "dashboard_title: 中文" in yaml_content | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test isolation failure
This test modifies shared fixture data (dashboard_title changed from "World Bank's Data" to "中文") without restoring it. The fixture cleanup deletes by ID, not by title, so the modification persists. If Code suggestionCheck the AI-generated fix before applying Code Review Run #e26422 Should Bito avoid suggestions like this for future reviews? (Manage Rules)
|
||
|
|
||
|
|
||
| class TestImportDashboardsCommand(SupersetTestCase): | ||
| def test_import_v0_dashboard_cli_export(self): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -395,6 +395,24 @@ def test_export_database_command_no_related(self, mock_g): | |
| assert "databases" in prefixes | ||
| assert "datasets" not in prefixes | ||
|
|
||
| @patch("superset.security.manager.g") | ||
| def test_export_database_command_unicode_chars(self, mock_g): | ||
| mock_g.user = security_manager.find_user("admin") | ||
| db.session.query(Database).filter_by(database_name="中文").delete() | ||
| command = CreateDatabaseCommand( | ||
| {"database_name": "中文", "sqlalchemy_uri": "sqlite:///:memory:"}, | ||
| ) | ||
| example_db = command.run() | ||
|
|
||
| command = ExportDatabasesCommand([example_db.id], export_related=False) | ||
| contents = dict(command.run()) | ||
|
|
||
| path = f"databases/{example_db.id}.yaml" | ||
| assert path in set(contents.keys()) | ||
| yaml_content = contents[path]() | ||
| assert "database_name: 中文" in yaml_content | ||
| db.session.query(Database).filter_by(database_name="中文").delete() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The test deletes the temporary Severity Level: Major
|
||
|
|
||
|
|
||
| class TestImportDatabasesCommand(SupersetTestCase): | ||
| @patch("superset.security.manager.g") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -273,6 +273,37 @@ def test_export_dataset_command_no_related(self, mock_g): | |
| f"datasets/examples/energy_usage_{example_dataset.id}.yaml", | ||
| ] | ||
|
|
||
| @patch("superset.security.manager.g") | ||
| def test_export_dataset_command_unicode_chars(self, mock_g): | ||
| mock_g.user = security_manager.find_user("admin") | ||
| examples_db = get_example_database() | ||
| with examples_db.get_sqla_engine() as engine: | ||
| engine.execute("DROP TABLE IF EXISTS 中文") | ||
| engine.execute("CREATE TABLE 中文 AS SELECT 2 as col") | ||
| if db.session.query(SqlaTable).filter_by(table_name="中文").count(): | ||
| db.session.query(SqlaTable).filter_by(table_name="中文").delete() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The cleanup query deletes datasets by Severity Level: Major
|
||
| with override_user(security_manager.find_user("admin")): | ||
| example_dataset = CreateDatasetCommand( | ||
| { | ||
| "table_name": "中文", | ||
| "database": examples_db.id, | ||
| } | ||
| ).run() | ||
|
|
||
| command = ExportDatasetsCommand([example_dataset.id], export_related=False) | ||
| contents = dict(command.run()) | ||
|
|
||
| path = f"datasets/examples/{example_dataset.id}.yaml" | ||
| assert path in set(contents.keys()) | ||
| yaml_content = contents[path]() | ||
| assert "table_name: 中文" in yaml_content | ||
|
|
||
| db.session.delete(example_dataset) | ||
| db.session.commit() | ||
| with examples_db.get_sqla_engine() as engine: | ||
| engine.execute("DROP TABLE 中文") | ||
| db.session.commit() | ||
|
Comment on lines
+298
to
+310
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The dataset/table teardown runs only on the happy path; if any assertion above fails, cleanup is skipped and leaves persistent DB artifacts that can break later tests. Wrap the body in Severity Level: Major
|
||
|
|
||
|
|
||
| class TestImportDatasetsCommand(SupersetTestCase): | ||
| @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") | ||
|
|
@@ -602,6 +633,7 @@ def test_create_dataset_command(self): | |
| assert [owner.username for owner in table.owners] == ["admin"] | ||
|
|
||
| db.session.delete(table) | ||
| db.session.commit() | ||
|
xyb marked this conversation as resolved.
|
||
| with examples_db.get_sqla_engine() as engine: | ||
| engine.execute("DROP TABLE test_create_dataset_command") | ||
| db.session.commit() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: The state reset for the renamed chart is placed after assertions instead of in a guaranteed cleanup path. If any assertion fails, the chart name remains changed and fixture teardown can fail because cleanup expects
Energy Sankeyto exist. Move the rename-back logic into afinallyblock so cleanup always runs. [missing cleanup]Severity Level: Major⚠️
Steps of Reproduction ✅
Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖