content: import functools
  import os
  import sys
  import collections
  import inspect
  import importlib
  import warnings
  from contextvars import copy_context
  from importlib.machinery import ModuleSpec
  from importlib.util import find_spec
  from importlib import metadata
  import pkgutil
  import threading
  import re
  import logging
  import time
  import mimetypes
  import hashlib
  import base64
  import traceback
  from urllib.parse import urlparse
  from typing import Any, Callable, Dict, Optional, Union, Sequence, Literal, List
  
  import asyncio
  import flask
  
  from importlib_metadata import version as _get_distribution_version
  
  from dash import dcc
  from dash import html
  from dash import dash_table
  
  from .fingerprint import build_fingerprint, check_fingerprint
  from .resources import Scripts, Css
  from .dependencies import (
      Input,
      Output,
      State,
  )
  from .development.base_component import ComponentRegistry
  from .exceptions import (
      PreventUpdate,
      InvalidResourceError,
      ProxyError,
      DuplicateCallback,
  )
  from .version import __version__
  from ._configs import get_combined_config, pathname_configs, pages_folder_config
  from ._utils import (
      AttributeDict,
      format_tag,
      generate_hash,
      inputs_to_dict,
      inputs_to_vals,
      interpolate_str,
      patch_collections_abc,
      split_callback_id,
      to_json,
      convert_to_AttributeDict,
      gen_salt,
      hooks_to_js_object,
      parse_version,
      get_caller_name,
  )
  from . import _callback
  from . import _get_paths
  from . import _dash_renderer
  from . import _validate
  from . import _watch
  from . import _get_app
  
  from ._get_app import with_app_context, with_app_context_async, with_app_context_factory
  from ._grouping import map_grouping, grouping_len, update_args_group
  from ._obsolete import ObsoleteChecker
  
  from . import _pages
  from ._pages import (
      _parse_query_string,
      _page_meta_tags,
      _path_to_page,
      _import_layouts_from_pages,
  )
  from ._jupyter import jupyter_dash, JupyterDisplayMode
  from .types import RendererHooks
  
  RouteCallable = Callable[..., Any]
  
  # If dash_design_kit is installed, check for version
  ddk_version = None
  if find_spec("dash_design_kit"):
      ddk_version = metadata.version("dash_design_kit")
  
  plotly_version = None
  if find_spec("plotly"):
      plotly_version = metadata.version("plotly")
  
  # Add explicit mapping for map files
  mimetypes.add_type("application/json", ".map", True)
  
  _default_index = """<!DOCTYPE html>
  <html>
      <head>
          {%metas%}
          <title>{%title%}</title>
          {%favicon%}
          {%css%}
      </head>
      <body>
          <!--[if IE]><script>
          alert("Dash v2.7+ does not support Internet Explorer. Please use a newer browser.");
          </script><![endif]-->
          {%app_entry%}
          <footer>
              {%config%}
              {%scripts%}
              {%renderer%}
          </footer>
      </body>
  </html>"""
  
  _app_entry = """
  <div id="react-entry-point">
      <div class="_dash-loading">
          Loading...
      </div>
  </div>
  """
  
  _re_index_entry = "{%app_entry%}", "{%app_entry%}"
  _re_index_config = "{%config%}", "{%config%}"
  _re_index_scripts = "{%scripts%}", "{%scripts%}"
  
  _re_index_entry_id = 'id="react-entry-point"', "#react-entry-point"
  _re_index_config_id = 'id="_dash-config"', "#_dash-config"
  _re_index_scripts_id = 'src="[^"]*dash[-_]renderer[^"]*"', "dash-renderer"
  _re_renderer_scripts_id = 'id="_dash-renderer', "new DashRenderer"
  
  
  _ID_CONTENT = "_pages_content"
  _ID_LOCATION = "_pages_location"
  _ID_STORE = "_pages_store"
  _ID_DUMMY = "_pages_dummy"
  
  DASH_VERSION_URL = "https://dash-version.plotly.com:8080/current_version"
  
  # Handles the case in a newly cloned environment where the components are not yet generated.
  try:
      page_container = html.Div(  # type: ignore[operator]
          [
              dcc.Location(id=_ID_LOCATION, refresh="callback-nav"),  # type: ignore[operator]
              html.Div(id=_ID_CONTENT, disable_n_clicks=True),  # type: ignore[operator]
              dcc.Store(id=_ID_STORE),  # type: ignore[operator]
              html.Div(id=_ID_DUMMY, disable_n_clicks=True),  # type: ignore[operator]
          ]
      )
  # pylint: disable-next=bare-except
  except:  # noqa: E722
      page_container = None
  
  
  def _get_traceback(secret, error: Exception):
      try:
          # pylint: disable=import-outside-toplevel
          from werkzeug.debug import tbtools
      except ImportError:
          tbtools = None  # type: ignore[assignment]
  
      def _get_skip(error):
          from dash._callback import (  # pylint: disable=import-outside-toplevel
              _invoke_callback,
              _async_invoke_callback,
          )
  
          tb = error.__traceback__
          skip = 1
          while tb.tb_next is not None:
              skip += 1
              tb = tb.tb_next
              if tb.tb_frame.f_code in [
                  _invoke_callback.__code__,
                  _async_invoke_callback.__code__,
              ]:
                  return skip
  
          return skip
  
      def _do_skip(error):
          from dash._callback import (  # pylint: disable=import-outside-toplevel
              _invoke_callback,
              _async_invoke_callback,
          )
  
          tb = error.__traceback__
          while tb.tb_next is not None:
              if tb.tb_frame.f_code in [
                  _invoke_callback.__code__,
                  _async_invoke_callback.__code__,
              ]:
                  return tb.tb_next
              tb = tb.tb_next
          return error.__traceback__
  
      # werkzeug<2.1.0
      if hasattr(tbtools, "get_current_traceback"):
          return tbtools.get_current_traceback(  # type: ignore
              skip=_get_skip(error)
          ).render_full()
  
      if hasattr(tbtools, "DebugTraceback"):
          # pylint: disable=no-member
          return tbtools.DebugTraceback(  # type: ignore
              error, skip=_get_skip(error)
          ).render_debugger_html(True, secret, True)
  
      return "".join(traceback.format_exception(type(error), error, _do_skip(error)))
  
  
  # Singleton signal to not update an output, alternative to PreventUpdate
  no_update = _callback.NoUpdate()  # pylint: disable=protected-access
  
  
  async def execute_async_function(func, *args, **kwargs):
      # Check if the function is a coroutine function
      if inspect.iscoroutinefunction(func):
          return await func(*args, **kwargs)
      # If the function is not a coroutine, call it directly
      return func(*args, **kwargs)
  
  
  # pylint: disable=too-many-instance-attributes
  # pylint: disable=too-many-arguments, too-many-locals
  class Dash(ObsoleteChecker):
      """Dash is a framework for building analytical web applications.
      No JavaScript required.
  
      If a parameter can be set by an environment variable, that is listed as:
          env: ``DASH_****``
      Values provided here take precedence over environment variables.
  
      :param name: The name Flask should use for your app. Even if you provide
          your own ``server``, ``name`` will be used to help find assets.
          Typically ``__name__`` (the magic global var, not a string) is the
          best value to use. Default ``'__main__'``, env: ``DASH_APP_NAME``
      :type name: string
  
      :param server: Sets the Flask server for your app. There are three options:
          ``True`` (default): Dash will create a new server
          ``False``: The server will be added later via ``app.init_app(server)``
              where ``server`` is a ``flask.Flask`` instance.
          ``flask.Flask``: use this pre-existing Flask server.
      :type server: boolean or flask.Flask
  
      :param assets_folder: a path, relative to the current working directory,
          for extra files to be used in the browser. Default ``'assets'``.
          All .js and .css files will be loaded immediately unless excluded by
          ``assets_ignore``, and other files such as images will be served if
          requested.
      :type assets_folder: string
  
      :param pages_folder: a relative or absolute path for pages of a multi-page app.
          Default ``'pages'``.
      :type pages_folder: string or pathlib.Path
  
      :param use_pages: When True, the ``pages`` feature for multi-page apps is
          enabled. If you set a non-default ``pages_folder`` this will be inferred
          to be True. Default `None`.
      :type use_pages: boolean
  
      :param include_pages_meta: Include the page meta tags for twitter cards.
      :type include_pages_meta: bool
  
      :param assets_url_path: The local urls for assets will be:
          ``requests_pathname_prefix + assets_url_path + '/' + asset_path``
          where ``asset_path`` is the path to a file inside ``assets_folder``.
          Default ``'assets'``.
      :type asset_url_path: string
  
      :param assets_ignore: A regex, as a string to pass to ``re.compile``, for
          assets to omit from immediate loading. Ignored files will still be
          served if specifically requested. You cannot use this to prevent access
          to sensitive files.
      :type assets_ignore: string
  
      :param assets_path_ignore: A list of regex, each regex as a string to pass to ``re.compile``, for
          assets path to omit from immediate loading. The files in these ignored paths will still be
          served if specifically requested. You cannot use this to prevent access
          to sensitive files.
      :type assets_path_ignore: list of strings
  
      :param assets_external_path: an absolute URL from which to load assets.
          Use with ``serve_locally=False``. assets_external_path is joined
          with assets_url_path to determine the absolute url to the
          asset folder. Dash can still find js and css to automatically load
          if you also keep local copies in your assets folder that Dash can index,
          but external serving can improve performance and reduce load on
          the Dash server.
          env: ``DASH_ASSETS_EXTERNAL_PATH``
      :type assets_external_path: string
  
      :param include_assets_files: Default ``True``, set to ``False`` to prevent
          immediate loading of any assets. Assets will still be served if
          specifically requested. You cannot use this to prevent access
          to sensitive files. env: ``DASH_INCLUDE_ASSETS_FILES``
      :type include_assets_files: boolean
  
      :param url_base_pathname: A local URL prefix to use app-wide.
          Default ``'/'``. Both `requests_pathname_prefix` and
          `routes_pathname_prefix` default to `url_base_pathname`.
          env: ``DASH_URL_BASE_PATHNAME``
      :type url_base_pathname: string
  
      :param requests_pathname_prefix: A local URL prefix for file requests.
          Defaults to `url_base_pathname`, and must end with
          `routes_pathname_prefix`. env: ``DASH_REQUESTS_PATHNAME_PREFIX``
      :type requests_pathname_prefix: string
  
      :param routes_pathname_prefix: A local URL prefix for JSON requests.
          Defaults to ``url_base_pathname``, and must start and end
          with ``'/'``. env: ``DASH_ROUTES_PATHNAME_PREFIX``
      :type routes_pathname_prefix: string
  
      :param serve_locally: If ``True`` (default), assets and dependencies
          (Dash and Component js and css) will be served from local URLs.
          If ``False`` we will use CDN links where available.
      :type serve_locally: boolean
  
      :param compress: Use gzip to compress files and data served by Flask.
          To use this option, you need to install dash[compress]
          Default ``False``
      :type compress: boolean
  
      :param meta_tags: html <meta> tags to be added to the index page.
          Each dict should have the attributes and values for one tag, eg:
          ``{'name': 'description', 'content': 'My App'}``
      :type meta_tags: list of dicts
  
      :param index_string: Override the standard Dash index page.
          Must contain the correct insertion markers to interpolate various
          content into it depending on the app config and components used.
          See https://dash.plotly.com/external-resources for details.
      :type index_string: string
  
      :param external_scripts: Additional JS files to load with the page.
          Each entry can be a string (the URL) or a dict with ``src`` (the URL)
          and optionally other ``<script>`` tag attributes such as ``integrity``
          and ``crossorigin``.
      :type external_scripts: list of strings or dicts
  
      :param external_stylesheets: Additional CSS files to load with the page.
          Each entry can be a string (the URL) or a dict with ``href`` (the URL)
          and optionally other ``<link>`` tag attributes such as ``rel``,
          ``integrity`` and ``crossorigin``.
      :type external_stylesheets: list of strings or dicts
  
      :param suppress_callback_exceptions: Default ``False``: check callbacks to
          ensure referenced IDs exist and props are valid. Set to ``True``
          if your layout is dynamic, to bypass these checks.
          env: ``DASH_SUPPRESS_CALLBACK_EXCEPTIONS``
      :type suppress_callback_exceptions: boolean
  
      :param prevent_initial_callbacks: Default ``False``: Sets the default value
          of ``prevent_initial_call`` for all callbacks added to the app.
          Normally all callbacks are fired when the associated outputs are first
          added to the page. You can disable this for individual callbacks by
          setting ``prevent_initial_call`` in their definitions, or set it
          ``True`` here in which case you must explicitly set it ``False`` for
          those callbacks you wish to have an initial call. This setting has no
          effect on triggering callbacks when their inputs change later on.
  
      :param show_undo_redo: Default ``False``, set to ``True`` to enable undo
          and redo buttons for stepping through the history of the app state.
      :type show_undo_redo: boolean
  
      :param extra_hot_reload_paths: A list of paths to watch for changes, in
          addition to assets and known Python and JS code, if hot reloading is
          enabled.
      :type extra_hot_reload_paths: list of strings
  
      :param plugins: Extend Dash functionality by passing a list of objects
          with a ``plug`` method, taking a single argument: this app, which will
          be called after the Flask server is attached.
      :type plugins: list of objects
  
      :param title: Default ``Dash``. Configures the document.title
      (the text that appears in a browser tab).
  
      :param update_title: Default ``Updating...``. Configures the document.title
      (the text that appears in a browser tab) text when a callback is being run.
      Set to None or '' if you don't want the document.title to change or if you
      want to control the document.title through a separate component or
      clientside callback.
  
      :param background_callback_manager: Background callback manager instance
          to support the ``@callback(..., background=True)`` decorator.
          One of ``DiskcacheManager`` or ``CeleryManager`` currently supported.
  
      :param add_log_handler: Automatically add a StreamHandler to the app logger
          if not added previously.
  
      :param hooks: Extend Dash renderer functionality by passing a dictionary of
      javascript functions. To hook into the layout, use dict keys "layout_pre" and
      "layout_post". To hook into the callbacks, use keys "request_pre" and "request_post"
  
      :param routing_callback_inputs: When using Dash pages (use_pages=True), allows to
      add new States to the routing callback, to pass additional data to the layout
      functions. The syntax for this parameter is a dict of State objects:
      `routing_callback_inputs={"language": Input("language", "value")}`
      NOTE: the keys "pathname_" and "search_" are reserved for internal use.
  
      :param description:  Sets a default description for meta tags on Dash pages (use_pages=True).
  
      :param on_error: Global callback error handler to call when
          an exception is raised. Receives the exception object as first argument.
          The callback_context can be used to access the original callback inputs,
          states and output.
  
      :param use_async: When True, the app will create async endpoints, as a dev,
          they will be responsible for installing the `flask[async]` dependency.
      :type use_async: boolean
  
      :param health_endpoint: Path for the health check endpoint. Set to None to
          disable the health endpoint. Default is None.
      :type health_endpoint: string or None
      """
  
      _plotlyjs_url: str
      STARTUP_ROUTES: list = []
  
      server: flask.Flask
  
      # Layout is a complex type which can be many things
      _layout: Any
      _extra_components: Any
  
      def __init__(  # pylint: disable=too-many-statements
          self,
          name: Optional[str] = None,
          server: Union[bool, flask.Flask] = True,
          assets_folder: str = "assets",
          pages_folder: str = "pages",
          use_pages: Optional[bool] = None,
          assets_url_path: str = "assets",
          assets_ignore: str = "",
          assets_path_ignore: Optional[List[str]] = None,
          assets_external_path: Optional[str] = None,
          eager_loading: bool = False,
          include_assets_files: bool = True,
          include_pages_meta: bool = True,
          url_base_pathname: Optional[str] = None,
          requests_pathname_prefix: Optional[str] = None,
          routes_pathname_prefix: Optional[str] = None,
          serve_locally: bool = True,
          compress: Optional[bool] = None,
          meta_tags: Optional[Sequence[Dict[str, Any]]] = None,
          index_string: str = _default_index,
          external_scripts: Optional[Sequence[Union[str, Dict[str, Any]]]] = None,
          external_stylesheets: Optional[Sequence[Union[str, Dict[str, Any]]]] = None,
          suppress_callback_exceptions: Optional[bool] = None,
          prevent_initial_callbacks: bool = False,
          show_undo_redo: bool = False,
          extra_hot_reload_paths: Optional[Sequence[str]] = None,
          plugins: Optional[list] = None,
          title: str = "Dash",
          update_title: str = "Updating...",
          background_callback_manager: Optional[
              Any
          ] = None,  # Type should be specified if possible
          add_log_handler: bool = True,
          hooks: Optional[RendererHooks] = None,
          routing_callback_inputs: Optional[Dict[str, Union[Input, State]]] = None,
          description: Optional[str] = None,
          on_error: Optional[Callable[[Exception], Any]] = None,
          use_async: Optional[bool] = None,
          health_endpoint: Optional[str] = None,
          **obsolete,
      ):
  
          if use_async is None:
              try:
                  import asgiref  # type: ignore[import-not-found] # pylint: disable=unused-import, import-outside-toplevel # noqa
  
                  use_async = True
              except ImportError:
                  pass
          elif use_async:
              try:
                  import asgiref  # type: ignore[import-not-found] # pylint: disable=unused-import, import-outside-toplevel # noqa
              except ImportError as exc:
                  raise Exception(
                      "You are trying to use dash[async] without having installed the requirements please install via: `pip install dash[async]`"
                  ) from exc
  
          _validate.check_obsolete(obsolete)
  
          caller_name: str = name if name is not None else get_caller_name()
  
          # We have 3 cases: server is either True (we create the server), False
          # (defer server creation) or a Flask app instance (we use their server)
          if isinstance(server, flask.Flask):
              self.server = server
              if name is None:
                  caller_name = getattr(server, "name", caller_name)
          elif isinstance(server, bool):
              self.server = flask.Flask(caller_name) if server else None  # type: ignore
          else:
              raise ValueError("server must be a Flask app or a boolean")
  
          base_prefix, routes_prefix, requests_prefix = pathname_configs(
              url_base_pathname, routes_pathname_prefix, requests_pathname_prefix
          )
  
          self.config = AttributeDict(
              name=caller_name,
              assets_folder=os.path.join(
                  flask.helpers.get_root_path(caller_name), assets_folder
              ),  # type: ignore
              assets_url_path=assets_url_path,
              assets_ignore=assets_ignore,
              assets_path_ignore=assets_path_ignore,
              assets_external_path=get_combined_config(
                  "assets_external_path", assets_external_path, ""
              ),
              pages_folder=pages_folder_config(caller_name, pages_folder, use_pages),
              eager_loading=eager_loading,
              include_assets_files=get_combined_config(
                  "include_assets_files", include_assets_files, True
              ),
              url_base_pathname=base_prefix,
              routes_pathname_prefix=routes_prefix,
              requests_pathname_prefix=requests_prefix,
              serve_locally=serve_locally,
              compress=get_combined_config("compress", compress, False),
              meta_tags=meta_tags or [],
              external_scripts=external_scripts or [],
              external_stylesheets=external_stylesheets or [],
              suppress_callback_exceptions=get_combined_config(
                  "suppress_callback_exceptions", suppress_callback_exceptions, False
              ),
              prevent_initial_callbacks=prevent_initial_callbacks,
              show_undo_redo=show_undo_redo,
              extra_hot_reload_paths=extra_hot_reload_paths or [],
              title=title,
              update_title=update_title,
              include_pages_meta=include_pages_meta,
              description=description,
              health_endpoint=health_endpoint,
          )
          self.config.set_read_only(
              [
                  "name",
                  "assets_folder",
                  "assets_url_path",
                  "eager_loading",
                  "serve_locally",
                  "compress",
                  "pages_folder",
              ],
              "Read-only: can only be set in the Dash constructor",
          )
          self.config.finalize(
              "Invalid config key. Some settings are only available "
              "via the Dash constructor"
          )
  
          _get_paths.CONFIG = self.config
          _pages.CONFIG = self.config
  
          self.pages_folder = str(pages_folder)
          self.use_pages = (pages_folder != "pages") if use_pages is None else use_pages
          self.routing_callback_inputs = routing_callback_inputs or {}
  
          # keep title as a class property for backwards compatibility
          self.title = title
  
          # list of dependencies - this one is used by the back end for dispatching
          self.callback_map: dict = {}
          # same deps as a list to catch duplicate outputs, and to send to the front end
          self._callback_list: list = []
          self.callback_api_paths: dict = {}
  
          # list of inline scripts
          self._inline_scripts: list = []
  
          # index_string has special setter so can't go in config
          self._index_string: str = ""
          self.index_string = index_string
          self._favicon = None
  
          # default renderer string
          self.renderer = f"var renderer = new DashRenderer({hooks_to_js_object(hooks)});"
  
          # static files from the packages
          self.css = Css(serve_locally)
          self.scripts = Scripts(serve_locally, eager_loading)
  
          self.registered_paths: Any = collections.defaultdict(set)
  
          # urls
          self.routes: Any = []
  
          self._layout = None
          self._layout_is_function = False
          self.validation_layout = None
          self._on_error = on_error
          self._extra_components = []
          self._use_async = use_async
  
          self._setup_dev_tools()
          self._hot_reload = AttributeDict(
              hash=None,
              hard=False,
              lock=threading.RLock(),
              watch_thread=None,
              changed_assets=[],
          )
  
          self._assets_files: list = []
  
          self._background_manager = background_callback_manager
  
          self.logger = logging.getLogger(__name__)
  
          if not self.logger.handlers and add_log_handler:
              self.logger.addHandler(logging.StreamHandler(stream=sys.stdout))
  
          if plugins is not None and isinstance(
              plugins, patch_collections_abc("Iterable")
          ):
              for plugin in plugins:
                  plugin.plug(self)
  
          self._setup_hooks()
  
          # tracks internally if a function already handled at least one request.
          self._got_first_request = {"pages": False, "setup_server": False}
  
          if self.server is not None:
              self.init_app()
  
          self.logger.setLevel(logging.INFO)
  
          if self.__class__.__name__ == "JupyterDash":
              warnings.warn(
                  "JupyterDash is deprecated, use Dash instead.\n"
                  "See https://dash.plotly.com/dash-in-jupyter for more details."
              )
          self.setup_startup_routes()
  
          self._plotly_cloud = None
  
      def _setup_hooks(self):
          # pylint: disable=import-outside-toplevel,protected-access
          from ._hooks import HooksManager
  
          self._hooks = HooksManager
          self._hooks.register_setuptools()
  
          for setup in self._hooks.get_hooks("setup"):
              setup(self)
  
          for hook in self._hooks.get_hooks("callback"):
              callback_args, callback_kwargs = hook.data  # type: ignore
              self.callback(*callback_args, **callback_kwargs)(hook.func)
  
          for (
              clientside_function,
              args,
              kwargs,
          ) in self._hooks.hooks._clientside_callbacks:
              _callback.register_clientside_callback(
                  self._callback_list,
                  self.callback_map,
                  self.config.prevent_initial_callbacks,
                  self._inline_scripts,
                  clientside_function,
                  *args,
                  **kwargs,
              )
  
          if self._hooks.get_hooks("error"):
              self._on_error = self._hooks.HookErrorHandler(self._on_error)
  
      def init_app(self, app: Optional[flask.Flask] = None, **kwargs) -> None:
          """Initialize the parts of Dash that require a flask app."""
  
          config = self.config
  
          config.update(kwargs)
          config.set_read_only(
              [
                  "url_base_pathname",
                  "routes_pathname_prefix",
                  "requests_pathname_prefix",
              ],
              "Read-only: can only be set in the Dash constructor or during init_app()",
          )
  
          if app is not None:
              self.server = app
  
          bp_prefix = config.routes_pathname_prefix.replace("/", "_").replace(".", "_")
          assets_blueprint_name = f"{bp_prefix}dash_assets"
  
          self.server.register_blueprint(
              flask.Blueprint(
                  assets_blueprint_name,
                  config.name,
                  static_folder=self.config.assets_folder,
                  static_url_path=config.routes_pathname_prefix
                  + self.config.assets_url_path.lstrip("/"),
              )
          )
  
          if config.compress:
              try:
                  # pylint: disable=import-outside-toplevel
                  from flask_compress import Compress  # type: ignore
  
                  # gzip
                  Compress(self.server)
  
                  _flask_compress_version = parse_version(
                      _get_distribution_version("flask_compress")
                  )
  
                  if not hasattr(
                      self.server.config, "COMPRESS_ALGORITHM"
                  ) and _flask_compress_version >= parse_version("1.6.0"):
                      # flask-compress==1.6.0 changed default to ['br', 'gzip']
                      # and non-overridable default compression with Brotli is
                      # causing performance issues
                      self.server.config["COMPRESS_ALGORITHM"] = ["gzip"]
              except ImportError as error:
                  raise ImportError(
                      "To use the compress option, you need to install dash[compress]"
                  ) from error
  
          @self.server.errorhandler(PreventUpdate)
          def _handle_error(_):
              """Handle a halted callback and return an empty 204 response."""
              return "", 204
  
          self.server.before_request(self._setup_server)
  
          # add a handler for components suites errors to return 404
          self.server.errorhandler(InvalidResourceError)(self._invalid_resources_handler)
  
          self._setup_routes()
  
          _get_app.APP = self
          self.enable_pages()
  
          self._setup_plotlyjs()
  
      def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> None:
          full_name = self.config.routes_pathname_prefix + name
  
          self.server.add_url_rule(
              full_name, view_func=view_func, endpoint=full_name, methods=list(methods)
          )
  
          # record the url in Dash.routes so that it can be accessed later
          # e.g. for adding authentication with flask_login
          self.routes.append(full_name)
  
      def _setup_routes(self):
          self._add_url(
              "_dash-component-suites/<string:package_name>/<path:fingerprinted_path>",
              self.serve_component_suites,
          )
          self._add_url("_dash-layout", self.serve_layout)
          self._add_url("_dash-dependencies", self.dependencies)
          if self._use_async:
              self._add_url("_dash-update-component", self.async_dispatch, ["POST"])
          else:
              self._add_url("_dash-update-component", self.dispatch, ["POST"])
          self._add_url("_reload-hash", self.serve_reload_hash)
          self._add_url("_favicon.ico", self._serve_default_favicon)
          if self.config.health_endpoint is not None:
              self._add_url(self.config.health_endpoint, self.serve_health)
          self._add_url("", self.index)
  
          if jupyter_dash.active:
              self._add_url(
                  "_alive_" + jupyter_dash.alive_token, jupyter_dash.serve_alive
              )
  
          for hook in self._hooks.get_hooks("routes"):
              self._add_url(
                  hook.data["name"],
                  with_app_context_factory(hook.func, self),
                  hook.data["methods"],
              )
  
          # catch-all for front-end routes, used by dcc.Location
          self._add_url("<path:path>", self.index)
  
      def setup_apis(self):
          """
          Register API endpoints for all callbacks defined using `dash.callback`.
  
          This method must be called after all callbacks are registered and before the app is served.
          It ensures that all callback API routes are available for the Dash app to function correctly.
  
          Typical usage:
              app = Dash(__name__)
              # Register callbacks here
              app.setup_apis()
              app.run()
  
          If not called, callback endpoints will not be available and the app will not function as expected.
          """
          for k in list(_callback.GLOBAL_API_PATHS):
              if k in self.callback_api_paths:
                  raise DuplicateCallback(
                      f"The callback `{k}` provided with `dash.callback` was already "
                      "assigned with `app.callback`."
                  )
              self.callback_api_paths[k] = _callback.GLOBAL_API_PATHS.pop(k)
  
          def make_parse_body(func):
              def _parse_body():
                  if flask.request.is_json:
                      data = flask.request.get_json()
                      return flask.jsonify(func(**data))
                  return flask.jsonify({})
  
              return _parse_body
  
          def make_parse_body_async(func):
              async def _parse_body_async():
                  if flask.request.is_json:
                      data = flask.request.get_json()
                      result = await func(**data)
                      return flask.jsonify(result)
                  return flask.jsonify({})
  
              return _parse_body_async
  
          for path, func in self.callback_api_paths.items():
              if inspect.iscoroutinefunction(func):
                  self._add_url(path, make_parse_body_async(func), ["POST"])
              else:
                  self._add_url(path, make_parse_body(func), ["POST"])
  
      def _setup_plotlyjs(self):
          # pylint: disable=import-outside-toplevel
          from plotly.offline import get_plotlyjs_version  # type: ignore[import-untyped]
  
          url = f"https://cdn.plot.ly/plotly-{get_plotlyjs_version()}.min.js"
  
          # pylint: disable=protected-access
          dcc._js_dist.extend(
              [
                  {
                      "relative_package_path": "package_data/plotly.min.js",
                      "external_url": url,
                      "namespace": "plotly",
                      "async": "eager",
                  }
              ]
          )
          self._plotlyjs_url = url
  
      @property
      def layout(self) -> Any:
  