Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions dash/_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
BackgroundCallbackError,
ImportedInsideCallbackError,
)

from ._get_app import get_app
from ._grouping import (
flatten_grouping,
make_grouping_by_index,
Expand All @@ -39,7 +39,6 @@
from ._callback_context import context_value
from ._no_update import NoUpdate
from . import _validate
from . import backends


async def _async_invoke_callback(
Expand Down Expand Up @@ -373,7 +372,7 @@ def _get_callback_manager(
" and store results on redis.\n"
)

adapter = backends.backend.request_adapter()
adapter = get_app().backend.request_adapter()
old_job = adapter.args.getlist("oldJob") if hasattr(adapter.args, "getlist") else []

if old_job:
Expand Down Expand Up @@ -433,7 +432,7 @@ def _setup_background_callback(

def _progress_background_callback(response, callback_manager, background):
progress_outputs = background.get("progress")
adapter = backends.backend.request_adapter()
adapter = get_app().backend.request_adapter()
cache_key = adapter.args.get("cacheKey")

if progress_outputs:
Expand All @@ -451,7 +450,7 @@ def _update_background_callback(
"""Set up the background callback and manage jobs."""
callback_manager = _get_callback_manager(kwargs, background)

adapter = backends.backend.request_adapter()
adapter = get_app().backend.request_adapter()
cache_key = adapter.args.get("cacheKey") if adapter else None
job_id = adapter.args.get("job") if adapter else None

Expand All @@ -473,7 +472,7 @@ def _handle_rest_background_callback(
multi,
has_update=False,
):
adapter = backends.backend.request_adapter()
adapter = get_app().backend.request_adapter()
cache_key = adapter.args.get("cacheKey") if adapter else None
job_id = adapter.args.get("job") if adapter else None
# Must get job_running after get_result since get_results terminates it.
Expand Down Expand Up @@ -691,7 +690,7 @@ def add_context(*args, **kwargs):
jsonResponse: Optional[str] = None
try:
if background is not None:
adapter = backends.backend.request_adapter()
adapter = get_app().backend.request_adapter()
if not (adapter and adapter.args.get("cacheKey")):
return _setup_background_callback(
kwargs,
Expand Down Expand Up @@ -763,7 +762,7 @@ async def async_add_context(*args, **kwargs):

try:
if background is not None:
adapter = backends.backend.request_adapter()
adapter = get_app().backend.request_adapter()
if not (adapter and adapter.args.get("cacheKey")):
return _setup_background_callback(
kwargs,
Expand Down
6 changes: 3 additions & 3 deletions dash/_callback_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import typing

from . import exceptions
from . import backends
from ._get_app import get_app
from ._utils import AttributeDict, stringify_id


Expand Down Expand Up @@ -221,7 +221,7 @@ def record_timing(name, duration, description=None):
:param description: A description of the resource.
:type description: string or None
"""
request = backends.backend.request_adapter()
request = get_app().backend.request_adapter()
timing_information = getattr(request.context, "timing_information", {})

if name in timing_information:
Expand Down Expand Up @@ -252,7 +252,7 @@ def using_outputs_grouping(self):
@property
@has_context
def timing_information(self):
request = backends.backend.request_adapter()
request = get_app().backend.request_adapter()
return getattr(request.context, "timing_information", {})

@has_context
Expand Down
4 changes: 3 additions & 1 deletion dash/_get_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from textwrap import dedent
from typing import Any, Optional

from dash.exceptions import AppNotFoundError

APP: Optional[Any] = None

app_context: ContextVar[Any] = ContextVar("dash_app_context")
Expand Down Expand Up @@ -55,7 +57,7 @@ def get_app():
pass

if APP is None:
raise Exception(
raise AppNotFoundError(
dedent(
"""
App object is not yet defined. `app = dash.Dash()` needs to be run
Expand Down
19 changes: 12 additions & 7 deletions dash/_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .development.base_component import Component
from . import backends
from . import exceptions
from ._get_app import get_app
from ._utils import (
patch_collections_abc,
stringify_id,
Expand Down Expand Up @@ -510,13 +511,17 @@ def validate_use_pages(config):
"`dash.register_page()` must be called after app instantiation"
)

if backends.backend.has_request_context():
raise exceptions.PageError(
"""
dash.register_page() can’t be called within a callback as it updates dash.page_registry, which is a global variable.
For more details, see https://dash.plotly.com/sharing-data-between-callbacks#why-global-variables-will-break-your-app
"""
)
try:
if get_app().backend.has_request_context():
raise exceptions.PageError(
"""
dash.register_page() can’t be called within a callback as it updates dash.page_registry, which is a global variable.
For more details, see https://dash.plotly.com/sharing-data-between-callbacks#why-global-variables-will-break-your-app
"""
)
except exceptions.AppNotFoundError:
# If the app is not found we can add pages since before instantiation.
pass


def validate_module_name(module):
Expand Down
4 changes: 0 additions & 4 deletions dash/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
from .base_server import BaseDashServer


backend: BaseDashServer


_backend_imports = {
"flask": ("dash.backends._flask", "FlaskDashServer"),
"fastapi": ("dash.backends._fastapi", "FastAPIDashServer"),
Expand Down Expand Up @@ -74,6 +71,5 @@ def get_server_type(server):

__all__ = [
"get_backend",
"backend",
"get_server_type",
]
11 changes: 4 additions & 7 deletions dash/dash.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,14 +501,10 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches

self.backend = backend_cls(server)
self.server = server
backends.backend = self.backend # type: ignore
backends.request_adapter = self.backend.request_adapter # type: ignore
else:
# No server instance provided, create backend and let backend create server
self.server = backend_cls.create_app(caller_name) # type: ignore
self.backend = backend_cls(self.server)
backends.backend = self.backend
backends.request_adapter = self.backend.request_adapter # type: ignore

base_prefix, routes_prefix, requests_prefix = pathname_configs(
url_base_pathname, routes_pathname_prefix, requests_pathname_prefix
Expand Down Expand Up @@ -641,6 +637,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches
self._got_first_request = {"pages": False, "setup_server": False}

if server:
print(f"init app from server {server}")
self.init_app()

self.logger.setLevel(logging.INFO)
Expand Down Expand Up @@ -1179,7 +1176,7 @@ def index(self, *_args, **_kwargs):
renderer = self._generate_renderer()
title = self.title
# Refactored: direct access to global request adapter
request = backends.backend.request_adapter()
request = self.backend.request_adapter()

if self.use_pages and self.config.include_pages_meta and request:
metas = _page_meta_tags(self, request) + metas
Expand Down Expand Up @@ -1395,7 +1392,7 @@ def _inputs_to_vals(self, inputs):
# pylint: disable=R0915
def _initialize_context(self, body):
"""Initialize the global context for the request."""
adapter = backends.backend.request_adapter()
adapter = self.backend.request_adapter()
g = AttributeDict({})
g.inputs_list = body.get("inputs", [])
g.states_list = body.get("state", [])
Expand Down Expand Up @@ -2382,7 +2379,7 @@ def verify_url_part(served_part, url_part, part_name):
server_url=jupyter_server_url,
)
else:
backends.backend.run(
self.backend.run(
dash_app=self, host=host, port=port, debug=debug, **flask_run_options
)

Expand Down
4 changes: 4 additions & 0 deletions dash/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,7 @@ class ImportedInsideCallbackError(DashException):

class HookError(DashException):
pass


class AppNotFoundError(DashException):
pass
Loading