code: def upgrade(
      all_: bool,  # pylint: disable=unused-argument
      dashboard_ids: tuple[int, ...],
  ) -> None:
      """
      Upgrade legacy filter-box charts to native dashboard filters.
      """
  
      # pylint: disable=import-outside-toplevel
      from superset.utils.dashboard_filter_scopes_converter import (
          convert_filter_scopes_to_native_filters,
      )
  
      if not is_feature_enabled("DASHBOARD_NATIVE_FILTERS"):
          click.echo(
              "The 'DASHBOARD_NATIVE_FILTERS' feature needs to be enabled."
          )
          return
  
      # Mapping between the CHART- and MARKDOWN- IDs.
      mapping = {}
  
      for dashboard in (  # pylint: disable=too-many-nested-blocks
          db.session.query(Dashboard)
          .filter(
              *[Dashboard.id.in_(dashboard_ids)]
              if dashboard_ids
              else []
          )
          .all()
      ):
          click.echo(f"Upgrading {str(dashboard)}")
  
          try:
              json_metadata = json.loads(
                  dashboard.json_metadata or "{}"
              )
              position_json = json.loads(
                  dashboard.position_json or "{}"
              )
  
              if "native_filter_migration" in json_metadata:
                  click.echo(f"{dashboard} has already been upgraded")
                  continue
  
              # Save the native and legacy filter configurations for recovery purposes.
              json_metadata["native_filter_migration"] = {
                  key: deepcopy(json_metadata[key])
                  for key in (
                      "default_filters",
                      "filter_scopes",
                      "native_filter_configuration",
                  )
                  if key in json_metadata
              }
  
              filter_boxes_by_id = {
                  slc.id: slc
                  for slc in dashboard.slices
                  if slc.viz_type == "filter_box"
              }
  
              # Convert the legacy filter configurations to native filters.
              native_filter_configuration = json_metadata.setdefault(
                  "native_filter_configuration",
                  [],
              )
  
              native_filter_configuration.extend(
                  convert_filter_scopes_to_native_filters(
                      json_metadata,
                      position_json,
                      filter_boxes=list(filter_boxes_by_id.values()),
                  ),
              )
  
              # Remove the legacy filter configuration.
              for key in ["default_filters", "filter_scopes"]:
                  json_metadata.pop(key, None)
  
              # Replace the filter-box charts with markdown elements.
              for key, value in list(
                  position_json.items()
              ):  # Immutable iteration
                  if (
                      isinstance(value, dict)
                      and value["type"] == "CHART"
                      and (meta := value.get("meta"))
                      and meta["chartId"] in filter_boxes_by_id
                  ):
                      slc = filter_boxes_by_id[meta["chartId"]]
                      mapping[key] = key.replace("CHART-", "MARKDOWN-")
  
                      value["id"] = mapping[key]
                      value["type"] = "MARKDOWN"
  
                      meta["code"] = dedent(
                          f"""
                          &#9888; The <a href="/superset/slice/{slc.id}/">{slc.slice_name}
                          </a> filter-box chart has been migrated to a native filter.
  
                          This placeholder markdown element can be safely removed after
                          verifying that the native filter(s) have been correctly applied,
                          otherwise ask an admin to revert the migration.
                          """
                      )
  
                      # Save the filter-box info for recovery purposes.
                      meta["native_filter_migration"] = {
                          key: meta.pop(key)
                          for key in (
                              "chartId",
                              "sliceName",
                              "sliceNameOverride",
                          )
                          if key in meta
                      }
  
                      position_json[mapping[key]] = value
                      del position_json[key]
  
              # Replace the relevant CHART- references.
              for value in position_json.values():
                  if isinstance(value, dict):
                      for relation in ["children", "parents"]:
                          if relation in value:
                              for idx, key in enumerate(
                                  value[relation]
                              ):
                                  if key in mapping:
                                      value[relation][idx] = mapping[
                                          key
                                      ]
  
              # Remove the filter-box charts from the dashboard/slice mapping
              dashboard.slices = [
                  slc
                  for slc in dashboard.slices
                  if slc.viz_type != "filter_box"
              ]
  
              dashboard.json_metadata = json.dumps(json_metadata)
              dashboard.position_json = json.dumps(position_json)
          except Exception:  # pylint: disable=broad-except
              click.echo(f"Unable to upgrade {str(dashboard)}")
  
      db.session.commit()
      db.session.close()
  
file_path: superset/superset/cli/native_filters.py
imports: import json
  from copy import deepcopy
  from textwrap import dedent
  import click
  from click_option_group import optgroup, RequiredMutuallyExclusiveOptionGroup
  from flask.cli import with_appcontext
  from sqlalchemy import Column, ForeignKey, Integer, String, Table, Text
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import relationship
  from superset import db, is_feature_enabled
label_desc: Use image node_id 2 for calling a global function with example usage: upgrade(all_, dashboard_ids) without return types