From c42ae53d89671c969d71befe42387f04a68a7681 Mon Sep 17 00:00:00 2001 From: Isabel Zimmerman Date: Fri, 8 Dec 2023 16:13:13 -0600 Subject: [PATCH] update to latest pyright (posit-dev/positron-python#278) * update to pyright 1.1.339 * a lot of the function signatures we are vendoring in change between Python versions, so we will end up with CI errors on various Python versions unless we ignore the `reportIncompatibleMethodOverride` errors. if this becomes an ongoing issue, let's move this ignore to a project level. --- .../pythonFiles/positron/inspectors.py | 13 ++------ .../pythonFiles/positron/positron_ipkernel.py | 30 +++++++++---------- .../pythonFiles/positron/positron_jedilsp.py | 6 ++-- .../pythonFiles/positron/pydoc.py | 12 ++++---- .../pythonFiles/tests/positron/conftest.py | 3 +- .../pythonFiles/tests/positron/test_plots.py | 15 +++++----- .../pythonFiles/tests/test_create_venv.py | 2 +- .../pythonFiles/vscode_pytest/__init__.py | 2 +- 8 files changed, 37 insertions(+), 46 deletions(-) diff --git a/extensions/positron-python/pythonFiles/positron/inspectors.py b/extensions/positron-python/pythonFiles/positron/inspectors.py index a91c1db0c8e..2c542d6b7e2 100644 --- a/extensions/positron-python/pythonFiles/positron/inspectors.py +++ b/extensions/positron-python/pythonFiles/positron/inspectors.py @@ -13,15 +13,9 @@ import types import uuid from abc import ABC, abstractmethod -from collections.abc import ( - Mapping, - MutableMapping, - MutableSequence, - MutableSet, - Sequence, - Set, -) +from collections.abc import Mapping, MutableMapping, MutableSequence, MutableSet, Sequence, Set from typing import ( + TYPE_CHECKING, Any, Callable, Collection, @@ -35,7 +29,6 @@ Protocol, Sized, Tuple, - TYPE_CHECKING, Type, TypeVar, Union, @@ -567,7 +560,7 @@ def copy(self, value: torch.Tensor) -> torch.Tensor: class _BaseMapInspector(PositronInspector[MT], ABC): - def get_kind(self, value: Mapping) -> str: + def get_kind(self, value: MT) -> str: return "map" @abstractmethod diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipkernel.py b/extensions/positron-python/pythonFiles/positron/positron_ipkernel.py index cba006c025b..6efbcf66fc7 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipkernel.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipkernel.py @@ -4,32 +4,32 @@ """ Positron extensions to the iPython Kernel.""" from __future__ import annotations + import asyncio import logging import warnings from collections.abc import Iterable from itertools import chain -from typing import Any, Callable, Container, Dict, Mapping, Optional, Set, Tuple, Type +from typing import Any, Callable, Container, Coroutine, Dict, Mapping, Optional, Set, Tuple, Type +import traitlets from ipykernel.comm.manager import CommManager from ipykernel.ipkernel import IPythonKernel from ipykernel.kernelapp import IPKernelApp -from ipykernel.zmqshell import ZMQInteractiveShell, ZMQDisplayPublisher -from IPython.core import oinspect +from ipykernel.zmqshell import ZMQDisplayPublisher, ZMQInteractiveShell +from IPython.core import oinspect, page from IPython.core.interactiveshell import InteractiveShell -from IPython.core.magic import Magics, line_magic, magics_class, needs_local_scope, MagicsManager -from IPython.core import page +from IPython.core.magic import Magics, MagicsManager, line_magic, magics_class, needs_local_scope from IPython.utils import PyColorize -import traitlets from .dataviewer import DataViewerService -from .variables import VariablesService from .frontend import FrontendService from .help import HelpService from .inspectors import get_inspector from .lsp import LSPService from .plots import PositronDisplayPublisherHook from .utils import cancel_tasks, create_task +from .variables import VariablesService POSITRON_DATA_VIEWER_COMM = "positron.dataViewer" """The comm channel target_name for Positron's Data Viewer""" @@ -69,12 +69,11 @@ class PositronIPythonInspector(oinspect.Inspector): def pinfo( self, obj: Any, - oname: str, - formatter: Callable[[str], Dict[str, str]], - info: oinspect.OInfo, - *, - detail_level: int, - enable_html_pager: bool, + oname: str = "", + formatter: Optional[Callable[[str], Dict[str, str]]] = None, + info: Optional[oinspect.OInfo] = None, + detail_level: int = 0, + enable_html_pager: bool = True, omit_sections: Container[str] = (), ) -> None: # Intercept `%pinfo obj` / `obj?` calls, and instead use Positron's help service @@ -106,7 +105,7 @@ class PositronShell(ZMQInteractiveShell): ).tag(config=True) @traitlets.observe("colors") - def init_inspector(self, change: Optional[traitlets.Bunch] = None) -> None: + def init_inspector(self, changes: Optional[traitlets.Bunch] = None) -> None: # Override to pass `parent=self` to the inspector self.inspector = self.inspector_class( oinspect.InspectColors, @@ -160,7 +159,6 @@ class PositronIPyKernel(IPythonKernel): shell: PositronShell comm_manager: CommManager - execution_count: int shell_class: PositronShell = traitlets.Type(PositronShell, klass=InteractiveShell) # type: ignore @@ -230,7 +228,7 @@ def start(self) -> None: super().start() self.help_service.start() - async def do_shutdown(self, restart: bool) -> Dict[str, Any]: + async def do_shutdown(self, restart: bool) -> Dict[str, str | bool]: # type: ignore ReportIncompatibleMethodOverride """ Handle kernel shutdown. """ diff --git a/extensions/positron-python/pythonFiles/positron/positron_jedilsp.py b/extensions/positron-python/pythonFiles/positron/positron_jedilsp.py index d2db1f6ab72..2b8949062aa 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_jedilsp.py +++ b/extensions/positron-python/pythonFiles/positron/positron_jedilsp.py @@ -122,7 +122,7 @@ class HelpTopicRequest: class PositronJediLanguageServerProtocol(JediLanguageServerProtocol): - def get_message_type(self, method: str) -> Optional[Type]: + def get_message_type(self, method: str) -> Optional[Type]: # type: ignore # Overriden to include custom Positron LSP messages. # Doing so ensures that the corresponding feature function receives `params` of the correct type. if method == _HELP_TOPIC: @@ -137,7 +137,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.loop: asyncio.AbstractEventLoop - self.lsp: PositronJediLanguageServerProtocol + self.lsp: PositronJediLanguageServerProtocol # type: ignore reportIncompatibleVariableOverride # LSP comm used to notify the frontend when the server is ready self._comm: Optional[BaseComm] = None @@ -363,7 +363,7 @@ def positron_completion( has_whitespace = " " in trimmed_line if server.kernel is not None and not (is_completing_attribute or has_whitespace): # Cast type from traitlets.Dict to typing.Dict - magic_commands = cast(Dict[str, Callable], server.kernel.shell.magics_manager.lsmagic()) + magic_commands = cast(Dict[str, Any], server.kernel.shell.magics_manager.lsmagic()) chars_before_cursor = trimmed_line[: params.position.character] diff --git a/extensions/positron-python/pythonFiles/positron/pydoc.py b/extensions/positron-python/pythonFiles/positron/pydoc.py index c1bbec6b2c6..92638f9787e 100644 --- a/extensions/positron-python/pythonFiles/positron/pydoc.py +++ b/extensions/positron-python/pythonFiles/positron/pydoc.py @@ -218,7 +218,7 @@ def page(self, title, contents): ) # --- End Positron --- - def heading(self, title: str, extras="") -> str: + def heading(self, title: str, extras="") -> str: # type: ignore ReportIncompatibleMethodOverride """Format a page heading.""" # Simplified version of pydoc.HTMLDoc.heading that doesn't use tables lines = [f"

{title}

"] @@ -227,7 +227,7 @@ def heading(self, title: str, extras="") -> str: result = "\n".join(lines) return result - def section( + def section( # type: ignore self, title: str, cls: str, @@ -236,7 +236,7 @@ def section( prelude="", marginalia=None, gap=None, - ) -> str: + ) -> str: # type: ignore ReportIncompatibleMethodOverride """Format a section with a heading.""" # Simplified version of pydoc.HTMLDoc.section that doesn't use tables if width is not None: @@ -264,7 +264,7 @@ def bigsection(self, *args): return self.section(*args) # Heavily customized version of pydoc.HTMLDoc.docmodule - def docmodule(self, object: ModuleType, *_): + def docmodule(self, object: ModuleType, *_): # type: ignore reportIncompatibleMethodOverride obj_name = object.__name__ # Create the heading, with links to each parent module @@ -338,7 +338,7 @@ def docmodule(self, object: ModuleType, *_): return result # Heavily customized version of pydoc.HTMLDoc.docclass - def docclass(self, obj: Type, name=None, *_): + def docclass(self, obj: Type, name=None, *_): # type: ignore reportIncompatibleMethodOverride obj_name = name or obj.__name__ # Separate the class's members into attributes and methods @@ -497,7 +497,7 @@ def markup(self, text, escape=None, funcs={}, classes={}, methods={}): return text # as is from pydoc.HTMLDoc to port Python 3.11 breaking CSS changes - def index(self, dir, shadowed: Optional[Dict[str, int]] = None): + def index(self, dir, shadowed: Optional[Dict[str, int]] = None): # type: ignore reportIncompatibleMethodOverride """Generate an HTML index for a directory of modules.""" modpkgs = [] if shadowed is None: diff --git a/extensions/positron-python/pythonFiles/tests/positron/conftest.py b/extensions/positron-python/pythonFiles/tests/positron/conftest.py index cc66e02a454..8d32aa35293 100644 --- a/extensions/positron-python/pythonFiles/tests/positron/conftest.py +++ b/extensions/positron-python/pythonFiles/tests/positron/conftest.py @@ -4,7 +4,6 @@ import pytest from IPython.conftest import get_ipython from IPython.terminal.interactiveshell import TerminalInteractiveShell - from positron.positron_ipkernel import PositronIPyKernel @@ -17,7 +16,7 @@ def __init__(self, *args, **kwargs): self.messages = [] super().__init__(*args, **kwargs) - def publish_msg(self, msg_type, **msg): + def publish_msg(self, msg_type, **msg): # type: ignore ReportIncompatibleMethodOverride msg["msg_type"] = msg_type self.messages.append(msg) diff --git a/extensions/positron-python/pythonFiles/tests/positron/test_plots.py b/extensions/positron-python/pythonFiles/tests/positron/test_plots.py index a8900c12e8e..2af341473d4 100644 --- a/extensions/positron-python/pythonFiles/tests/positron/test_plots.py +++ b/extensions/positron-python/pythonFiles/tests/positron/test_plots.py @@ -1,22 +1,21 @@ import codecs import pickle from pathlib import Path -from typing import cast, Iterable +from typing import Iterable, cast import matplotlib import matplotlib.pyplot as plt import pytest from IPython.conftest import get_ipython from IPython.core.formatters import DisplayFormatter +from matplotlib.axes import Axes from matplotlib.figure import Figure from matplotlib.testing.compare import compare_images from matplotlib_inline.backend_inline import configure_inline_support - from positron.plots import BASE_DPI, PositronDisplayPublisherHook from .conftest import DummyComm - PLOT_DATA = [1, 2] @@ -113,8 +112,9 @@ def test_hook_call(hook: PositronDisplayPublisherHook, images_path: Path) -> Non fig.savefig(str(actual)) # Create the reference figure - fig_ref: plt.figure.Figure = plt.figure() - fig_ref.subplots().plot(PLOT_DATA) + fig_ref = cast(Figure, plt.figure()) + fig_axes = cast(Axes, fig_ref.subplots()) + fig_axes.plot(PLOT_DATA) expected = images_path / "test-hook-call-expected.png" fig_ref.savefig(str(expected)) @@ -210,8 +210,9 @@ def test_hook_render(figure_comm: DummyComm, images_path: Path) -> None: width_in = width_px / BASE_DPI height_in = height_px / BASE_DPI - fig_ref: plt.figure.Figure = plt.figure() - fig_ref.subplots().plot([1, 2]) + fig_ref = cast(Figure, plt.figure()) + fig_axes = cast(Axes, fig_ref.subplots()) + fig_axes.plot([1, 2]) fig_ref.set_dpi(dpi) fig_ref.set_size_inches(width_in, height_in) diff --git a/extensions/positron-python/pythonFiles/tests/test_create_venv.py b/extensions/positron-python/pythonFiles/tests/test_create_venv.py index 772fc02708f..350fa5ca997 100644 --- a/extensions/positron-python/pythonFiles/tests/test_create_venv.py +++ b/extensions/positron-python/pythonFiles/tests/test_create_venv.py @@ -242,7 +242,7 @@ def redirect_io(stream: str, new_stream): class CustomIO(io.TextIOWrapper): """Custom stream object to replace stdio.""" - name: str = "customio" + name: str = "customio" # type: ignore ReportIncompatibleMethodOverride (remove once updated upstream) def __init__(self, name: str, encoding="utf-8", newline=None): self._buffer = io.BytesIO() diff --git a/extensions/positron-python/pythonFiles/vscode_pytest/__init__.py b/extensions/positron-python/pythonFiles/vscode_pytest/__init__.py index 6f5687357f1..8d585c35963 100644 --- a/extensions/positron-python/pythonFiles/vscode_pytest/__init__.py +++ b/extensions/positron-python/pythonFiles/vscode_pytest/__init__.py @@ -689,7 +689,7 @@ def post_response(cwd: str, session_node: TestNode) -> None: class PathEncoder(json.JSONEncoder): """A custom JSON encoder that encodes pathlib.Path objects as strings.""" - def default(self, obj): + def default(self, obj): # type: ignore ReportIncompatibleMethodOverride (remove once updated upstream) if isinstance(obj, pathlib.Path): return os.fspath(obj) return super().default(obj)