Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Enable strict type checking #7497

Merged
merged 34 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b7037ec
Align types of linked_properties
philippjfr Nov 14, 2024
6e2479b
Begin typing everything
philippjfr Nov 15, 2024
d887943
More typing
philippjfr Nov 15, 2024
19b786f
More fixes
philippjfr Nov 15, 2024
e051df1
Add Tabulator types
philippjfr Nov 15, 2024
95e0b52
More types
philippjfr Nov 15, 2024
750a217
Small fix
philippjfr Nov 15, 2024
9e602c9
More types
philippjfr Nov 15, 2024
396ad6d
More types
philippjfr Nov 16, 2024
71912de
Upgrade type definitions and apply pyupgrade
philippjfr Nov 16, 2024
52bef7c
More updates
philippjfr Nov 16, 2024
b865a10
Update type imports for generics
philippjfr Nov 16, 2024
d9e1f1f
Add more types
philippjfr Nov 16, 2024
949b37c
More minor fixes
philippjfr Nov 16, 2024
6e38a3c
More types
philippjfr Nov 17, 2024
2158148
More types
philippjfr Nov 17, 2024
5264b2f
More types
philippjfr Nov 17, 2024
60b9eb4
More types
philippjfr Nov 17, 2024
ef2fd79
Fix up type error
philippjfr Nov 17, 2024
4b8da9b
Fix tests
philippjfr Nov 17, 2024
04ca6fe
Apply suggestions from code review
philippjfr Nov 17, 2024
19d68bf
Fix up type
philippjfr Nov 17, 2024
5218def
fix textual tests
philippjfr Nov 17, 2024
c867531
Merge branch 'main' into linked_props_types
philippjfr Nov 18, 2024
1a7f4d1
Fix JupyterServerContext
philippjfr Nov 18, 2024
197ff5a
Back out of JupyterServerContext
philippjfr Nov 18, 2024
daa8493
Address review comments
philippjfr Nov 18, 2024
060f415
revert version upgrade
philippjfr Nov 18, 2024
46c1107
Apply suggestions from code review
philippjfr Dec 2, 2024
770be06
Resolve review comments
philippjfr Dec 2, 2024
8c7443a
Small fix
philippjfr Dec 2, 2024
875aeca
Fix types
philippjfr Dec 2, 2024
b8253e3
Another fix
philippjfr Dec 2, 2024
16bd060
Merge branch 'main' into linked_props_types
philippjfr Dec 2, 2024
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
36 changes: 19 additions & 17 deletions doc/generate_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,39 +57,40 @@ def write_file(name, text, opts):
"""Write the output file for module/package <name>."""
if opts.dryrun:
return
fname = os.path.join(opts.destdir, "{}.{}".format(name, opts.suffix))
fname = os.path.join(opts.destdir, f"{name}.{opts.suffix}")
if not opts.force and os.path.isfile(fname):
print('File %s already exists, skipping.' % fname)
print(f'File {fname} already exists, skipping.')
else:
print('Creating file %s.' % fname)
print(f'Creating file {fname}.')
f = open(fname, 'w')
f.write(text)
f.close()

def format_heading(level, text):
"""Create a heading of <level> [1, 2 or 3 supported]."""
underlining = ['=', '-', '~', ][level-1] * len(text)
return '{}\n{}\n\n'.format(text, underlining)
return f'{text}\n{underlining}\n\n'

def format_directive(module, package=None):
"""Create the automodule directive and add the options."""
directive = '.. automodule:: %s\n' % makename(package, module)
module_name = makename(package, module)
directive = f'.. automodule:: %s{module_name}'
for option in OPTIONS:
directive += ' :%s:\n' % option
directive += f' :{option}:\n'
return directive

def create_module_file(package, module, opts):
"""Build the text of the file and write the file."""

text = format_heading(1, '%s Module' % module)
text += format_heading(2, ':mod:`%s` Module' % module)
text = format_heading(1, f'{module} Module')
text += format_heading(2, f':mod:`{module}` Module')
text += format_directive(module, package)
write_file(makename(package, module), text, opts)

def create_package_file(root, master_package, subroot, py_files, opts, subs):
"""Build the text of the file and write the file."""
package = os.path.split(root)[-1]
text = format_heading(1, '{}.{} Package'.format(master_package, package))
text = format_heading(1, f'{master_package}.{package} Package')
text += '\n---------\n\n'
# add each package's module
for py_file in py_files:
Expand All @@ -99,9 +100,9 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs):
py_file = os.path.splitext(py_file)[0]
py_path = makename(subroot, py_file)
if is_package:
heading = ':mod:`%s` Package' % package
heading = f':mod:`{package}` Package'
else:
heading = ':mod:`%s` Module' % py_file
heading = f':mod:`{py_file}` Module'
text += format_heading(2, heading)
text += '\n\n'
text += format_directive(is_package and subroot or py_path, master_package)
Expand All @@ -113,8 +114,9 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs):
if subs:
text += format_heading(2, 'Subpackages')
text += '.. toctree::\n\n'
subpackage_name = makename(master_package, subroot)
for sub in subs:
text += ' {}.{}\n'.format(makename(master_package, subroot), sub)
text += f' {subpackage_name}.{sub}\n'
text += '\n'

write_file(makename(master_package, subroot), text, opts)
Expand All @@ -123,9 +125,9 @@ def create_modules_toc_file(master_package, modules, opts, name='modules'):
"""
Create the module's index.
"""
text = format_heading(1, '%s Modules' % opts.header)
text = format_heading(1, f'{opts.header} Modules')
text += '.. toctree::\n'
text += ' :maxdepth: %s\n\n' % opts.maxdepth
text += f' :maxdepth: {opts.maxdepth}\n\n'

modules.sort()
prev_module = ''
Expand All @@ -134,7 +136,7 @@ def create_modules_toc_file(master_package, modules, opts, name='modules'):
if module.startswith(prev_module + '.'):
continue
prev_module = module
text += ' %s\n' % module
text += f' {module}\n'

write_file(name, text, opts)

Expand Down Expand Up @@ -261,9 +263,9 @@ def main():
excludes = normalize_excludes(rootpath, excludes)
recurse_tree(rootpath, excludes, opts)
else:
print('%s is not a valid output destination directory.' % opts.destdir)
print(f'{opts.destdir} is not a valid output destination directory.')
else:
print('%s is not a valid directory.' % rootpath)
print(f'{rootpath} is not a valid directory.')


if __name__ == '__main__':
Expand Down
8 changes: 3 additions & 5 deletions panel/_param.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
from __future__ import annotations

from typing import (
TYPE_CHECKING, Any, Literal, TypeAlias, cast,
Any, Literal, TypeAlias, cast,
)

from bokeh.core.enums import enumeration
from param import Parameter, _is_number

if TYPE_CHECKING:
MarginType: TypeAlias = int | tuple[int, int] | tuple[int, int, int] | tuple[int, int, int, int]

AlignmentType = Literal["auto", "start", "center", "end"]
Alignment = enumeration(AlignmentType)
MarginType: TypeAlias = int | tuple[int, int] | tuple[int, int, int] | tuple[int, int, int, int]
philippjfr marked this conversation as resolved.
Show resolved Hide resolved


class Align(Parameter):
Expand Down Expand Up @@ -87,7 +85,7 @@ def _validate_value(self, val: Any, allow_None: bool) -> None:
)

def _validate_length(self, val: Any) -> None:
if not isinstance(val, tuple) or (1 < len(val) < 5):
if not isinstance(val, tuple) or len(val) in (2, 4):
return
raise ValueError(
f'Margin parameter {self.name!r} only takes integer and '
Expand Down
4 changes: 2 additions & 2 deletions panel/chat/feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ def prompt_user(
timeout_button_params : dict | None
Additional parameters to pass to the timeout button.
"""
async def _prepare_prompt(*_) -> None:
async def _prepare_prompt(*args) -> None:
input_button_params = button_params or {}
if "name" not in input_button_params:
input_button_params["name"] = "Submit"
Expand All @@ -868,7 +868,7 @@ async def _prepare_prompt(*_) -> None:
send_kwargs["user"] = "Input"
self.send(form, respond=False, **send_kwargs)

for __ in range(timeout * 10): # sleeping for 0.1 seconds
for _ in range(timeout * 10): # sleeping for 0.1 seconds
is_fulfilled = predicate(component) if predicate else True
submit_button.disabled = not is_fulfilled
if submit_button.clicks > 0:
Expand Down
7 changes: 4 additions & 3 deletions panel/chat/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,10 @@ def _link_disabled_loading(self, obj: Viewable):
Link the disabled and loading attributes of the chat box to the
given object.
"""
for attr in ["disabled", "loading"]:
setattr(obj, attr, getattr(self, attr))
self.link(obj, callbacks=None, bidirectional=False, **{attr: attr})
mapping: dict[str, Any] = {"disabled": "disabled", "loading": "loading"}
values = {p: getattr(self, p) for p in mapping}
self.param.update(values)
self.link(obj, **mapping)

@param.depends("width", watch=True)
def _update_input_width(self):
Expand Down
4 changes: 2 additions & 2 deletions panel/command/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from .oauth_secret import OAuthSecret
from .serve import Serve

description = """\
_DESCRIPTION = """\
Found a Bug or Have a Feature Request?
Open an issue at: https://github.com/holoviz/panel/issues

Expand Down Expand Up @@ -66,7 +66,7 @@ def main(args: list[str] | None = None):
from bokeh.command.subcommands import all as bokeh_commands
parser = argparse.ArgumentParser(
prog="panel", epilog="See '<command> --help' to read about a specific subcommand.",
description=description, formatter_class=argparse.RawTextHelpFormatter
description=_DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-v', '--version', action='version', version=__version__)
subs = parser.add_subparsers(help="Sub-commands")
Expand Down
2 changes: 1 addition & 1 deletion panel/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ def _update_esm(self):

@property
def _linked_properties(self) -> tuple[str, ...]:
return tuple(p for p in self._data_model.properties() if p not in ('js_property_callbacks',))
return tuple(p for p in self._data_model.properties() if p != 'js_property_callbacks')

def _get_properties(self, doc: Document | None) -> dict[str, Any]:
props = super()._get_properties(doc)
Expand Down
4 changes: 2 additions & 2 deletions panel/io/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ def build_applications(
slug = slug if slug.startswith('/') else '/'+slug

# Handle other types of apps using a custom handler
for chandler in (custom_handlers or ()):
new_app = chandler(slug, app)
for custom_handler in (custom_handlers or ()):
new_app = custom_handler(slug, app)
if app is not None:
break
else:
Expand Down
8 changes: 5 additions & 3 deletions panel/io/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
from collections.abc import Callable, Mapping
from functools import partial, wraps
from html import escape
from typing import TYPE_CHECKING, Any, TypedDict
from typing import (
TYPE_CHECKING, Any, Literal, TypedDict,
)
from urllib.parse import urlparse

import bokeh
Expand Down Expand Up @@ -611,8 +613,8 @@ class ComponentResourceHandler(StaticFileHandler):
'_css', '_js', 'base_css', 'css', '_stylesheets', 'modifiers', '_bundle_path'
]

def initialize(self, path: str | None = None, default_filename: str | None = None):
self.root = path or 'root'
def initialize(self, path: str | Literal['root'] = 'root', default_filename: str | None = None):
self.root = path
self.default_filename = default_filename

def parse_url_path(self, path: str) -> str:
Expand Down
2 changes: 1 addition & 1 deletion panel/models/tabulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from ..util import classproperty
from .layout import HTMLBox

TABULATOR_VERSION = "6.3.0"
TABULATOR_VERSION = "6.2.5"

JS_SRC = f"{config.npm_cdn}/tabulator-tables@{TABULATOR_VERSION}/dist/js/tabulator.min.js"
MOMENT_SRC = f"{config.npm_cdn}/luxon/build/global/luxon.min.js"
Expand Down
9 changes: 4 additions & 5 deletions panel/widgets/codeeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,10 @@ def _get_model(
self, doc: Document, root: Model | None = None,
parent: Model | None = None, comm: Comm | None = None
) -> Model:
if self._widget_type is None:
CodeEditor._widget_type = lazy_load(
'panel.models.ace', 'AcePlot', isinstance(comm, JupyterComm),
root, ext='codeeditor'
)
CodeEditor._widget_type = lazy_load(
hoxbro marked this conversation as resolved.
Show resolved Hide resolved
'panel.models.ace', 'AcePlot', isinstance(comm, JupyterComm),
root, ext='codeeditor'
)
return super()._get_model(doc, root, parent, comm)

def _update_disabled(self, *events: param.parameterized.Event):
Expand Down
Loading