Skip to content

feat: adding more type annotations #3254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
send_string,
)

__all__ = _components + [
__all__ = _components + [ # type: ignore[reportUnsupportedDunderAll]
"send_bytes",
"send_data_frame",
"send_file",
Expand Down
2 changes: 2 additions & 0 deletions components/dash-table/dash_table_base/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# type: ignore

import os as _os
import sys as _sys
import json
Expand Down
49 changes: 14 additions & 35 deletions components/dash-table/src/dash-table/dash/DataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -472,25 +472,14 @@ export const propTypes = {
* View the documentation examples to learn more.
*
*/
fixed_columns: PropTypes.oneOfType([
PropTypes.exact({
/**
* Example `{'headers':False, 'data':0}` No columns are fixed (the default)
*/

data: PropTypes.oneOf([0]),
headers: PropTypes.oneOf([false])
}),

PropTypes.exact({
/**
* Example `{'headers':True, 'data':1}` one column is fixed.
*/
fixed_columns: PropTypes.exact({
/**
* Example `{'headers':False, 'data':0}` No columns are fixed (the default)
*/

data: PropTypes.number,
headers: PropTypes.oneOf([true]).isRequired
})
]),
data: PropTypes.number,
headers: PropTypes.bool
}),

/**
* `fixed_rows` will "fix" the set of rows so that
Expand All @@ -505,24 +494,14 @@ export const propTypes = {
* way that your columns are rendered or sized.
* View the documentation examples to learn more.
*/
fixed_rows: PropTypes.oneOfType([
PropTypes.exact({
/**
* Example `{'headers':False, 'data':0}` No rows are fixed (the default)
*/

data: PropTypes.oneOf([0]),
headers: PropTypes.oneOf([false])
}),
PropTypes.exact({
/**
* Example `{'headers':True, 'data':1}` one row is fixed.
*/
fixed_rows: PropTypes.exact({
/**
* Example `{'headers':False, 'data':0}` No rows are fixed (the default)
*/

data: PropTypes.number,
headers: PropTypes.oneOf([true]).isRequired
})
]),
data: PropTypes.number,
headers: PropTypes.bool
}),

/**
* If `single`, then the user can select a single column or group
Expand Down
9 changes: 6 additions & 3 deletions dash/_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,9 @@ def register_callback(
# pylint: disable=too-many-locals
def wrap_func(func):

if background is not None:
if background is None:
background_key = None
else:
background_key = BaseBackgroundCallbackManager.register_func(
func,
background.get("progress") is not None,
Expand Down Expand Up @@ -520,7 +522,7 @@ def add_context(*args, **kwargs):
return to_json(response)
else:
try:
output_value = _invoke_callback(func, *func_args, **func_kwargs)
output_value = _invoke_callback(func, *func_args, **func_kwargs) # type: ignore[reportArgumentType]
except PreventUpdate as err:
raise err
except Exception as err: # pylint: disable=broad-exception-caught
Expand Down Expand Up @@ -560,7 +562,7 @@ def add_context(*args, **kwargs):
if NoUpdate.is_no_update(val):
continue
for vali, speci in (
zip(val, spec) if isinstance(spec, list) else [[val, spec]]
zip(val, spec) if isinstance(spec, list) else [[val, spec]] # type: ignore[reportArgumentType]]
):
if not NoUpdate.is_no_update(vali):
has_update = True
Expand Down Expand Up @@ -595,6 +597,7 @@ def add_context(*args, **kwargs):
dist = app.get_dist(diff_packages)
response["dist"] = dist

jsonResponse = None
try:
jsonResponse = to_json(response)
except TypeError:
Expand Down
4 changes: 2 additions & 2 deletions dash/_callback_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,15 +207,15 @@ def response(self):

@staticmethod
@has_context
def record_timing(name, duration=None, description=None):
def record_timing(name, duration, description=None):
"""Records timing information for a server resource.

:param name: The name of the resource.
:type name: string

:param duration: The time in seconds to report. Internally, this
is rounded to the nearest millisecond.
:type duration: float or None
:type duration: float

:param description: A description of the resource.
:type description: string or None
Expand Down
2 changes: 1 addition & 1 deletion dash/_grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
structure

"""
from dash.exceptions import InvalidCallbackReturnValue
from .exceptions import InvalidCallbackReturnValue
from ._utils import AttributeDict, stringify_id


Expand Down
12 changes: 7 additions & 5 deletions dash/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ def add_hook(
hook: str,
func: _t.Callable,
priority: _t.Optional[int] = None,
final=False,
data=None,
final: bool = False,
data: _t.Optional[HookDataType] = None,
):
if final:
existing = self._finals.get(hook)
Expand Down Expand Up @@ -117,7 +117,7 @@ def route(
name: _t.Optional[str] = None,
methods: _t.Sequence[str] = ("GET",),
priority: _t.Optional[int] = None,
final=False,
final: bool = False,
):
"""
Add a route to the Dash server.
Expand All @@ -136,7 +136,7 @@ def wrap(func: _t.Callable[[], _f.Response]):

return wrap

def error(self, priority: _t.Optional[int] = None, final=False):
def error(self, priority: _t.Optional[int] = None, final: bool = False):
"""Automatically add an error handler to the dash app."""

def _error(func: _t.Callable[[Exception], _t.Any]):
Expand All @@ -145,7 +145,9 @@ def _error(func: _t.Callable[[Exception], _t.Any]):

return _error

def callback(self, *args, priority: _t.Optional[int] = None, final=False, **kwargs):
def callback(
self, *args, priority: _t.Optional[int] = None, final: bool = False, **kwargs
):
"""
Add a callback to all the apps with the hook installed.
"""
Expand Down
1 change: 1 addition & 0 deletions dash/_jupyter.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# type: ignore
import asyncio
import io
import inspect
Expand Down
11 changes: 7 additions & 4 deletions dash/_pages.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import collections
import importlib
import importlib.util # to make the type checker happy
import os
import re
import sys
Expand Down Expand Up @@ -85,9 +86,11 @@ def _infer_path(module_name, template):


def _module_name_is_package(module_name):
file_path = sys.modules[module_name].__file__
return (
module_name in sys.modules
and Path(sys.modules[module_name].__file__).name == "__init__.py"
file_path
and module_name in sys.modules
and Path(file_path).name == "__init__.py"
)


Expand Down Expand Up @@ -441,8 +444,8 @@ def _import_layouts_from_pages(pages_folder):

module_name = _infer_module_name(page_path)
spec = importlib.util.spec_from_file_location(module_name, page_path)
page_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(page_module)
page_module = importlib.util.module_from_spec(spec) # type: ignore[reportArgumentType]
spec.loader.exec_module(page_module) # type: ignore[reportOptionalMemberAccess]
sys.modules[module_name] = page_module

if (
Expand Down
53 changes: 31 additions & 22 deletions dash/_patch.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
from typing import List, Union, Optional, Any


def _operation(name, location, **kwargs):
return {"operation": name, "location": location, "params": dict(**kwargs)}


_noop = object()

_KeyType = Union[str, int]


def validate_slice(obj):
def validate_slice(obj: Any):
if isinstance(obj, slice):
raise TypeError("a slice is not a valid index for patch")

Expand All @@ -19,7 +24,11 @@ class Patch:
Supported prop types: Dictionaries and lists.
"""

def __init__(self, location=None, parent=None):
def __init__(
self,
location: Optional[List[_KeyType]] = None,
parent: Optional["Patch"] = None,
):
if location is not None:
self._location = location
else:
Expand All @@ -36,11 +45,11 @@ def __getstate__(self):
def __setstate__(self, state):
vars(self).update(state)

def __getitem__(self, item) -> "Patch":
def __getitem__(self, item: _KeyType) -> "Patch":
validate_slice(item)
return Patch(location=self._location + [item], parent=self)

def __getattr__(self, item) -> "Patch":
def __getattr__(self, item: _KeyType) -> "Patch":
if item == "tolist":
# to_json fix
raise AttributeError
Expand All @@ -50,16 +59,16 @@ def __getattr__(self, item) -> "Patch":
return self._operations # type: ignore
return self.__getitem__(item)

def __setattr__(self, key, value):
def __setattr__(self, key: _KeyType, value: Any):
if key in ("_location", "_operations"):
self.__dict__[key] = value
else:
self.__setitem__(key, value)

def __delattr__(self, item):
def __delattr__(self, item: _KeyType):
self.__delitem__(item)

def __setitem__(self, key, value):
def __setitem__(self, key: _KeyType, value: Any):
validate_slice(key)
if value is _noop:
# The += set themselves.
Expand All @@ -72,11 +81,11 @@ def __setitem__(self, key, value):
)
)

def __delitem__(self, key):
def __delitem__(self, key: _KeyType):
validate_slice(key)
self._operations.append(_operation("Delete", self._location + [key]))

def __iadd__(self, other):
def __iadd__(self, other: Any):
if isinstance(other, (list, tuple)):
self.extend(other)
else:
Expand All @@ -85,25 +94,25 @@ def __iadd__(self, other):
return self
return _noop

def __isub__(self, other):
def __isub__(self, other: Any):
self._operations.append(_operation("Sub", self._location, value=other))
if not self._location:
return self
return _noop

def __imul__(self, other):
def __imul__(self, other: Any) -> "Patch":
self._operations.append(_operation("Mul", self._location, value=other))
if not self._location:
return self
return _noop

def __itruediv__(self, other):
def __itruediv__(self, other: Any):
self._operations.append(_operation("Div", self._location, value=other))
if not self._location:
return self
return _noop

def __ior__(self, other):
def __ior__(self, other: Any):
self.update(E=other)
if not self._location:
return self
Expand All @@ -115,39 +124,39 @@ def __iter__(self):
def __repr__(self):
return f"<write-only dash.Patch object at {self._location}>"

def append(self, item):
def append(self, item: Any) -> None:
"""Add the item to the end of a list"""
self._operations.append(_operation("Append", self._location, value=item))

def prepend(self, item):
def prepend(self, item: Any) -> None:
"""Add the item to the start of a list"""
self._operations.append(_operation("Prepend", self._location, value=item))

def insert(self, index, item):
def insert(self, index: int, item: Any) -> None:
"""Add the item at the index of a list"""
self._operations.append(
_operation("Insert", self._location, value=item, index=index)
)

def clear(self):
def clear(self) -> None:
"""Remove all items in a list"""
self._operations.append(_operation("Clear", self._location))

def reverse(self):
def reverse(self) -> None:
"""Reversal of the order of items in a list"""
self._operations.append(_operation("Reverse", self._location))

def extend(self, item):
def extend(self, item: Union[list, tuple]) -> None:
"""Add all the items to the end of a list"""
if not isinstance(item, (list, tuple)):
raise TypeError(f"{item} should be a list or tuple")
self._operations.append(_operation("Extend", self._location, value=item))

def remove(self, item):
def remove(self, item: Any) -> None:
"""filter the item out of a list on the frontend"""
self._operations.append(_operation("Remove", self._location, value=item))

def update(self, E=None, **F):
def update(self, E: Any = None, **F) -> None:
"""Merge a dict or keyword arguments with another dictionary"""
value = E or {}
value.update(F)
Expand All @@ -159,7 +168,7 @@ def sort(self):
"sort is reserved for future use, use brackets to access this key on your object"
)

def to_plotly_json(self):
def to_plotly_json(self) -> Any:
return {
"__dash_patch_update": "__dash_patch_update",
"operations": self._operations,
Expand Down
Loading