Skip to content
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

Fix background callbacks & register page #2226

Merged
merged 7 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 4 additions & 0 deletions dash/_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from . import _validate
from ._utils import AttributeDict
from ._get_paths import get_relative_path
from ._callback_context import context_value


CONFIG = AttributeDict()
Expand Down Expand Up @@ -250,6 +251,9 @@ def register_page(
])
```
"""
if context_value.get().get("ignore_register_page"):
return

_validate.validate_use_pages(CONFIG)

page = dict(
Expand Down
5 changes: 3 additions & 2 deletions dash/_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .development.base_component import Component
from . import exceptions
from ._utils import patch_collections_abc, stringify_id, to_json, coerce_to_list
from .exceptions import PageError


def validate_callback(outputs, inputs, state, extra_args, types):
Expand Down Expand Up @@ -462,10 +463,10 @@ def validate_pages_layout(module, page):

def validate_use_pages(config):
if not config.get("assets_folder", None):
raise Exception("`dash.register_page()` must be called after app instantiation")
raise PageError("`dash.register_page()` must be called after app instantiation")

if flask.has_request_context():
raise Exception(
raise 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
Expand Down
2 changes: 2 additions & 0 deletions dash/dash.py
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,8 @@ def dispatch(self):
cb = self.callback_map[output]
func = cb["callback"]

g.ignore_register_page = cb.get("long", False)
alexcjohnson marked this conversation as resolved.
Show resolved Hide resolved

# Add args_grouping
inputs_state_indices = cb["inputs_state_indices"]
inputs_state = inputs + state
Expand Down
4 changes: 4 additions & 0 deletions dash/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,7 @@ class LongCallbackError(DashException):

class MissingLongCallbackManagerError(DashException):
pass


class PageError(DashException):
pass
17 changes: 17 additions & 0 deletions dash/testing/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from contextlib import contextmanager

from .._callback_context import context_value as _ctx
from .._utils import AttributeDict as _AD


@contextmanager
def ignore_register_page():
previous = _ctx.get()
copied = _AD(previous)
copied.ignore_register_page = True
_ctx.set(copied)

try:
yield
finally:
_ctx.set(previous)
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions tests/unit/test_testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from dash.testing import ignore_register_page
from dash import register_page


def test_tst001_ignore_register_page():
with ignore_register_page():
register_page("/")