Skip to content

chore(tags): stop auto-generating type:/editor:/favorited_by: tags - #43471

Open
rusackas wants to merge 2 commits into
masterfrom
chore/remove-implicit-tag-generation
Open

chore(tags): stop auto-generating type:/editor:/favorited_by: tags#43471
rusackas wants to merge 2 commits into
masterfrom
chore/remove-implicit-tag-generation

Conversation

@rusackas

Copy link
Copy Markdown
Member

SUMMARY

On #43390, villebro noted that these system-generated tags appear to be unused, and suggested considering removing them entirely.

Confirmed: every tags list and filter in the frontend explicitly excludes non-custom tags — ChartList, DashboardList, SavedQueryList, the chart PropertiesModal, the dashboard Header, and features/tags/tags.ts's fetchAllTags/fetchTags all filter to TagType.custom only. Nothing in the UI ever surfaced a type:/editor:/favorited_by: tag or let a user search/filter by one — the docstring's own promise ("user alice can find all their objects by querying for the tag editor:alice") had no UI path to actually do that.

What remained was pure write-side overhead: with TAGGING_SYSTEM enabled, 13 SQLAlchemy event listeners across 5 models (chart/dashboard/query/dataset/favorite) fired on every insert/update/delete, writing Tag/TaggedObject rows nobody ever read. There was even a whole performance-optimization mixin (CustomTagsOptimizationMixin, DASHBOARD_LIST_CUSTOM_TAGS_ONLY) that existed purely to strip this noise back out of dashboard-list API responses — evidence this was a known cost nobody had gotten around to addressing at the source.

What this removes:

  • superset/tags/models.py: ObjectUpdater's editor:/type: generation (after_insert/after_update) and FavStarUpdater's favorited_by: generation, entirely.
  • superset/tags/core.py: only registers the delete-cleanup listeners now (see below).
  • superset/common/tags.py and the sync_tags CLI command: the backfill path for the generation this removes.
  • superset/views/custom_tags_api_mixin.py, DASHBOARD_LIST_CUSTOM_TAGS_ONLY, Dashboard.custom_tags, and the schema/API plumbing built around them: nothing left to optimize away once implicit tags stop accumulating.

What's kept, on purpose:

  • ObjectUpdater.after_delete — cleans up tagged_object rows for every tag on a deleted object, custom tags included. tagged_object.object_id carries no foreign key (see its column comment), so this is the only thing that prevents orphaned rows when a chart/dashboard/query/dataset is hard-deleted — not part of the removed generation, added a regression test for it (test_tagged_object_cleanup_on_dashboard_delete).
  • The TagType enum values, the custom_tag API filter, and bulk-delete protection for non-custom tags — for backward compatibility with upgraded deployments that already have type:/editor:/favorited_by: rows, and because MCP's list_tags/get_tag_info tools document and support filtering by these tag types. Docstrings updated to say these are legacy/no longer generated rather than actively implicit.

Unrelated but blocking: this branch also carries #43467 as its first commit — a genuinely broken import in superset/daos/tag.py from the just-merged #43390 (current_user_can_modify_object doesn't live in superset.commands.tag.utils) that otherwise breaks Flask app boot entirely and blocks every test in this area. Filed separately since it's unrelated; this branch will drop that commit on its own once #43467 merges and this rebases.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — internal cleanup, no UI changes (the UI never showed these tags to begin with).

TESTING INSTRUCTIONS

  • pytest tests/unit_tests/tags/ tests/unit_tests/commands/test_utils.py tests/unit_tests/initialization_test.py tests/unit_tests/dashboards/api_test.py — updated/removed tests for the removed generation and mixin.
  • pytest tests/integration_tests/tags/dao_tests.py::TestTagsDAO::test_tagged_object_cleanup_on_dashboard_delete — new regression test for the preserved delete-cleanup behavior.
  • Full pytest tests/unit_tests/ run: 13172 passed (the only failures are pre-existing, unrelated to this change — a missing optional pymysql dependency and a freezegun version quirk in files this PR doesn't touch).
  • Manual: with TAGGING_SYSTEM enabled, create/edit/delete a chart, dashboard, saved query, and dataset, and favorite/unfavorite one — confirm no type:/editor:/favorited_by: tags appear in the tag table anymore, while manually adding a custom tag and then deleting the tagged object still cleans up its tagged_object row.

ADDITIONAL INFORMATION

@bito-code-review

bito-code-review Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #cf379a

Actionable Suggestions - 0
Review Details
  • Files reviewed - 21 · Commit Range: d305cd9..009847e
    • superset/app.py
    • superset/cli/update.py
    • superset/common/tags.py
    • superset/config.py
    • superset/daos/tag.py
    • superset/dashboards/api.py
    • superset/dashboards/schemas.py
    • superset/mcp_service/tag/tool/get_tag_info.py
    • superset/mcp_service/tag/tool/list_tags.py
    • superset/models/dashboard.py
    • superset/tags/core.py
    • superset/tags/models.py
    • superset/views/custom_tags_api_mixin.py
    • tests/integration_tests/dashboards/api_tests.py
    • tests/integration_tests/superset_test_config.py
    • tests/integration_tests/tagging_tests.py
    • tests/integration_tests/tags/dao_tests.py
    • tests/integration_tests/tasks/async_queries_tests.py
    • tests/unit_tests/dashboards/api_test.py
    • tests/unit_tests/tags/commands/update_test.py
    • tests/unit_tests/views/test_custom_tags_api_mixin.py
  • Files skipped - 2
    • UPDATING.md - Reason: Filter setting
    • docs/static/resources/openapi.json - Reason: Filter setting
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@github-actions github-actions Bot added api Related to the REST API doc Namespace | Anything related to documentation preset-io labels Aug 24, 2026
@netlify

netlify Bot commented Aug 24, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit f638a55
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a8caeba60a9e300087c4673
😎 Deploy Preview https://deploy-preview-43471--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread superset/tags/core.py Outdated
@bito-code-review

Copy link
Copy Markdown
Contributor

The flagged issue regarding the non-idempotent registration of the SavedQuery listener is correct. Because sync_config_to_db() can be called multiple times, registering the listener directly leads to duplicate callbacks, which are not fully cleaned up by clear_sqla_event_listeners().

To resolve this, you should register and remove the SavedQuery listener using the same declaration-based helper used for other listeners. Since the relevant code is not fully visible in the provided diff, please ensure you update the registration logic in superset/app.py or the corresponding core tagging module to use the centralized register_sqla_event_listeners helper.

Regarding other comments on this PR, there are no additional review comments in the provided pr_comments.csv file.

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.47368% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.99%. Comparing base (ca3d767) to head (f638a55).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
superset/tags/core.py 85.71% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #43471      +/-   ##
==========================================
+ Coverage   78.96%   78.99%   +0.03%     
==========================================
  Files        2878     2876       -2     
  Lines      165183   164937     -246     
  Branches    38170    38156      -14     
==========================================
- Hits       130430   130298     -132     
+ Misses      32301    32190     -111     
+ Partials     2452     2449       -3     
Flag Coverage Δ
hive 38.06% <26.31%> (+0.04%) ⬆️
mysql 57.78% <89.47%> (+0.01%) ⬆️
postgres 57.81% <89.47%> (+0.01%) ⬆️
presto 39.99% <26.31%> (+0.05%) ⬆️
python 83.71% <89.47%> (+0.09%) ⬆️
sqlite 57.50% <89.47%> (+0.01%) ⬆️
unit 73.84% <26.31%> (+0.15%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

claude and others added 2 commits August 24, 2026 13:44
villebro noted on #43390 that these system-generated tags appear to be
unused. Confirmed: every tags list and filter in the frontend explicitly
excludes non-custom tags (ChartList, DashboardList, SavedQueryList, the
chart PropertiesModal, the dashboard Header), so nothing ever surfaced
them to a user. What remained was pure write-side overhead: 13
SQLAlchemy event listeners across 5 models firing on every chart/
dashboard/query/dataset save and every favorite/unfavorite, plus a whole
performance-optimization mixin (CustomTagsOptimizationMixin,
DASHBOARD_LIST_CUSTOM_TAGS_ONLY) that existed purely to strip the
resulting noise back out of dashboard-list responses.

This removes the generation:
- superset/tags/models.py: drop ObjectUpdater's editor:/type: generation
  (after_insert/after_update) and FavStarUpdater's favorited_by:
  generation entirely. Keeps after_delete (tagged_object cleanup applies
  to every tag, custom included, and nothing else removes those rows
  since tagged_object.object_id has no FK - see its column comment).
- superset/tags/core.py: only registers the delete-cleanup listeners now.
- superset/common/tags.py + the `sync_tags` CLI command: removed (the
  backfill path for the generation this removes).
- superset/views/custom_tags_api_mixin.py, DASHBOARD_LIST_CUSTOM_TAGS_ONLY,
  Dashboard.custom_tags, and the schema/API plumbing built around them:
  removed - nothing left to optimize away once implicit tags stop
  accumulating.

Kept for backward compatibility, since MCP's list_tags/get_tag_info tools
document these tag types and upgraded deployments may already have rows
of these types: the TagType enum values, the custom_tag API filter,
and bulk-delete protection for non-custom tags. Docstrings updated to
say these are legacy/no longer generated rather than actively implicit.

Also fixes a real, currently-broken import in superset/daos/tag.py
(current_user_can_modify_object doesn't live in
superset.commands.tag.utils, only in superset.commands.utils) that
otherwise blocks every test in this area from running at all. Filed and
fixed separately as #43467; this commit will collapse away on rebase
once that merges.

Follow-up to #43390.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Guard sqla.event.listen/remove for the SavedQuery after_delete listener
with sa.event.contains(), matching the pattern register_delete_listener
already uses, so repeated register_sqla_event_listeners() calls don't
stack duplicate cleanup callbacks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rusackas
rusackas force-pushed the chore/remove-implicit-tag-generation branch from 009847e to f638a55 Compare August 24, 2026 20:51
@bito-code-review

bito-code-review Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #c4c797

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/models/dashboard.py - 1
    • Dead code removal unverified · Line 194-203
      The diff removes `custom_tags` relationship (lines 194-203) but this code is absent from the current file. This indicates the PR base branch may be out of sync with target, or the change was already applied. Ensure the base branch contains the `custom_tags` definition before merging this removal.
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • tests/integration_tests/superset_test_config.py - 1
Review Details
  • Files reviewed - 19 · Commit Range: ae18388..f638a55
    • superset/app.py
    • superset/cli/update.py
    • superset/common/tags.py
    • superset/config.py
    • superset/dashboards/api.py
    • superset/dashboards/schemas.py
    • superset/mcp_service/tag/tool/get_tag_info.py
    • superset/mcp_service/tag/tool/list_tags.py
    • superset/models/dashboard.py
    • superset/tags/core.py
    • superset/tags/models.py
    • superset/views/custom_tags_api_mixin.py
    • tests/integration_tests/dashboards/api_tests.py
    • tests/integration_tests/superset_test_config.py
    • tests/integration_tests/tagging_tests.py
    • tests/integration_tests/tags/dao_tests.py
    • tests/integration_tests/tasks/async_queries_tests.py
    • tests/unit_tests/dashboards/api_test.py
    • tests/unit_tests/views/test_custom_tags_api_mixin.py
  • Files skipped - 2
    • UPDATING.md - Reason: Filter setting
    • docs/static/resources/openapi.json - Reason: Filter setting
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/tags/core.py
def register_sqla_event_listeners() -> None:
"""Register cleanup of ``tagged_object`` rows on object deletion.

Only deletion is handled here: Superset no longer auto-generates

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Upgrades retain existing editor: and favorited_by: associations as queryable rows, but this removes the update and favorite listeners that kept them current. Changing an asset's editors or unfavoriting it after upgrading therefore leaves tag lookups reporting relationships that no longer exist. Should we clear these legacy associations during upgrade or continue maintaining them while they remain queryable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API doc Namespace | Anything related to documentation preset-io size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants