diff --git a/components/dash-core-components/src/components/LogoutButton.react.js b/components/dash-core-components/src/components/LogoutButton.react.js deleted file mode 100644 index b9c1e4d1d8..0000000000 --- a/components/dash-core-components/src/components/LogoutButton.react.js +++ /dev/null @@ -1,120 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import './css/logout.css'; - -/** - * Logout button to submit a form post request to the `logout_url` prop. - * Usage is intended for dash-deployment-server authentication. - * - * DDS usage: - * - * `dcc.LogoutButton(logout_url=os.getenv('DASH_LOGOUT_URL'))` - * - * Custom usage: - * - * - Implement a login mechanism. - * - Create a flask route with a post method handler. - * `@app.server.route('/logout', methods=['POST'])` - * - The logout route should perform what's necessary for the user to logout. - * - If you store the session in a cookie, clear the cookie: - * `rep = flask.Response(); rep.set_cookie('session', '', expires=0)` - * - * - Create a logout button component and assign it the logout_url - * `dcc.LogoutButton(logout_url='/logout')` - * - * See https://dash.plotly.com/dash-core-components/logout_button - * for more documentation and examples. - */ -export default class LogoutButton extends React.Component { - render() { - const {id, logout_url, label, className, style, method, loading_state} = - this.props; - - let url, submitMethod; - if (!logout_url) { - url = - logout_url || - 'https://dash.plotly.com/dash-core-components/logout_button'; - submitMethod = 'get'; - } else { - url = logout_url; - submitMethod = method; - } - - return ( -
- -
- ); - } -} - -LogoutButton.defaultProps = { - label: 'Logout', - method: 'post', -}; - -LogoutButton.propTypes = { - /** - * Id of the button. - */ - id: PropTypes.string, - - /** - * Text of the button - */ - label: PropTypes.string, - /** - * Url to submit a post logout request. - */ - logout_url: PropTypes.string, - /** - * Style of the button - */ - style: PropTypes.object, - /** - * Http method to submit the logout form. - */ - method: PropTypes.string, - /** - * CSS class for the button. - */ - className: PropTypes.string, - /** - * Dash-assigned callback that gets fired when the value changes. - */ - setProps: PropTypes.func, - - /** - * Object that holds the loading state object coming from dash-renderer - */ - loading_state: PropTypes.shape({ - /** - * Determines if the component is loading or not - */ - is_loading: PropTypes.bool, - /** - * Holds which property is loading - */ - prop_name: PropTypes.string, - /** - * Holds the name of the component that is loading - */ - component_name: PropTypes.string, - }), -}; diff --git a/components/dash-core-components/src/components/css/logout.css b/components/dash-core-components/src/components/css/logout.css deleted file mode 100644 index bc2ab2b1aa..0000000000 --- a/components/dash-core-components/src/components/css/logout.css +++ /dev/null @@ -1,20 +0,0 @@ -.dash-logout-btn { - padding: 1rem; - background-color: #119DFF; - border: 1px solid #119DFF; - color: #ffffff; - outline: none; - cursor: pointer; - text-align: center; -} - -.dash-logout-btn:hover, .dash-logout-btn:focus { - background-color: #0d76bf; - border: 1px solid #0d76bf; -} - -.dash-logout-frame { - display: block; - padding: 0; - margin: 0; -} diff --git a/components/dash-core-components/src/index.js b/components/dash-core-components/src/index.js index d2e70c7755..f696898fc1 100644 --- a/components/dash-core-components/src/index.js +++ b/components/dash-core-components/src/index.js @@ -14,7 +14,6 @@ import Interval from './components/Interval.react'; import Link from './components/Link.react'; import Loading from './components/Loading.react'; import Location from './components/Location.react'; -import LogoutButton from './components/LogoutButton.react'; import Markdown from './components/Markdown.react'; import RadioItems from './components/RadioItems.react'; import RangeSlider from './components/RangeSlider.react'; @@ -45,7 +44,6 @@ export { Link, Loading, Location, - LogoutButton, Markdown, RadioItems, RangeSlider, diff --git a/components/dash-core-components/tests/integration/location/test_location_logout.py b/components/dash-core-components/tests/integration/location/test_location_logout.py deleted file mode 100644 index 12ceda2a35..0000000000 --- a/components/dash-core-components/tests/integration/location/test_location_logout.py +++ /dev/null @@ -1,30 +0,0 @@ -from dash import Dash, Input, Output, dcc, html -import pytest -import time - - -@pytest.mark.parametrize("add_initial_logout_button", [False, True]) -def test_llgo001_location_logout(dash_dcc, add_initial_logout_button): - # FIXME: Logout button is deprecated, remove this test for dash 3.0 - app = Dash(__name__) - - with pytest.warns( - DeprecationWarning, - match="The Logout Button is no longer used with Dash Enterprise and can be replaced with a html.Button or html.A.", - ): - app.layout = [ - html.H2("Logout test"), - html.Div(id="content"), - ] - if add_initial_logout_button: - app.layout.append(dcc.LogoutButton()) - else: - - @app.callback(Output("content", "children"), Input("content", "id")) - def on_location(location_path): - return dcc.LogoutButton(id="logout-btn", logout_url="/_logout") - - dash_dcc.start_server(app) - time.sleep(1) - - assert dash_dcc.get_logs() == [] diff --git a/components/dash-table/README.md b/components/dash-table/README.md index 2a4f3237a8..8275ff0ed1 100644 --- a/components/dash-table/README.md +++ b/components/dash-table/README.md @@ -25,7 +25,7 @@ app.layout = dash_table.DataTable( ) if __name__ == '__main__': - app.run_server(debug=True) + app.run(debug=True) ``` ![Interactive Dash DataTable](https://user-images.githubusercontent.com/1280389/47935912-67187080-deb2-11e8-8936-34b0c99b518f.png) diff --git a/dash/__init__.py b/dash/__init__.py index 39ed65c539..2c8542a6b5 100644 --- a/dash/__init__.py +++ b/dash/__init__.py @@ -26,7 +26,7 @@ get_relative_path, strip_relative_path, ) -from .long_callback import ( # noqa: F401,E402 +from .background_callback import ( # noqa: F401,E402 CeleryManager, DiskcacheManager, ) diff --git a/dash/_callback.py b/dash/_callback.py index 8524f97e5b..d9bae3d6ec 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -20,7 +20,7 @@ PreventUpdate, WildcardInLongCallback, MissingLongCallbackManagerError, - LongCallbackError, + BackgroundCallbackError, ImportedInsideCallbackError, ) @@ -39,7 +39,7 @@ ) from . import _validate -from .long_callback.managers import BaseLongCallbackManager +from .background_callback.managers import BaseBackgroundCallbackManager from ._callback_context import context_value @@ -72,7 +72,7 @@ def callback( progress_default: Any = None, running: Optional[List[Tuple[Output, Any, Any]]] = None, cancel: Optional[List[Input]] = None, - manager: Optional[BaseLongCallbackManager] = None, + manager: Optional[BaseBackgroundCallbackManager] = None, cache_args_to_ignore: Optional[list] = None, on_error: Optional[Callable[[Exception], Any]] = None, **_kwargs, @@ -96,11 +96,11 @@ def callback( :Keyword Arguments: :param background: - Mark the callback as a long callback to execute in a manager for + Mark the callback as a background callback to execute in a manager for callbacks that take a long time without locking up the Dash app or timing out. :param manager: - A long callback manager instance. Currently, an instance of one of + A background callback manager instance. Currently, an instance of one of `DiskcacheManager` or `CeleryManager`. Defaults to the `background_callback_manager` instance provided to the `dash.Dash constructor`. @@ -144,14 +144,14 @@ def callback( this should be a list of argument names as strings. Otherwise, this should be a list of argument indices as integers. :param interval: - Time to wait between the long callback update requests. + Time to wait between the background callback update requests. :param on_error: Function to call when the callback raises an exception. Receives the exception object as first argument. The callback_context can be used to access the original callback inputs, states and output. """ - long_spec = None + background_spec = None config_prevent_initial_callbacks = _kwargs.pop( "config_prevent_initial_callbacks", False @@ -160,34 +160,36 @@ def callback( callback_list = _kwargs.pop("callback_list", GLOBAL_CALLBACK_LIST) if background: - long_spec: Any = { + background_spec: Any = { "interval": interval, } if manager: - long_spec["manager"] = manager + background_spec["manager"] = manager if progress: - long_spec["progress"] = coerce_to_list(progress) - validate_long_inputs(long_spec["progress"]) + background_spec["progress"] = coerce_to_list(progress) + validate_background_inputs(background_spec["progress"]) if progress_default: - long_spec["progressDefault"] = coerce_to_list(progress_default) + background_spec["progressDefault"] = coerce_to_list(progress_default) - if not len(long_spec["progress"]) == len(long_spec["progressDefault"]): + if not len(background_spec["progress"]) == len( + background_spec["progressDefault"] + ): raise Exception( "Progress and progress default needs to be of same length" ) if cancel: cancel_inputs = coerce_to_list(cancel) - validate_long_inputs(cancel_inputs) + validate_background_inputs(cancel_inputs) - long_spec["cancel"] = [c.to_dict() for c in cancel_inputs] - long_spec["cancel_inputs"] = cancel_inputs + background_spec["cancel"] = [c.to_dict() for c in cancel_inputs] + background_spec["cancel_inputs"] = cancel_inputs if cache_args_to_ignore: - long_spec["cache_args_to_ignore"] = cache_args_to_ignore + background_spec["cache_args_to_ignore"] = cache_args_to_ignore return register_callback( callback_list, @@ -195,19 +197,19 @@ def callback( config_prevent_initial_callbacks, *_args, **_kwargs, - long=long_spec, + background=background_spec, manager=manager, running=running, on_error=on_error, ) -def validate_long_inputs(deps): +def validate_background_inputs(deps): for dep in deps: if dep.has_wildcard(): raise WildcardInLongCallback( f""" - long callbacks does not support dependencies with + background callbacks does not support dependencies with pattern-matching ids Received: {repr(dep)}\n""" ) @@ -239,7 +241,7 @@ def insert_callback( state, inputs_state_indices, prevent_initial_call, - long=None, + background=None, manager=None, running=None, dynamic_creator: Optional[bool] = False, @@ -261,9 +263,9 @@ def insert_callback( # prevent_initial_call can be a string "initial_duplicates" # which should not prevent the initial call. "prevent_initial_call": prevent_initial_call is True, - "long": long + "background": background and { - "interval": long["interval"], + "interval": background["interval"], }, "dynamic_creator": dynamic_creator, "no_output": no_output, @@ -276,7 +278,7 @@ def insert_callback( "state": callback_spec["state"], "outputs_indices": outputs_indices, "inputs_state_indices": inputs_state_indices, - "long": long, + "background": background, "output": output, "raw_inputs": inputs, "manager": manager, @@ -318,7 +320,7 @@ def register_callback( multi = True has_output = len(output) > 0 - long = _kwargs.get("long") + background = _kwargs.get("background") manager = _kwargs.get("manager") running = _kwargs.get("running") on_error = _kwargs.get("on_error") @@ -342,7 +344,7 @@ def register_callback( flat_state, inputs_state_indices, prevent_initial_call, - long=long, + background=background, manager=manager, dynamic_creator=allow_dynamic_callbacks, running=running, @@ -352,23 +354,25 @@ def register_callback( # pylint: disable=too-many-locals def wrap_func(func): - if long is not None: - long_key = BaseLongCallbackManager.register_func( + if background is not None: + background_key = BaseBackgroundCallbackManager.register_func( func, - long.get("progress") is not None, + background.get("progress") is not None, callback_id, ) @wraps(func) def add_context(*args, **kwargs): output_spec = kwargs.pop("outputs_list") - app_callback_manager = kwargs.pop("long_callback_manager", None) + app_callback_manager = kwargs.pop("background_callback_manager", None) callback_ctx = kwargs.pop( "callback_context", AttributeDict({"updated_props": {}}) ) app = kwargs.pop("app", None) - callback_manager = long and long.get("manager", app_callback_manager) + callback_manager = background and background.get( + "manager", app_callback_manager + ) error_handler = on_error or kwargs.pop("app_on_error", None) original_packages = set(ComponentRegistry.registry) @@ -384,10 +388,10 @@ def add_context(*args, **kwargs): response: dict = {"multi": True} has_update = False - if long is not None: + if background is not None: if not callback_manager: raise MissingLongCallbackManagerError( - "Running `long` callbacks requires a manager to be installed.\n" + "Running `background` callbacks requires a manager to be installed.\n" "Available managers:\n" "- Diskcache (`pip install dash[diskcache]`) to run callbacks in a separate Process" " and store results on the local filesystem.\n" @@ -395,7 +399,7 @@ def add_context(*args, **kwargs): " and store results on redis.\n" ) - progress_outputs = long.get("progress") + progress_outputs = background.get("progress") cache_key = flask.request.args.get("cacheKey") job_id = flask.request.args.get("job") old_job = flask.request.args.getlist("oldJob") @@ -404,7 +408,7 @@ def add_context(*args, **kwargs): func, # Inputs provided as dict is kwargs. func_args if func_args else func_kwargs, - long.get("cache_args_to_ignore", []), + background.get("cache_args_to_ignore", []), ) if old_job: @@ -414,7 +418,7 @@ def add_context(*args, **kwargs): if not cache_key: cache_key = current_key - job_fn = callback_manager.func_registry.get(long_key) + job_fn = callback_manager.func_registry.get(background_key) ctx_value = AttributeDict(**context_value.get()) ctx_value.ignore_register_page = True @@ -433,11 +437,11 @@ def add_context(*args, **kwargs): "job": job, } - cancel = long.get("cancel") + cancel = background.get("cancel") if cancel: data["cancel"] = cancel - progress_default = long.get("progressDefault") + progress_default = background.get("progressDefault") if progress_default: data["progressDefault"] = { str(o): x @@ -461,11 +465,11 @@ def add_context(*args, **kwargs): elif ( isinstance(output_value, dict) - and "long_callback_error" in output_value + and "background_callback_error" in output_value ): - error = output_value.get("long_callback_error", {}) - exc = LongCallbackError( - f"An error occurred inside a long callback: {error['msg']}\n{error['tb']}" + error = output_value.get("background_callback_error", {}) + exc = BackgroundCallbackError( + f"An error occurred inside a background callback: {error['msg']}\n{error['tb']}" ) if error_handler: output_value = error_handler(exc) @@ -555,7 +559,7 @@ def add_context(*args, **kwargs): output_value = [] flat_output_values = [] - if not long: + if not background: has_update = _set_side_update(callback_ctx, response) or has_update if not has_update: diff --git a/dash/_jupyter.py b/dash/_jupyter.py index 5037742a87..b791d2e2e0 100644 --- a/dash/_jupyter.py +++ b/dash/_jupyter.py @@ -382,7 +382,7 @@ def wait_for_app(): url = f"http://{host}:{port}" raise OSError( f"Address '{url}' already in use.\n" - " Try passing a different port to run_server." + " Try passing a different port to run." ) except requests.ConnectionError as err: _get_error() diff --git a/dash/_validate.py b/dash/_validate.py index a26fd0f73b..0922c276ea 100644 --- a/dash/_validate.py +++ b/dash/_validate.py @@ -364,6 +364,10 @@ def check_obsolete(kwargs): file=sys.stderr, ) continue + if key in ["long_callback_manager"]: + raise exceptions.ObsoleteKwargException( + "long_callback_manager is obsolete, use background_callback_manager instead" + ) # any other kwarg mimic the built-in exception raise TypeError(f"Dash() got an unexpected keyword argument '{key}'") @@ -413,7 +417,7 @@ def validate_layout(layout, layout_value): if layout is None: raise exceptions.NoLayoutException( """ - The layout was `None` at the time that `run_server` was called. + The layout was `None` at the time that `run` was called. Make sure to set the `layout` attribute of your application before running the server. """ @@ -522,9 +526,9 @@ def validate_module_name(module): return module -def validate_long_callbacks(callback_map): - # Validate that long callback side output & inputs are not circular - # If circular, triggering a long callback would result in a fatal server/computer crash. +def validate_background_callbacks(callback_map): + # Validate that background callback side output & inputs are not circular + # If circular, triggering a background callback would result in a fatal server/computer crash. all_outputs = set() input_indexed = {} for callback in callback_map.values(): @@ -534,22 +538,22 @@ def validate_long_callbacks(callback_map): input_indexed.setdefault(o, set()) input_indexed[o].update(coerce_to_list(callback["raw_inputs"])) - for callback in (x for x in callback_map.values() if x.get("long")): - long_info = callback["long"] - progress = long_info.get("progress", []) - running = long_info.get("running", []) + for callback in (x for x in callback_map.values() if x.get("background")): + bg_info = callback["background"] + progress = bg_info.get("progress", []) + running = bg_info.get("running", []) - long_inputs = coerce_to_list(callback["raw_inputs"]) + bg_inputs = coerce_to_list(callback["raw_inputs"]) outputs = set([x[0] for x in running] + progress) circular = [ x for x in set(k for k, v in input_indexed.items() if v.intersection(outputs)) - if x in long_inputs + if x in bg_inputs ] if circular: - raise exceptions.LongCallbackError( - f"Long callback circular error!\n{circular} is used as input for a long callback" + raise exceptions.BackgroundCallbackError( + f"Background callback circular error!\n{circular} is used as input for a background callback" f" but also used as output from an input that is updated with progress or running argument." ) diff --git a/dash/long_callback/__init__.py b/dash/background_callback/__init__.py similarity index 71% rename from dash/long_callback/__init__.py rename to dash/background_callback/__init__.py index d89324f749..e4c6c3594d 100644 --- a/dash/long_callback/__init__.py +++ b/dash/background_callback/__init__.py @@ -1,8 +1,6 @@ from .managers.celery_manager import ( # noqa: F401,E402 - CeleryLongCallbackManager, CeleryManager, ) from .managers.diskcache_manager import ( # noqa: F401,E402 - DiskcacheLongCallbackManager, DiskcacheManager, ) diff --git a/dash/long_callback/_proxy_set_props.py b/dash/background_callback/_proxy_set_props.py similarity index 100% rename from dash/long_callback/_proxy_set_props.py rename to dash/background_callback/_proxy_set_props.py diff --git a/dash/long_callback/managers/__init__.py b/dash/background_callback/managers/__init__.py similarity index 91% rename from dash/long_callback/managers/__init__.py rename to dash/background_callback/managers/__init__.py index 5bfdc837bc..f8a9068a4b 100644 --- a/dash/long_callback/managers/__init__.py +++ b/dash/background_callback/managers/__init__.py @@ -3,7 +3,7 @@ import hashlib -class BaseLongCallbackManager(ABC): +class BaseBackgroundCallbackManager(ABC): UNDEFINED = object() # Keep a ref to all the ref to register every callback to every manager. @@ -18,7 +18,7 @@ def __init__(self, cache_by): self.cache_by = cache_by - BaseLongCallbackManager.managers.append(self) + BaseBackgroundCallbackManager.managers.append(self) self.func_registry = {} @@ -83,8 +83,8 @@ def register(self, key, fn, progress): @staticmethod def register_func(fn, progress, callback_id): - key = BaseLongCallbackManager.hash_function(fn, callback_id) - BaseLongCallbackManager.functions.append( + key = BaseBackgroundCallbackManager.hash_function(fn, callback_id) + BaseBackgroundCallbackManager.functions.append( ( key, fn, @@ -92,7 +92,7 @@ def register_func(fn, progress, callback_id): ) ) - for manager in BaseLongCallbackManager.managers: + for manager in BaseBackgroundCallbackManager.managers: manager.register(key, fn, progress) return key diff --git a/dash/long_callback/managers/celery_manager.py b/dash/background_callback/managers/celery_manager.py similarity index 95% rename from dash/long_callback/managers/celery_manager.py rename to dash/background_callback/managers/celery_manager.py index 612cc245fb..9e1cb83543 100644 --- a/dash/long_callback/managers/celery_manager.py +++ b/dash/background_callback/managers/celery_manager.py @@ -7,11 +7,11 @@ from dash._callback_context import context_value from dash._utils import AttributeDict from dash.exceptions import PreventUpdate -from dash.long_callback._proxy_set_props import ProxySetProps -from dash.long_callback.managers import BaseLongCallbackManager +from dash.background_callback._proxy_set_props import ProxySetProps +from dash.background_callback.managers import BaseBackgroundCallbackManager -class CeleryManager(BaseLongCallbackManager): +class CeleryManager(BaseBackgroundCallbackManager): """Manage background execution of callbacks with a celery queue.""" def __init__(self, celery_app, cache_by=None, expire=None): @@ -138,7 +138,7 @@ def get_updated_props(self, key): def _make_job_fn(fn, celery_app, progress, key): cache = celery_app.backend - @celery_app.task(name=f"long_callback_{key}") + @celery_app.task(name=f"background_callback_{key}") def job_fn(result_key, progress_key, user_callback_args, context=None): def _set_progress(progress_value): if not isinstance(progress_value, (list, tuple)): @@ -184,7 +184,7 @@ def run(): result_key, json.dumps( { - "long_callback_error": { + "background_callback_error": { "msg": str(err), "tb": traceback.format_exc(), } diff --git a/dash/long_callback/managers/diskcache_manager.py b/dash/background_callback/managers/diskcache_manager.py similarity index 98% rename from dash/long_callback/managers/diskcache_manager.py rename to dash/background_callback/managers/diskcache_manager.py index e1a110f14f..f591f96fc8 100644 --- a/dash/long_callback/managers/diskcache_manager.py +++ b/dash/background_callback/managers/diskcache_manager.py @@ -1,7 +1,7 @@ import traceback from contextvars import copy_context -from . import BaseLongCallbackManager +from . import BaseBackgroundCallbackManager from .._proxy_set_props import ProxySetProps from ..._callback_context import context_value from ..._utils import AttributeDict @@ -10,7 +10,7 @@ _pending_value = "__$pending__" -class DiskcacheManager(BaseLongCallbackManager): +class DiskcacheManager(BaseBackgroundCallbackManager): """Manage the background execution of callbacks with subprocesses and a diskcache result backend.""" def __init__(self, cache=None, cache_by=None, expire=None): @@ -204,7 +204,7 @@ def run(): cache.set( result_key, { - "long_callback_error": { + "background_callback_error": { "msg": str(err), "tb": traceback.format_exc(), } diff --git a/dash/dash-renderer/src/actions/callbacks.ts b/dash/dash-renderer/src/actions/callbacks.ts index 23da0a3ff3..2d698b372d 100644 --- a/dash/dash-renderer/src/actions/callbacks.ts +++ b/dash/dash-renderer/src/actions/callbacks.ts @@ -29,7 +29,7 @@ import { IStoredCallback, IBlockedCallback, IPrioritizedCallback, - LongCallbackInfo, + BackgroundCallbackInfo, CallbackResponse, CallbackResponseData, SideUpdateOutput @@ -413,7 +413,7 @@ function handleServerside( hooks: any, config: any, payload: ICallbackPayload, - long: LongCallbackInfo | undefined, + background: BackgroundCallbackInfo | undefined, additionalArgs: [string, string, boolean?][] | undefined, getState: any, output: string, @@ -578,7 +578,7 @@ function handleServerside( progressDefault = data.progressDefault; } - if (!long || data.response !== undefined) { + if (!background || data.response !== undefined) { if (data.dist) { Promise.all(data.dist.map(loadLibrary)).then(() => { completeJob(); @@ -592,7 +592,9 @@ function handleServerside( // Poll chain. setTimeout( handle, - long.interval !== undefined ? long.interval : 500 + background.interval !== undefined + ? background.interval + : 500 ); } }); @@ -679,8 +681,14 @@ export function executeCallback( dispatch: any, getState: any ): IExecutingCallback { - const {output, inputs, state, clientside_function, long, dynamic_creator} = - cb.callback; + const { + output, + inputs, + state, + clientside_function, + background, + dynamic_creator + } = cb.callback; try { const inVals = fillVals(paths, layout, cb, inputs, 'Input', true); @@ -797,7 +805,7 @@ export function executeCallback( hooks, newConfig, payload, - long, + background, additionalArgs.length ? additionalArgs : undefined, getState, cb.callback.output, diff --git a/dash/dash-renderer/src/types/callbacks.ts b/dash/dash-renderer/src/types/callbacks.ts index d1cf636776..f1e1dc382c 100644 --- a/dash/dash-renderer/src/types/callbacks.ts +++ b/dash/dash-renderer/src/types/callbacks.ts @@ -11,7 +11,7 @@ export interface ICallbackDefinition { outputs: ICallbackProperty[]; prevent_initial_call: boolean; state: ICallbackProperty[]; - long?: LongCallbackInfo; + background?: BackgroundCallbackInfo; dynamic_creator?: boolean; running: any; no_output?: boolean; @@ -85,7 +85,7 @@ export type CallbackResult = { payload: ICallbackPayload | null; }; -export type LongCallbackInfo = { +export type BackgroundCallbackInfo = { interval?: number; progress?: any; running?: any; diff --git a/dash/dash.py b/dash/dash.py index f1b598bd65..33afffe533 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -349,9 +349,6 @@ class Dash: want to control the document.title through a separate component or clientside callback. - :param long_callback_manager: Deprecated, use ``background_callback_manager`` - instead. - :param background_callback_manager: Background callback manager instance to support the ``@callback(..., background=True)`` decorator. One of ``DiskcacheManager`` or ``CeleryManager`` currently supported. @@ -411,9 +408,6 @@ def __init__( # pylint: disable=too-many-statements plugins: Optional[list] = None, title: str = "Dash", update_title: str = "Updating...", - long_callback_manager: Optional[ - Any - ] = None, # Type should be specified if possible background_callback_manager: Optional[ Any ] = None, # Type should be specified if possible @@ -546,15 +540,8 @@ def __init__( # pylint: disable=too-many-statements ) self._assets_files = [] - self._long_callback_count = 0 - if long_callback_manager: - warnings.warn( - DeprecationWarning( - "`long_callback_manager` is deprecated and will be remove in Dash 3.0, " - "use `background_callback_manager` instead." - ) - ) - self._background_manager = background_callback_manager or long_callback_manager + + self._background_manager = background_callback_manager self.logger = logging.getLogger(__name__) @@ -1284,38 +1271,6 @@ def callback(self, *_args, **_kwargs): **_kwargs, ) - def long_callback( - self, - *_args, - manager=None, - interval=1000, - running=None, - cancel=None, - progress=None, - progress_default=None, - cache_args_to_ignore=None, - **_kwargs, - ): - """ - Deprecated: long callbacks are now supported natively with regular callbacks, - use `background=True` with `dash.callback` or `app.callback` instead. - """ - return _callback.callback( - *_args, - background=True, - manager=manager, - interval=interval, - progress=progress, - progress_default=progress_default, - running=running, - cancel=cancel, - cache_args_to_ignore=cache_args_to_ignore, - callback_map=self.callback_map, - callback_list=self._callback_list, - config_prevent_initial_callbacks=self.config.prevent_initial_callbacks, - **_kwargs, - ) - # pylint: disable=R0915 def dispatch(self): body = flask.request.get_json() @@ -1353,7 +1308,7 @@ def dispatch(self): g.background_callback_manager = ( cb.get("manager") or self._background_manager ) - g.ignore_register_page = cb.get("long", False) + g.ignore_register_page = cb.get("background", False) # Add args_grouping inputs_state_indices = cb["inputs_state_indices"] @@ -1428,7 +1383,7 @@ def dispatch(self): func, *args, outputs_list=outputs_list, - long_callback_manager=self._background_manager, + background_callback_manager=self._background_manager, callback_context=g, app=self, app_on_error=self._on_error, @@ -1476,18 +1431,18 @@ def _setup_server(self): self._callback_list.extend(_callback.GLOBAL_CALLBACK_LIST) _callback.GLOBAL_CALLBACK_LIST.clear() - _validate.validate_long_callbacks(self.callback_map) + _validate.validate_background_callbacks(self.callback_map) cancels = {} for callback in self.callback_map.values(): - long = callback.get("long") - if not long: + background = callback.get("background") + if not background: continue - if "cancel_inputs" in long: - cancel = long.pop("cancel_inputs") + if "cancel_inputs" in background: + cancel = background.pop("cancel_inputs") for c in cancel: - cancels[c] = long.get("manager") + cancels[c] = background.get("manager") if cancels: for cancel_input, manager in cancels.items(): @@ -2349,16 +2304,3 @@ def update(pathname_, search_, **states): Output(_ID_DUMMY, "children"), Input(_ID_STORE, "data"), ) - - def run_server(self, *args, **kwargs): - """`run_server` is a deprecated alias of `run` and may be removed in a - future version. We recommend using `app.run` instead. - - See `app.run` for usage information. - """ - warnings.warn( - DeprecationWarning( - "Dash.run_server is deprecated and will be removed in Dash 3.0" - ) - ) - self.run(*args, **kwargs) diff --git a/dash/development/__init__.py b/dash/development/__init__.py index a8c6749c22..e2106eb1dc 100644 --- a/dash/development/__init__.py +++ b/dash/development/__init__.py @@ -1,2 +1 @@ from . import base_component # noqa:F401 -from . import component_loader # noqa:F401 diff --git a/dash/development/component_loader.py b/dash/development/component_loader.py deleted file mode 100644 index 4075d598ac..0000000000 --- a/dash/development/component_loader.py +++ /dev/null @@ -1,96 +0,0 @@ -import collections -import json -import os -import warnings - - -from ._py_components_generation import ( - generate_class_file, - generate_imports, - generate_classes_files, - generate_class, -) -from .base_component import ComponentRegistry - - -def _get_metadata(metadata_path): - # Start processing - with open(metadata_path, encoding="utf-8") as data_file: - json_string = data_file.read() - data = json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode( - json_string - ) - return data - - -def load_components(metadata_path, namespace="default_namespace"): - """Load React component metadata into a format Dash can parse. - - Usage: load_components('../../component-suites/lib/metadata.json') - - Keyword arguments: - metadata_path -- a path to a JSON file created by - [`react-docgen`](https://github.com/reactjs/react-docgen). - - Returns: - components -- a list of component objects with keys - `type`, `valid_kwargs`, and `setup`. - """ - warnings.warn( - DeprecationWarning( - "Dynamic components loading has been deprecated and will be removed" - " in dash 3.0.\n" - f"Update {namespace} to generate components with dash-generate-components" - ) - ) - # Register the component lib for index include. - ComponentRegistry.registry.add(namespace) - components = [] - - data = _get_metadata(metadata_path) - - # Iterate over each property name (which is a path to the component) - for componentPath in data: - componentData = data[componentPath] - - # Extract component name from path - # e.g. src/components/MyControl.react.js - # TODO Make more robust - some folks will write .jsx and others - # will be on windows. Unfortunately react-docgen doesn't include - # the name of the component atm. - name = componentPath.split("/").pop().split(".")[0] - component = generate_class( - name, componentData["props"], componentData["description"], namespace, None - ) - - components.append(component) - - return components - - -def generate_classes(namespace, metadata_path="lib/metadata.json"): - """Load React component metadata into a format Dash can parse, then create - Python class files. - - Usage: generate_classes() - - Keyword arguments: - namespace -- name of the generated Python package (also output dir) - - metadata_path -- a path to a JSON file created by - [`react-docgen`](https://github.com/reactjs/react-docgen). - - Returns: - """ - - data = _get_metadata(metadata_path) - imports_path = os.path.join(namespace, "_imports_.py") - - # Make sure the file doesn't exist, as we use append write - if os.path.exists(imports_path): - os.remove(imports_path) - - components = generate_classes_files(namespace, data, generate_class_file) - - # Add the __all__ value so we can import * from _imports_ - generate_imports(namespace, components) diff --git a/dash/exceptions.py b/dash/exceptions.py index 62008210e1..a971d2e5a3 100644 --- a/dash/exceptions.py +++ b/dash/exceptions.py @@ -87,7 +87,7 @@ class DuplicateCallback(DashException): pass -class LongCallbackError(DashException): +class BackgroundCallbackError(DashException): pass diff --git a/dash/testing/plugin.py b/dash/testing/plugin.py index 00008c2b4c..02386dc458 100644 --- a/dash/testing/plugin.py +++ b/dash/testing/plugin.py @@ -244,8 +244,8 @@ def dashjl(request, dashjl_server, tmpdir) -> DashJuliaComposite: @pytest.fixture def diskcache_manager(): - from dash.long_callback import ( # pylint: disable=import-outside-toplevel - DiskcacheLongCallbackManager, + from dash.background_callback import ( # pylint: disable=import-outside-toplevel + DiskcacheManager, ) - return DiskcacheLongCallbackManager() + return DiskcacheManager() diff --git a/requirements/ci.txt b/requirements/ci.txt index b7f501bfb2..d66bb6af10 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -1,7 +1,5 @@ # Dependencies used by CI on github.com/plotly/dash black==22.3.0 -dash-flow-example==0.0.5 -dash-dangerously-set-inner-html flake8==7.0.0 flaky==3.8.1 flask-talisman==1.0.0 diff --git a/requirements/install.txt b/requirements/install.txt index 94e78db8da..8a02fa781a 100644 --- a/requirements/install.txt +++ b/requirements/install.txt @@ -1,9 +1,6 @@ Flask>=1.0.4,<3.1 Werkzeug<3.1 plotly>=5.0.0 -dash_html_components==2.0.0 -dash_core_components==2.0.0 -dash_table==5.0.0 importlib-metadata typing_extensions>=4.1.1 requests diff --git a/tests/assets/simple_app.py b/tests/assets/simple_app.py index 39e15865ef..48afd2712e 100644 --- a/tests/assets/simple_app.py +++ b/tests/assets/simple_app.py @@ -33,4 +33,4 @@ def on_style(value): if __name__ == "__main__": - app.run_server(debug=True, port=10850) + app.run(debug=True, port="10850") diff --git a/tests/integration/long_callback/__init__.py b/tests/integration/background_callback/__init__.py similarity index 100% rename from tests/integration/long_callback/__init__.py rename to tests/integration/background_callback/__init__.py diff --git a/tests/integration/long_callback/app1.py b/tests/integration/background_callback/app1.py similarity index 59% rename from tests/integration/long_callback/app1.py rename to tests/integration/background_callback/app1.py index 5bc48652df..2c2b99d6de 100644 --- a/tests/integration/long_callback/app1.py +++ b/tests/integration/background_callback/app1.py @@ -1,10 +1,10 @@ from dash import Dash, Input, Output, dcc, html import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle app = Dash(__name__) app.layout = html.Div( @@ -15,11 +15,12 @@ ) -@app.long_callback( +@app.callback( Output("output-1", "children"), [Input("input", "value")], interval=500, - manager=long_callback_manager, + manager=background_callback_manager, + background=True, ) def update_output(value): time.sleep(0.1) @@ -27,4 +28,4 @@ def update_output(value): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app2.py b/tests/integration/background_callback/app2.py similarity index 63% rename from tests/integration/long_callback/app2.py rename to tests/integration/background_callback/app2.py index 3c7851e9cb..f30b0bf078 100644 --- a/tests/integration/long_callback/app2.py +++ b/tests/integration/background_callback/app2.py @@ -2,12 +2,12 @@ import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ html.Button(id="button-1", children="Click Here", n_clicks=0), @@ -17,12 +17,13 @@ ) -@app.long_callback( +@app.callback( Output("result", "children"), [Input("button-1", "n_clicks")], running=[(Output("status", "children"), "Running", "Finished")], interval=500, prevent_initial_call=True, + background=True, ) def update_output(n_clicks): time.sleep(2) @@ -30,4 +31,4 @@ def update_output(n_clicks): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app3.py b/tests/integration/background_callback/app3.py similarity index 72% rename from tests/integration/long_callback/app3.py rename to tests/integration/background_callback/app3.py index dbff6896e1..fd3d7d2d6a 100644 --- a/tests/integration/long_callback/app3.py +++ b/tests/integration/background_callback/app3.py @@ -1,10 +1,10 @@ from dash import Dash, Input, Output, State, dcc, html import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle app = Dash(__name__) app.layout = html.Div( @@ -18,14 +18,15 @@ ) -@app.long_callback( +@app.callback( Output("result", "children"), [Input("run-button", "n_clicks"), State("input", "value")], running=[(Output("status", "children"), "Running", "Finished")], cancel=[Input("cancel-button", "n_clicks")], interval=500, - manager=long_callback_manager, + manager=background_callback_manager, prevent_initial_call=True, + background=True, ) def update_output(n_clicks, value): time.sleep(2) @@ -33,4 +34,4 @@ def update_output(n_clicks, value): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app4.py b/tests/integration/background_callback/app4.py similarity index 73% rename from tests/integration/long_callback/app4.py rename to tests/integration/background_callback/app4.py index 9004b4c830..1e0ec36907 100644 --- a/tests/integration/long_callback/app4.py +++ b/tests/integration/background_callback/app4.py @@ -1,13 +1,13 @@ from dash import Dash, Input, Output, State, dcc, html import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +bg_callback_manager = get_background_callback_manager() +handle = bg_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=bg_callback_manager) app.layout = html.Div( [ dcc.Input(id="input", value="hello, world"), @@ -19,7 +19,7 @@ ) -@app.long_callback( +@app.callback( Output("result", "children"), [Input("run-button", "n_clicks"), State("input", "value")], progress=Output("status", "children"), @@ -27,6 +27,7 @@ cancel=[Input("cancel-button", "n_clicks")], interval=500, prevent_initial_call=True, + background=True, ) def update_output(set_progress, n_clicks, value): for i in range(4): @@ -36,4 +37,4 @@ def update_output(set_progress, n_clicks, value): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app5.py b/tests/integration/background_callback/app5.py similarity index 70% rename from tests/integration/long_callback/app5.py rename to tests/integration/background_callback/app5.py index c8f58f7f80..421694f599 100644 --- a/tests/integration/long_callback/app5.py +++ b/tests/integration/background_callback/app5.py @@ -2,13 +2,13 @@ import time from multiprocessing import Value -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app._cache_key = Value("i", 0) @@ -17,7 +17,7 @@ def cache_fn(): return app._cache_key.value -long_callback_manager.cache_by = [cache_fn] +background_callback_manager.cache_by = [cache_fn] app.layout = html.Div( @@ -30,13 +30,14 @@ def cache_fn(): ) -@app.long_callback( +@app.callback( Output("result", "children"), [Input("run-button", "n_clicks"), State("input", "value")], progress=Output("status", "children"), progress_default="Finished", interval=500, cache_args_to_ignore=0, + background=True, ) def update_output(set_progress, _n_clicks, value): for i in range(4): @@ -46,4 +47,4 @@ def update_output(set_progress, _n_clicks, value): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app6.py b/tests/integration/background_callback/app6.py similarity index 79% rename from tests/integration/long_callback/app6.py rename to tests/integration/background_callback/app6.py index dfd1e021bb..9876a760dd 100644 --- a/tests/integration/long_callback/app6.py +++ b/tests/integration/background_callback/app6.py @@ -3,12 +3,12 @@ import time from multiprocessing import Value -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app._cache_key = Value("i", 0) @@ -17,7 +17,7 @@ def cache_fn(): return app._cache_key.value -long_callback_manager.cache_by = [cache_fn] +background_callback_manager.cache_by = [cache_fn] app.layout = html.Div( @@ -35,13 +35,14 @@ def cache_fn(): ) -@app.long_callback( +@app.callback( Output("result1", "children"), [Input("run-button1", "n_clicks"), State("input1", "value")], progress=Output("status1", "children"), progress_default="Finished", interval=500, cache_args_to_ignore=[0], + background=True, ) def update_output1(set_progress, _n_clicks, value): for i in range(4): @@ -50,7 +51,7 @@ def update_output1(set_progress, _n_clicks, value): return f"Result for '{value}'" -@app.long_callback( +@app.callback( Output("result2", "children"), dict(button=Input("run-button2", "n_clicks"), value=State("input2", "value")), progress=Output("status2", "children"), @@ -58,6 +59,7 @@ def update_output1(set_progress, _n_clicks, value): interval=500, cache_args_to_ignore=["button"], prevent_initial_call=True, + background=True, ) def update_output2(set_progress, button, value): for i in range(4): @@ -67,4 +69,4 @@ def update_output2(set_progress, button, value): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app7.py b/tests/integration/background_callback/app7.py similarity index 84% rename from tests/integration/long_callback/app7.py rename to tests/integration/background_callback/app7.py index 7895b1fa3c..a82cc02e2e 100644 --- a/tests/integration/long_callback/app7.py +++ b/tests/integration/background_callback/app7.py @@ -2,13 +2,13 @@ import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +bg_callback_manager = get_background_callback_manager() +handle = bg_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=bg_callback_manager) app.layout = html.Div( [ html.Button(id="show-layout-button", children="Show"), @@ -47,7 +47,7 @@ def make_layout(n_clicks): return [] -@app.long_callback( +@app.callback( Output("result", "children"), [Input("run-button", "n_clicks"), State("input", "value")], progress=Output("status", "children"), @@ -55,6 +55,7 @@ def make_layout(n_clicks): cancel=[Input("cancel-button", "n_clicks")], interval=500, prevent_initial_call=True, + background=True, ) def update_output(set_progress, n_clicks, value): for i in range(4): @@ -64,4 +65,4 @@ def update_output(set_progress, n_clicks, value): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_arbitrary.py b/tests/integration/background_callback/app_arbitrary.py similarity index 73% rename from tests/integration/long_callback/app_arbitrary.py rename to tests/integration/background_callback/app_arbitrary.py index 939fce8334..6ff73d0665 100644 --- a/tests/integration/long_callback/app_arbitrary.py +++ b/tests/integration/background_callback/app_arbitrary.py @@ -1,13 +1,13 @@ from dash import Dash, Input, Output, html, callback, set_props import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) -app.test_lock = lock = long_callback_manager.test_lock +app = Dash(__name__, background_callback_manager=background_callback_manager) +app.test_lock = lock = background_callback_manager.test_lock app.layout = html.Div( [ @@ -47,4 +47,4 @@ def on_click(_): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_bg_on_error.py b/tests/integration/background_callback/app_bg_on_error.py similarity index 76% rename from tests/integration/long_callback/app_bg_on_error.py rename to tests/integration/background_callback/app_bg_on_error.py index 3132b6d8a0..5492bf2758 100644 --- a/tests/integration/long_callback/app_bg_on_error.py +++ b/tests/integration/background_callback/app_bg_on_error.py @@ -1,8 +1,8 @@ from dash import Dash, Input, Output, html, set_props -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle def global_error_handler(err): @@ -10,7 +10,9 @@ def global_error_handler(err): app = Dash( - __name__, long_callback_manager=long_callback_manager, on_error=global_error_handler + __name__, + background_callback_manager=background_callback_manager, + on_error=global_error_handler, ) app.layout = [ diff --git a/tests/integration/long_callback/app_callback_ctx.py b/tests/integration/background_callback/app_callback_ctx.py similarity index 70% rename from tests/integration/long_callback/app_callback_ctx.py rename to tests/integration/background_callback/app_callback_ctx.py index f3d95346eb..3df02a749f 100644 --- a/tests/integration/long_callback/app_callback_ctx.py +++ b/tests/integration/background_callback/app_callback_ctx.py @@ -2,12 +2,12 @@ from dash import Dash, Input, Output, html, callback, ALL, ctx -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -18,7 +18,7 @@ html.Div(id="running"), ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock @callback( @@ -34,4 +34,4 @@ def update_output(n_clicks): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_ctx_cookies.py b/tests/integration/background_callback/app_ctx_cookies.py similarity index 69% rename from tests/integration/long_callback/app_ctx_cookies.py rename to tests/integration/background_callback/app_ctx_cookies.py index 088e00a24c..a629962137 100644 --- a/tests/integration/long_callback/app_ctx_cookies.py +++ b/tests/integration/background_callback/app_ctx_cookies.py @@ -1,11 +1,11 @@ from dash import Dash, Input, Output, html, callback, ctx -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, background_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -15,7 +15,7 @@ html.Div("output", id="output"), ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock @callback( diff --git a/tests/integration/long_callback/app_diff_outputs.py b/tests/integration/background_callback/app_diff_outputs.py similarity index 66% rename from tests/integration/long_callback/app_diff_outputs.py rename to tests/integration/background_callback/app_diff_outputs.py index 4294394747..1c5ebeba12 100644 --- a/tests/integration/long_callback/app_diff_outputs.py +++ b/tests/integration/background_callback/app_diff_outputs.py @@ -1,11 +1,11 @@ from dash import Dash, Input, Output, html -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -33,4 +33,4 @@ def callback_name(_): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_error.py b/tests/integration/background_callback/app_error.py similarity index 76% rename from tests/integration/long_callback/app_error.py rename to tests/integration/background_callback/app_error.py index 9e59fa121e..bcce865ce7 100644 --- a/tests/integration/long_callback/app_error.py +++ b/tests/integration/background_callback/app_error.py @@ -5,12 +5,12 @@ from dash.dependencies import Input, Output from dash.exceptions import PreventUpdate -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = dash.Dash(__name__, long_callback_manager=long_callback_manager) +app = dash.Dash(__name__, background_callback_manager=background_callback_manager) app.enable_dev_tools(debug=True, dev_tools_ui=True) app.layout = html.Div( [ @@ -23,16 +23,17 @@ html.Button("multi-output", id="multi-output"), ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock -@app.long_callback( +@app.callback( output=Output("output", "children"), inputs=Input("button", "n_clicks"), running=[ (Output("button", "disabled"), True, False), ], prevent_initial_call=True, + background=True, ) def callback(n_clicks): time.sleep(1) @@ -44,7 +45,7 @@ def callback(n_clicks): return f"Clicked {n_clicks} times" -@app.long_callback( +@app.callback( output=[Output("output-status", "children")] + [Output(f"output{i}", "children") for i in range(1, 4)], inputs=[Input("multi-output", "n_clicks")], @@ -52,6 +53,7 @@ def callback(n_clicks): (Output("multi-output", "disabled"), True, False), ], prevent_initial_call=True, + background=True, ) def long_multi(n_clicks): time.sleep(1) @@ -63,4 +65,4 @@ def long_multi(n_clicks): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_page_cancel.py b/tests/integration/background_callback/app_page_cancel.py similarity index 86% rename from tests/integration/long_callback/app_page_cancel.py rename to tests/integration/background_callback/app_page_cancel.py index d99ed6ac82..28cf191c8f 100644 --- a/tests/integration/long_callback/app_page_cancel.py +++ b/tests/integration/background_callback/app_page_cancel.py @@ -1,16 +1,16 @@ from dash import Dash, Input, Output, dcc, html, page_container, register_page -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle app = Dash( __name__, use_pages=True, pages_folder="", - long_callback_manager=long_callback_manager, + background_callback_manager=background_callback_manager, ) app.layout = html.Div( @@ -21,7 +21,7 @@ page_container, ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock register_page( "one", diff --git a/tests/integration/long_callback/app_pattern_matching.py b/tests/integration/background_callback/app_pattern_matching.py similarity index 65% rename from tests/integration/long_callback/app_pattern_matching.py rename to tests/integration/background_callback/app_pattern_matching.py index 65aa906bcd..0588268bd3 100644 --- a/tests/integration/long_callback/app_pattern_matching.py +++ b/tests/integration/background_callback/app_pattern_matching.py @@ -1,11 +1,11 @@ from dash import Dash, Input, Output, html, callback, ALL -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -15,7 +15,7 @@ html.Div(id="result", children="No results"), ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock @callback( @@ -30,4 +30,4 @@ def update_output(n_clicks): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_progress_delete.py b/tests/integration/background_callback/app_progress_delete.py similarity index 74% rename from tests/integration/long_callback/app_progress_delete.py rename to tests/integration/background_callback/app_progress_delete.py index 2fdf08af61..f4fb37dfdd 100644 --- a/tests/integration/long_callback/app_progress_delete.py +++ b/tests/integration/background_callback/app_progress_delete.py @@ -1,12 +1,12 @@ from dash import Dash, Input, Output, State, html, clientside_callback import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -42,4 +42,4 @@ def on_bg_progress(set_progress, _): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_short_interval.py b/tests/integration/background_callback/app_short_interval.py similarity index 68% rename from tests/integration/long_callback/app_short_interval.py rename to tests/integration/background_callback/app_short_interval.py index 2dd4c3f5fc..a7cd4b014f 100644 --- a/tests/integration/long_callback/app_short_interval.py +++ b/tests/integration/background_callback/app_short_interval.py @@ -1,12 +1,12 @@ from dash import Dash, Input, Output, html, callback import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -16,7 +16,7 @@ html.Div(id="result", children="No results"), ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock @callback( @@ -37,4 +37,4 @@ def update_output(set_progress, n_clicks): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_side_update.py b/tests/integration/background_callback/app_side_update.py similarity index 73% rename from tests/integration/long_callback/app_side_update.py rename to tests/integration/background_callback/app_side_update.py index e54a3318aa..e3f81c3a72 100644 --- a/tests/integration/long_callback/app_side_update.py +++ b/tests/integration/background_callback/app_side_update.py @@ -1,12 +1,12 @@ from dash import Dash, Input, Output, html, callback import time -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -17,7 +17,7 @@ html.Div(id="side-status"), ] ) -app.test_lock = lock = long_callback_manager.test_lock +app.test_lock = lock = background_callback_manager.test_lock @callback( @@ -47,4 +47,4 @@ def update_side(progress): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/app_unordered.py b/tests/integration/background_callback/app_unordered.py similarity index 61% rename from tests/integration/long_callback/app_unordered.py rename to tests/integration/background_callback/app_unordered.py index 95abeca9f7..c2e7ed3e68 100644 --- a/tests/integration/long_callback/app_unordered.py +++ b/tests/integration/background_callback/app_unordered.py @@ -1,11 +1,11 @@ from dash import Dash, Input, Output, dcc, State, html, callback -from tests.integration.long_callback.utils import get_long_callback_manager +from tests.integration.background_callback.utils import get_background_callback_manager -long_callback_manager = get_long_callback_manager() -handle = long_callback_manager.handle +background_callback_manager = get_background_callback_manager() +handle = background_callback_manager.handle -app = Dash(__name__, long_callback_manager=long_callback_manager) +app = Dash(__name__, background_callback_manager=background_callback_manager) app.layout = html.Div( [ @@ -28,4 +28,4 @@ def update_output(stored, n_clicks): if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/tests/integration/long_callback/conftest.py b/tests/integration/background_callback/conftest.py similarity index 100% rename from tests/integration/long_callback/conftest.py rename to tests/integration/background_callback/conftest.py diff --git a/tests/integration/long_callback/test_basic_long_callback001.py b/tests/integration/background_callback/test_basic_long_callback001.py similarity index 87% rename from tests/integration/long_callback/test_basic_long_callback001.py rename to tests/integration/background_callback/test_basic_long_callback001.py index e774443956..af8c80d3ee 100644 --- a/tests/integration/long_callback/test_basic_long_callback001.py +++ b/tests/integration/background_callback/test_basic_long_callback001.py @@ -4,7 +4,7 @@ import pytest from flaky import flaky -from .utils import setup_long_callback_app +from .utils import setup_background_callback_app @pytest.mark.skipif( @@ -16,7 +16,7 @@ def test_lcbc001_fast_input(dash_duo, manager): Make sure that we settle to the correct final value when handling rapid inputs """ lock = Lock() - with setup_long_callback_app(manager, "app1") as app: + with setup_background_callback_app(manager, "app1") as app: dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output-1", "initial value", 15) input_ = dash_duo.find_element("#input") diff --git a/tests/integration/long_callback/test_basic_long_callback002.py b/tests/integration/background_callback/test_basic_long_callback002.py similarity index 90% rename from tests/integration/long_callback/test_basic_long_callback002.py rename to tests/integration/background_callback/test_basic_long_callback002.py index 9d1de381f2..ee01da6f6f 100644 --- a/tests/integration/long_callback/test_basic_long_callback002.py +++ b/tests/integration/background_callback/test_basic_long_callback002.py @@ -3,7 +3,7 @@ import pytest from flaky import flaky -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -11,7 +11,7 @@ ) @flaky(max_runs=3) def test_lcbc002_long_callback_running(dash_duo, manager): - with setup_long_callback_app(manager, "app2") as app: + with setup_background_callback_app(manager, "app2") as app: dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#result", "Not clicked", 15) dash_duo.wait_for_text_to_equal("#status", "Finished", 8) diff --git a/tests/integration/long_callback/test_basic_long_callback003.py b/tests/integration/background_callback/test_basic_long_callback003.py similarity index 92% rename from tests/integration/long_callback/test_basic_long_callback003.py rename to tests/integration/background_callback/test_basic_long_callback003.py index c8825a6e0f..6a15bd0ef8 100644 --- a/tests/integration/long_callback/test_basic_long_callback003.py +++ b/tests/integration/background_callback/test_basic_long_callback003.py @@ -4,7 +4,7 @@ import pytest from flaky import flaky -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -14,7 +14,7 @@ def test_lcbc003_long_callback_running_cancel(dash_duo, manager): lock = Lock() - with setup_long_callback_app(manager, "app3") as app: + with setup_background_callback_app(manager, "app3") as app: dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#result", "No results", 15) dash_duo.wait_for_text_to_equal("#status", "Finished", 6) diff --git a/tests/integration/long_callback/test_basic_long_callback004.py b/tests/integration/background_callback/test_basic_long_callback004.py similarity index 91% rename from tests/integration/long_callback/test_basic_long_callback004.py rename to tests/integration/background_callback/test_basic_long_callback004.py index 06080ada7e..ec6cf333d8 100644 --- a/tests/integration/long_callback/test_basic_long_callback004.py +++ b/tests/integration/background_callback/test_basic_long_callback004.py @@ -3,7 +3,7 @@ import pytest from flaky import flaky -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -11,7 +11,7 @@ ) @flaky(max_runs=3) def test_lcbc004_long_callback_progress(dash_duo, manager): - with setup_long_callback_app(manager, "app4") as app: + with setup_background_callback_app(manager, "app4") as app: dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#status", "Finished", 8) dash_duo.wait_for_text_to_equal("#result", "No results", 8) diff --git a/tests/integration/long_callback/test_basic_long_callback005.py b/tests/integration/background_callback/test_basic_long_callback005.py similarity index 94% rename from tests/integration/long_callback/test_basic_long_callback005.py rename to tests/integration/background_callback/test_basic_long_callback005.py index c92c6ae00b..40cb4ce09e 100644 --- a/tests/integration/long_callback/test_basic_long_callback005.py +++ b/tests/integration/background_callback/test_basic_long_callback005.py @@ -3,7 +3,7 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -13,7 +13,7 @@ def test_lcbc005_long_callback_caching(dash_duo, manager): lock = Lock() - with setup_long_callback_app(manager, "app5") as app: + with setup_background_callback_app(manager, "app5") as app: dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#status", "Progress 2/4", 15) dash_duo.wait_for_text_to_equal("#status", "Finished", 15) diff --git a/tests/integration/long_callback/test_basic_long_callback006.py b/tests/integration/background_callback/test_basic_long_callback006.py similarity index 97% rename from tests/integration/long_callback/test_basic_long_callback006.py rename to tests/integration/background_callback/test_basic_long_callback006.py index 3ae58ce769..8771d58067 100644 --- a/tests/integration/long_callback/test_basic_long_callback006.py +++ b/tests/integration/background_callback/test_basic_long_callback006.py @@ -4,7 +4,7 @@ import pytest from flaky import flaky -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -14,7 +14,7 @@ def test_lcbc006_long_callback_caching_multi(dash_duo, manager): lock = Lock() - with setup_long_callback_app(manager, "app6") as app: + with setup_background_callback_app(manager, "app6") as app: dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#status1", "Progress 2/4", 15) dash_duo.wait_for_text_to_equal("#status1", "Finished", 15) diff --git a/tests/integration/long_callback/test_basic_long_callback007.py b/tests/integration/background_callback/test_basic_long_callback007.py similarity index 92% rename from tests/integration/long_callback/test_basic_long_callback007.py rename to tests/integration/background_callback/test_basic_long_callback007.py index a8970b2ff2..ba9e8043f5 100644 --- a/tests/integration/long_callback/test_basic_long_callback007.py +++ b/tests/integration/background_callback/test_basic_long_callback007.py @@ -3,7 +3,7 @@ import pytest from flaky import flaky -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -11,7 +11,7 @@ ) @flaky(max_runs=3) def test_lcbc007_validation_layout(dash_duo, manager): - with setup_long_callback_app(manager, "app7") as app: + with setup_background_callback_app(manager, "app7") as app: dash_duo.start_server(app) # Show layout diff --git a/tests/integration/long_callback/test_basic_long_callback008.py b/tests/integration/background_callback/test_basic_long_callback008.py similarity index 87% rename from tests/integration/long_callback/test_basic_long_callback008.py rename to tests/integration/background_callback/test_basic_long_callback008.py index dad22394d4..b56b5a32c1 100644 --- a/tests/integration/long_callback/test_basic_long_callback008.py +++ b/tests/integration/background_callback/test_basic_long_callback008.py @@ -2,14 +2,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc008_long_callbacks_error(dash_duo, manager): - with setup_long_callback_app(manager, "app_error") as app: + with setup_background_callback_app(manager, "app_error") as app: dash_duo.start_server( app, debug=True, @@ -34,7 +34,8 @@ def click_n_wait(): dash_duo.driver.switch_to.frame(dash_duo.find_element("iframe")) assert ( - "dash.exceptions.LongCallbackError: An error occurred inside a long callback:" + "dash.exceptions.BackgroundCallbackError: " + "An error occurred inside a background callback:" in dash_duo.wait_for_element(".errormsg").text ) dash_duo.driver.switch_to.default_content() diff --git a/tests/integration/long_callback/test_basic_long_callback009.py b/tests/integration/background_callback/test_basic_long_callback009.py similarity index 79% rename from tests/integration/long_callback/test_basic_long_callback009.py rename to tests/integration/background_callback/test_basic_long_callback009.py index c70b9736ad..83192fb467 100644 --- a/tests/integration/long_callback/test_basic_long_callback009.py +++ b/tests/integration/background_callback/test_basic_long_callback009.py @@ -3,14 +3,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc009_short_interval(dash_duo, manager): - with setup_long_callback_app(manager, "app_short_interval") as app: + with setup_background_callback_app(manager, "app_short_interval") as app: dash_duo.start_server(app) dash_duo.find_element("#run-button").click() dash_duo.wait_for_text_to_equal("#status", "Progress 2/4", 20) diff --git a/tests/integration/long_callback/test_basic_long_callback010.py b/tests/integration/background_callback/test_basic_long_callback010.py similarity index 70% rename from tests/integration/long_callback/test_basic_long_callback010.py rename to tests/integration/background_callback/test_basic_long_callback010.py index e6ba2fca44..bc4afc50e2 100644 --- a/tests/integration/long_callback/test_basic_long_callback010.py +++ b/tests/integration/background_callback/test_basic_long_callback010.py @@ -2,14 +2,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc010_side_updates(dash_duo, manager): - with setup_long_callback_app(manager, "app_side_update") as app: + with setup_background_callback_app(manager, "app_side_update") as app: dash_duo.start_server(app) dash_duo.find_element("#run-button").click() for i in range(1, 4): diff --git a/tests/integration/long_callback/test_basic_long_callback011.py b/tests/integration/background_callback/test_basic_long_callback011.py similarity index 72% rename from tests/integration/long_callback/test_basic_long_callback011.py rename to tests/integration/background_callback/test_basic_long_callback011.py index 94736f4b67..f7f4e80c39 100644 --- a/tests/integration/long_callback/test_basic_long_callback011.py +++ b/tests/integration/background_callback/test_basic_long_callback011.py @@ -2,14 +2,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc011_long_pattern_matching(dash_duo, manager): - with setup_long_callback_app(manager, "app_pattern_matching") as app: + with setup_background_callback_app(manager, "app_pattern_matching") as app: dash_duo.start_server(app) for i in range(1, 4): for _ in range(i): diff --git a/tests/integration/long_callback/test_basic_long_callback012.py b/tests/integration/background_callback/test_basic_long_callback012.py similarity index 74% rename from tests/integration/long_callback/test_basic_long_callback012.py rename to tests/integration/background_callback/test_basic_long_callback012.py index e646686f38..7fcb8b0175 100644 --- a/tests/integration/long_callback/test_basic_long_callback012.py +++ b/tests/integration/background_callback/test_basic_long_callback012.py @@ -3,14 +3,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc012_long_callback_ctx(dash_duo, manager): - with setup_long_callback_app(manager, "app_callback_ctx") as app: + with setup_background_callback_app(manager, "app_callback_ctx") as app: dash_duo.start_server(app) dash_duo.find_element("button:nth-child(1)").click() dash_duo.wait_for_text_to_equal("#running", "off") diff --git a/tests/integration/long_callback/test_basic_long_callback013.py b/tests/integration/background_callback/test_basic_long_callback013.py similarity index 67% rename from tests/integration/long_callback/test_basic_long_callback013.py rename to tests/integration/background_callback/test_basic_long_callback013.py index 451e03193e..aa38967655 100644 --- a/tests/integration/long_callback/test_basic_long_callback013.py +++ b/tests/integration/background_callback/test_basic_long_callback013.py @@ -2,14 +2,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc013_unordered_state_input(dash_duo, manager): - with setup_long_callback_app(manager, "app_unordered") as app: + with setup_background_callback_app(manager, "app_unordered") as app: dash_duo.start_server(app) dash_duo.find_element("#click").click() diff --git a/tests/integration/long_callback/test_basic_long_callback014.py b/tests/integration/background_callback/test_basic_long_callback014.py similarity index 70% rename from tests/integration/long_callback/test_basic_long_callback014.py rename to tests/integration/background_callback/test_basic_long_callback014.py index 47ff2f1155..05369c4284 100644 --- a/tests/integration/long_callback/test_basic_long_callback014.py +++ b/tests/integration/background_callback/test_basic_long_callback014.py @@ -2,14 +2,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc014_progress_delete(dash_duo, manager): - with setup_long_callback_app(manager, "app_progress_delete") as app: + with setup_background_callback_app(manager, "app_progress_delete") as app: dash_duo.start_server(app) dash_duo.find_element("#start").click() dash_duo.wait_for_text_to_equal("#output", "done") diff --git a/tests/integration/long_callback/test_basic_long_callback015.py b/tests/integration/background_callback/test_basic_long_callback015.py similarity index 70% rename from tests/integration/long_callback/test_basic_long_callback015.py rename to tests/integration/background_callback/test_basic_long_callback015.py index a35a8b19ee..b1e206e349 100644 --- a/tests/integration/long_callback/test_basic_long_callback015.py +++ b/tests/integration/background_callback/test_basic_long_callback015.py @@ -2,14 +2,14 @@ import pytest -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" ) def test_lcbc015_diff_outputs_same_func(dash_duo, manager): - with setup_long_callback_app(manager, "app_diff_outputs") as app: + with setup_background_callback_app(manager, "app_diff_outputs") as app: dash_duo.start_server(app) for i in range(1, 3): diff --git a/tests/integration/long_callback/test_basic_long_callback016.py b/tests/integration/background_callback/test_basic_long_callback016.py similarity index 91% rename from tests/integration/long_callback/test_basic_long_callback016.py rename to tests/integration/background_callback/test_basic_long_callback016.py index ac65d16cf6..ebc26bba3d 100644 --- a/tests/integration/long_callback/test_basic_long_callback016.py +++ b/tests/integration/background_callback/test_basic_long_callback016.py @@ -3,7 +3,7 @@ import pytest from flaky import flaky -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app @pytest.mark.skipif( @@ -11,7 +11,7 @@ ) @flaky(max_runs=3) def test_lcbc016_multi_page_cancel(dash_duo, manager): - with setup_long_callback_app(manager, "app_page_cancel") as app: + with setup_background_callback_app(manager, "app_page_cancel") as app: dash_duo.start_server(app) with app.test_lock: diff --git a/tests/integration/long_callback/test_basic_long_callback017.py b/tests/integration/background_callback/test_basic_long_callback017.py similarity index 81% rename from tests/integration/long_callback/test_basic_long_callback017.py rename to tests/integration/background_callback/test_basic_long_callback017.py index 3d64d39c6d..1fd5eb2e09 100644 --- a/tests/integration/long_callback/test_basic_long_callback017.py +++ b/tests/integration/background_callback/test_basic_long_callback017.py @@ -1,8 +1,8 @@ -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app def test_lcbc017_long_callback_set_props(dash_duo, manager): - with setup_long_callback_app(manager, "app_arbitrary") as app: + with setup_background_callback_app(manager, "app_arbitrary") as app: dash_duo.start_server(app) dash_duo.find_element("#start").click() diff --git a/tests/integration/long_callback/test_basic_long_callback018.py b/tests/integration/background_callback/test_basic_long_callback018.py similarity index 69% rename from tests/integration/long_callback/test_basic_long_callback018.py rename to tests/integration/background_callback/test_basic_long_callback018.py index 7dd0ca36d7..6a53669944 100644 --- a/tests/integration/long_callback/test_basic_long_callback018.py +++ b/tests/integration/background_callback/test_basic_long_callback018.py @@ -1,8 +1,8 @@ -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app def test_lcbc018_background_callback_on_error(dash_duo, manager): - with setup_long_callback_app(manager, "app_bg_on_error") as app: + with setup_background_callback_app(manager, "app_bg_on_error") as app: dash_duo.start_server(app) dash_duo.find_element("#start-cb-onerror").click() diff --git a/tests/integration/long_callback/test_ctx_cookies.py b/tests/integration/background_callback/test_ctx_cookies.py similarity index 66% rename from tests/integration/long_callback/test_ctx_cookies.py rename to tests/integration/background_callback/test_ctx_cookies.py index e752d5fe20..84410ad5ae 100644 --- a/tests/integration/long_callback/test_ctx_cookies.py +++ b/tests/integration/background_callback/test_ctx_cookies.py @@ -1,8 +1,8 @@ -from tests.integration.long_callback.utils import setup_long_callback_app +from tests.integration.background_callback.utils import setup_background_callback_app def test_lcbc019_ctx_cookies(dash_duo, manager): - with setup_long_callback_app(manager, "app_ctx_cookies") as app: + with setup_background_callback_app(manager, "app_ctx_cookies") as app: dash_duo.start_server(app) dash_duo.find_element("#set-cookies").click() diff --git a/tests/integration/long_callback/utils.py b/tests/integration/background_callback/utils.py similarity index 81% rename from tests/integration/long_callback/utils.py rename to tests/integration/background_callback/utils.py index 8c5c9e2a4f..3498ea7737 100644 --- a/tests/integration/long_callback/utils.py +++ b/tests/integration/background_callback/utils.py @@ -8,7 +8,7 @@ import psutil import redis -from dash.long_callback import DiskcacheManager +from dash.background_callback import DiskcacheManager manager = None @@ -30,12 +30,12 @@ def call_job_fn( return pid -def get_long_callback_manager(): +def get_background_callback_manager(): """ Get the long callback mangaer configured by environment variables """ if os.environ.get("LONG_CALLBACK_MANAGER", None) == "celery": - from dash.long_callback import CeleryLongCallbackManager + from dash.background_callback import CeleryManager from celery import Celery import redis @@ -44,15 +44,15 @@ def get_long_callback_manager(): broker=os.environ.get("CELERY_BROKER"), backend=os.environ.get("CELERY_BACKEND"), ) - long_callback_manager = CeleryLongCallbackManager(celery_app) + background_callback_manager = CeleryManager(celery_app) redis_conn = redis.Redis(host="localhost", port=6379, db=1) - long_callback_manager.test_lock = redis_conn.lock("test-lock") + background_callback_manager.test_lock = redis_conn.lock("test-lock") elif os.environ.get("LONG_CALLBACK_MANAGER", None) == "diskcache": import diskcache cache = diskcache.Cache(os.environ.get("DISKCACHE_DIR")) - long_callback_manager = TestDiskCacheManager(cache) - long_callback_manager.test_lock = diskcache.Lock(cache, "test-lock") + background_callback_manager = TestDiskCacheManager(cache) + background_callback_manager.test_lock = diskcache.Lock(cache, "test-lock") else: raise ValueError( "Invalid long callback manager specified as LONG_CALLBACK_MANAGER " @@ -60,9 +60,9 @@ def get_long_callback_manager(): ) global manager - manager = long_callback_manager + manager = background_callback_manager - return long_callback_manager + return background_callback_manager def kill(proc_pid): @@ -73,7 +73,7 @@ def kill(proc_pid): @contextmanager -def setup_long_callback_app(manager_name, app_name): +def setup_background_callback_app(manager_name, app_name): from dash.testing.application_runners import import_app if manager_name == "celery": @@ -92,7 +92,7 @@ def setup_long_callback_app(manager_name, app_name): [ "celery", "-A", - f"tests.integration.long_callback.{app_name}:handle", + f"tests.integration.background_callback.{app_name}:handle", "worker", "-P", "prefork", @@ -112,10 +112,11 @@ def setup_long_callback_app(manager_name, app_name): break lines.append(line) else: - raise RuntimeError("celery failed to start: " + {"\n".join(lines)}) + error = "\n".join(lines) + raise RuntimeError(f"celery failed to start: {error}") try: - yield import_app(f"tests.integration.long_callback.{app_name}") + yield import_app(f"tests.integration.background_callback.{app_name}") finally: # Interval may run one more time after settling on final app state # Sleep for 1 interval of time @@ -134,7 +135,7 @@ def setup_long_callback_app(manager_name, app_name): print(cache_directory) os.environ["DISKCACHE_DIR"] = cache_directory try: - app = import_app(f"tests.integration.long_callback.{app_name}") + app = import_app(f"tests.integration.background_callback.{app_name}") yield app finally: # Interval may run one more time after settling on final app state diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index c779ac47d4..53c42db3ba 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -2,13 +2,9 @@ import flask import json import pytest -import re from bs4 import BeautifulSoup -import dash_dangerously_set_inner_html -import dash_flow_example - import dash from dash import Dash, html, dcc, Input, Output from dash.exceptions import PreventUpdate @@ -48,67 +44,6 @@ def test_inin003_wildcard_data_attributes(dash_duo): assert dash_duo.get_logs() == [] -def test_inin004_no_props_component(dash_duo): - app = Dash() - app.layout = html.Div( - [ - dash_dangerously_set_inner_html.DangerouslySetInnerHTML( - """ -

No Props Component

- """ - ) - ], - id="app", - ) - - dash_duo.start_server(app) - - assert dash_duo.get_logs() == [] - assert dash_duo.find_element("h1").text == "No Props Component" - - inner = dash_duo.find_element("#app").get_property("innerHTML") - expected = "

No Props Component

" - assert re.sub("\\s+", " ", inner) == expected - - -def test_inin005_flow_component(dash_duo): - app = Dash() - - app.layout = html.Div( - [ - dash_flow_example.ExampleReactComponent( - id="react", value="my-value", label="react component" - ), - dash_flow_example.ExampleFlowComponent( - id="flow", value="my-value", label="flow component" - ), - html.Hr(), - html.Div(id="output"), - ] - ) - - @app.callback( - Output("output", "children"), [Input("react", "value"), Input("flow", "value")] - ) - def display_output(react_value, flow_value): - return html.Div( - [ - "You have entered {} and {}".format(react_value, flow_value), - html.Hr(), - html.Label("Flow Component Docstring"), - html.Pre(dash_flow_example.ExampleFlowComponent.__doc__), - html.Hr(), - html.Label("React PropTypes Component Docstring"), - html.Pre(dash_flow_example.ExampleReactComponent.__doc__), - html.Div(id="waitfor"), - ] - ) - - dash_duo.start_server(app) - dash_duo.wait_for_element("#waitfor") - dash_duo.percy_snapshot(name="flowtype") - - def test_inin006_meta_tags(dash_duo): metas = [ {"name": "description", "content": "my dash app"}, diff --git a/tests/unit/development/test_component_loader.py b/tests/unit/development/test_component_loader.py deleted file mode 100644 index aa30ed1c3d..0000000000 --- a/tests/unit/development/test_component_loader.py +++ /dev/null @@ -1,194 +0,0 @@ -import collections -import json -import os -import shutil - -import pytest - -from dash.development._py_components_generation import generate_class -from dash.development.base_component import Component -from dash.development.component_loader import load_components, generate_classes - -METADATA_PATH = "metadata.json" - -METADATA_STRING = """{ - "MyComponent.react.js": { - "props": { - "foo": { - "type": { - "name": "number" - }, - "required": false, - "description": "Description of prop foo.", - "defaultValue": { - "value": "42", - "computed": false - } - }, - "children": { - "type": { - "name": "object" - }, - "description": "Children", - "required": false - }, - "data-*": { - "type": { - "name": "string" - }, - "description": "Wildcard data", - "required": false - }, - "aria-*": { - "type": { - "name": "string" - }, - "description": "Wildcard aria", - "required": false - }, - "bar": { - "type": { - "name": "custom" - }, - "required": false, - "description": "Description of prop bar.", - "defaultValue": { - "value": "21", - "computed": false - } - }, - "baz": { - "type": { - "name": "union", - "value": [ - { - "name": "number" - }, - { - "name": "string" - } - ] - }, - "required": false, - "description": "" - } - }, - "description": "General component description.", - "methods": [] - }, - "A.react.js": { - "description": "", - "methods": [], - "props": { - "href": { - "type": { - "name": "string" - }, - "required": false, - "description": "The URL of a linked resource." - }, - "children": { - "type": { - "name": "object" - }, - "description": "Children", - "required": false - } - } - } -}""" -METADATA = json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode( - METADATA_STRING -) - - -@pytest.fixture -def write_metadata_file(): - with open(METADATA_PATH, "w") as f: - f.write(METADATA_STRING) - yield - os.remove(METADATA_PATH) - - -@pytest.fixture -def make_namespace(): - os.makedirs("default_namespace") - init_file_path = "default_namespace/__init__.py" - with open(init_file_path, "a"): - os.utime(init_file_path, None) - yield - shutil.rmtree("default_namespace") - - -def test_loadcomponents(write_metadata_file): - my_component = generate_class( - "MyComponent", - METADATA["MyComponent.react.js"]["props"], - METADATA["MyComponent.react.js"]["description"], - "default_namespace", - ) - - a_component = generate_class( - "A", - METADATA["A.react.js"]["props"], - METADATA["A.react.js"]["description"], - "default_namespace", - ) - - c = load_components(METADATA_PATH) - - my_component_kwargs = { - "foo": "Hello World", - "bar": "Lah Lah", - "baz": "Lemons", - "data-foo": "Blah", - "aria-bar": "Seven", - "children": "Child", - } - a_kwargs = {"children": "Child", "href": "Hello World"} - - assert isinstance(my_component(**my_component_kwargs), Component) - - assert repr(my_component(**my_component_kwargs)) == repr( - c[0](**my_component_kwargs) - ) - - assert repr(a_component(**a_kwargs)) == repr(c[1](**a_kwargs)) - - -def test_loadcomponents_from_generated_class(write_metadata_file, make_namespace): - my_component_runtime = generate_class( - "MyComponent", - METADATA["MyComponent.react.js"]["props"], - METADATA["MyComponent.react.js"]["description"], - "default_namespace", - ) - - a_runtime = generate_class( - "A", - METADATA["A.react.js"]["props"], - METADATA["A.react.js"]["description"], - "default_namespace", - ) - - generate_classes("default_namespace", METADATA_PATH) - from default_namespace.MyComponent import MyComponent as MyComponent_buildtime - from default_namespace.A import A as A_buildtime - - my_component_kwargs = { - "foo": "Hello World", - "bar": "Lah Lah", - "baz": "Lemons", - "data-foo": "Blah", - "aria-bar": "Seven", - "children": "Child", - } - a_kwargs = {"children": "Child", "href": "Hello World"} - - assert isinstance(MyComponent_buildtime(**my_component_kwargs), Component) - - assert repr(MyComponent_buildtime(**my_component_kwargs)) == repr( - my_component_runtime(**my_component_kwargs) - ) - - assert repr(a_runtime(**a_kwargs)) == repr(A_buildtime(**a_kwargs)) diff --git a/tests/unit/library/test_long_callback_validation.py b/tests/unit/library/test_background_callback_validation.py similarity index 55% rename from tests/unit/library/test_long_callback_validation.py rename to tests/unit/library/test_background_callback_validation.py index db0561233c..4578aabedc 100644 --- a/tests/unit/library/test_long_callback_validation.py +++ b/tests/unit/library/test_background_callback_validation.py @@ -1,26 +1,26 @@ import pytest -from dash.exceptions import LongCallbackError +from dash.exceptions import BackgroundCallbackError from dash.dependencies import Input, Output -from dash._validate import validate_long_callbacks +from dash._validate import validate_background_callbacks -def test_circular_long_callback_progress(): +def test_circular_background_callback_progress(): callback_map = { "side": { "output": [Output("side-progress", "children")], "raw_inputs": [Input("progress", "children")], }, - "long": { + "background": { "output": [Output("result", "children")], "raw_inputs": [ Input("click", "n_clicks"), Input("side-progress", "children"), ], - "long": {"progress": [Output("progress", "children")]}, + "background": {"progress": [Output("progress", "children")]}, }, } - with pytest.raises(LongCallbackError): + with pytest.raises(BackgroundCallbackError): - validate_long_callbacks(callback_map) + validate_background_callbacks(callback_map) diff --git a/tests/unit/test_old_imports.py b/tests/unit/test_old_imports.py deleted file mode 100644 index 90eaf4d0e7..0000000000 --- a/tests/unit/test_old_imports.py +++ /dev/null @@ -1,43 +0,0 @@ -from pytest import warns - -from dash import dcc, dash_table - - -def filter_dir(package): - ignore = [ - "warnings", - "json", - "async_resources", - "package", - "package_name", - "f", - "express", - "get_plotlyjs_version", - ] - return sorted( - [ - item - for item in dir(package) - if item == "__version__" or (item[0] not in "@_" and item not in ignore) - ] - ) - - -def test_old_dcc(): - with warns(UserWarning, match="dash_core_components package is deprecated"): - import dash_core_components as _dcc - - old_dir = filter_dir(_dcc) - new_dir = filter_dir(dcc) - - assert old_dir == new_dir - - -def test_old_table(): - with warns(UserWarning, match="dash_table package is deprecated"): - import dash_table as _dt - - old_dir = filter_dir(_dt) - new_dir = filter_dir(dash_table) - - assert old_dir == new_dir