8000 Add runtime type annotations to IPython.utils via MonkeyType by Carreau · Pull Request #15146 · ipython/ipython · GitHub
[go: up one dir, main page]

Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ venv*/
*.code-workspace
.history
.vscode

# MonkeyType runtime type trace database
monkeytype.sqlite3
2 changes: 1 addition & 1 deletion IPython/core/tbtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def _tokens_filename(
]
else:
name = util_path.compress_user(
py3compat.cast_unicode(file, util_path.fs_encoding)
py3compat.cast_unicode(file or "", util_path.fs_encoding)
)
if lineno is None:
return [
Expand Down
12 changes: 8 additions & 4 deletions IPython/terminal/prompts.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
"""Terminal input and output prompts."""

from pygments.token import Token
from pygments.token import _TokenType, Token
import sys

from IPython.core.displayhook import DisplayHook

from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens
from prompt_toolkit.shortcuts import print_formatted_text
from prompt_toolkit.enums import EditingMode
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple

if TYPE_CHECKING:
from IPython.terminal.interactiveshell import TerminalInteractiveShell


class Prompts:
def __init__(self, shell):
def __init__(self, shell: "TerminalInteractiveShell"):
self.shell = shell

def vi_mode(self):
Expand Down Expand Up @@ -84,7 +88,7 @@ def rewrite_prompt_tokens(self):
(Token.Prompt, ('-' * (width - 2)) + '> '),
]

def out_prompt_tokens(self):
def out_prompt_tokens(self) -> List[Tuple[_TokenType, str]]:
return [
(Token.OutPrompt, 'Out['),
(Token.OutPromptNum, str(self.shell.execution_count - 1)),
Expand Down Expand Up @@ -128,7 +132,7 @@ def write_output_prompt(self):
else:
sys.stdout.write(prompt_txt)

def write_format_data(self, format_dict, md_dict=None) -> None:
def write_format_data(self, format_dict: Dict[str, str], md_dict: Optional[Dict[Any, Any]]=None) -> None:
assert self.shell is not None
if self.shell.mime_renderers:

Expand Down
12 changes: 6 additions & 6 deletions IPython/terminal/shortcuts/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import re
import signal
import sys
from typing import Dict, Union
from typing import Optional, Dict, Union
from collections.abc import Callable

from prompt_toolkit.application.current import get_app
Expand Down Expand Up @@ -40,7 +40,7 @@ def cursor_in_leading_ws():
return (not before) or before.isspace()


def has_focus(value: FocusableElement):
def has_focus(value: FocusableElement) -> Condition:
"""Wrapper around has_focus adding a nice `__name__` to tester function"""
tester = has_focus_impl(value).func
tester.__name__ = f"is_focused({value})"
Expand Down Expand Up @@ -102,7 +102,7 @@ def all_quotes_paired(quote, buf):
_following_text_cache: Dict[Union[str, Callable], Condition] = {}


def preceding_text(pattern: Union[str, Callable]):
def preceding_text(pattern: Union[str, Callable]) -> Condition:
if pattern in _preceding_text_cache:
return _preceding_text_cache[pattern]

Expand All @@ -129,7 +129,7 @@ def _preceding_text():
return condition


def following_text(pattern):
def following_text(pattern: str) -> Condition:
try:
return _following_text_cache[pattern]
except KeyError:
Expand Down Expand Up @@ -284,7 +284,7 @@ def __call__(self):
}


def eval_node(node: Union[ast.AST, None]):
def eval_node(node: Union[ast.AST, None]) -> Optional[Filter]:
if node is None:
return None
if isinstance(node, ast.Expression):
Expand Down Expand Up @@ -315,7 +315,7 @@ def eval_node(node: Union[ast.AST, None]):
raise ValueError("Unhandled node", ast.dump(node))


def filter_from_string(code: str):
def filter_from_string(code: str) -> Union[Condition, Filter]:
expression = ast.parse(code, mode="eval")
return eval_node(expression)

Expand Down
10 changes: 6 additions & 4 deletions IPython/testing/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

# Expose the unittest-driven decorators
from .ipunittest import ipdoctest, ipdocstring
from _pytest.mark.structures import MarkDecorator
from typing import Optional

def skipif(skip_condition, msg=None):
def skipif(skip_condition: bool, msg: Optional[str]=None) -> MarkDecorator:
"""Make function raise SkipTest exception if skip_condition is true

Parameters
Expand Down Expand Up @@ -39,7 +41,7 @@ def skipif(skip_condition, msg=None):

# A version with the condition set to true, common case just to attach a message
# to a skip decorator
def skip(msg=None):
def skip(msg: Optional[str]=None) -> MarkDecorator:
"""Decorator factory - mark a test function for skipping from test suite.

Parameters
Expand All @@ -61,15 +63,15 @@ def skip(msg=None):
return skipif(True, msg)


def onlyif(condition, msg):
def onlyif(condition: bool, msg: str) -> MarkDecorator:
"""The reverse from skipif, see skipif for details."""

return skipif(not condition, msg)


# -----------------------------------------------------------------------------
# Utility functions for decorators
def module_not_available(module):
def module_not_available(module: str) -> bool:
"""Can module be imported? Returns true if module does NOT import.

This is used to make a decorator to skip tests that require module to be
Expand Down
2 changes: 1 addition & 1 deletion IPython/testing/ipunittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class Doc2UnitTester:
no attempt is made at turning it into a singleton, there is no need for
that).
"""
def __init__(self, verbose=False):
def __init__(self, verbose: bool=False):
"""New decorator.

Parameters
Expand Down
7 changes: 4 additions & 3 deletions IPython/testing/plugin/pytest_ipdoctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from _pytest.compat import safe_getattr
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.fixtures import TopRequest

try:
from _pytest.fixtures import TopRequest as FixtureRequest
Expand Down Expand Up @@ -300,7 +301,7 @@ def from_parent( # type: ignore
name: str,
runner: "IPDocTestRunner",
dtest: "doctest.DocTest",
):
) -> "IPDoctestItem":
# incompatible signature due to imposed limits on subclass
"""The public named constructor."""
return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest)
Expand Down Expand Up @@ -475,7 +476,7 @@ def _get_flag_lookup() -> Dict[str, int]:
)


def get_optionflags(parent):
def get_optionflags(parent: "IPDoctestModule") -> int:
optionflags_str = parent.config.getini("ipdoctest_optionflags")
flag_lookup_table = _get_flag_lookup()
flag_acc = 0
Expand All @@ -484,7 +485,7 @@ def get_optionflags(parent):
return fl 46C4 ag_acc


def _get_continue_on_failure(config):
def _get_continue_on_failure(config: Config) -> bool:
continue_on_failure = config.getvalue("ipdoctest_continue_on_failure")
if continue_on_failure:
# We need to turn off this if we use pdb since we should stop at
Expand Down
3 changes: 2 additions & 1 deletion IPython/testing/skipdoctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
numpy and sympy if they're present. Since this decorator is used in core parts
of IPython, it's in a separate module so that running IPython doesn't trigger
those imports."""
from typing import Any, Callable

# Copyright (C) IPython Development Team
# Distributed under the terms of the Modified BSD License.


def skip_doctest(f):
def skip_doctest(f: Any) -> Any:
"""Decorator - mark a function or method for skipping its doctest.

This decorator allows you to mark a function whose docstring you wish to
Expand Down
22 changes: 12 additions & 10 deletions IPython/testing/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

from . import decorators as dec
from . import skipdoctest
from types import TracebackType
from typing import List, Optional, Tuple, Type


# The docstring for full_path doctests differently on win32 (different path
Expand Down Expand Up @@ -67,7 +69,7 @@ def full_path(startPath: str, files: list[str]) -> list[str]:
return [ os.path.join(base,f) for f in files ]


def parse_test_output(txt):
def parse_test_output(txt: str) -> Tuple[int, int]:
"""Parse the output of a test run and return errors, failures.

Parameters
Expand Down Expand Up @@ -113,7 +115,7 @@ def parse_test_output(txt):
parse_test_output.__test__ = False


def default_argv():
def default_argv() -> List[str]:
"""Return a valid default argv for creating testing instances of ipython"""

return [
Expand All @@ -126,7 +128,7 @@ def default_argv():
]


def default_config():
def default_config() -> Config:
"""Return a config object with good defaults for testing."""
config = Config()
config.TerminalInteractiveShell.colors = "nocolor"
Expand All @@ -139,7 +141,7 @@ def default_config():
return config


def get_ipython_cmd(as_string=False):
def get_ipython_cmd(as_string: bool=False) -> List[str]:
"""
Return appropriate IPython command line name. By default, this will return
a list that can be used with subprocess.Popen, for example, but passing
Expand All @@ -157,7 +159,7 @@ def get_ipython_cmd(as_string=False):

return ipython_cmd

def ipexec(fname, options=None, commands=()):
def ipexec(fname: str, options: Optional[List[str]]=None, commands: Tuple[str, ...]=()) -> Tuple[str, str]:
"""Utility to call 'ipython filename'.

Starts IPython with a minimal and safe configuration to make startup as fast
Expand Down Expand Up @@ -215,8 +217,8 @@ def ipexec(fname, options=None, commands=()):
return out, err


def ipexec_validate(fname, expected_out, expected_err='',
options=None, commands=()):
def ipexec_validate(fname: str, expected_out: str, expected_err: str='',
options: Optional[List[str]]=None, commands: Tuple[str, ...]=()):
"""Utility to call 'ipython filename' and validate output/error.

This function raises an AssertionError if the validation fails.
Expand Down Expand Up @@ -267,7 +269,7 @@ class TempFileMixin(unittest.TestCase):

Meant as a mixin class for test cases."""

def mktmp(self, src, ext='.py'):
def mktmp(self, src: str, ext: str='.py'):
"""Make a valid python temp file."""
fname = temp_pyfile(src, ext)
if not hasattr(self, 'tmps'):
Expand Down Expand Up @@ -318,7 +320,7 @@ class AssertPrints:
abcd
def
"""
def __init__(self, s, channel='stdout', suppress=True):
def __init__(self, s: str, channel: str='stdout', suppress: bool=True):
self.s = s
if isinstance(self.s, (str, _re_type)):
self.s = [self.s]
Expand All @@ -331,7 +333,7 @@ def __enter__(self):
self.tee = Tee(self.buffer, channel=self.channel)
setattr(sys, self.channel, self.buffer if self.suppress else self.tee)

def __exit__(self, etype, value, traceback):
def __exit__(self, etype: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType]):
__tracebackhide__ = True

try:
Expand Down
14 changes: 8 additions & 6 deletions IPython/utils/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import sys
from io import StringIO
from types import TracebackType
from typing import Any, List, Optional, Type

#-----------------------------------------------------------------------------
# Classes and functions
Expand Down Expand Up @@ -72,7 +74,7 @@ class CapturedIO:
above in the same order, and can be invoked simply via ``c()``.
"""

def __init__(self, stdout, stderr, outputs=None):
def __init__(self, stdout: StringIO, stderr: StringIO, outputs: Optional[List[Any]]=None):
self._stdout = stdout
self._stderr = stderr
if outputs is None:
Expand All @@ -83,14 +85,14 @@ def __str__(self):
return self.stdout

@property
def stdout(self):
def stdout(self) -> str:
"Captured standard output"
if not self._stdout:
return ''
return self._stdout.getvalue()

@property
def stderr(self):
def stderr(self) -> str:
"Captured standard error"
if not self._stderr:
return ''
Expand Down Expand Up @@ -127,13 +129,13 @@ class capture_output:
stderr = True
display = True

def __init__(self, stdout=True, stderr=True, display=True):
def __init__(self, stdout: bool=True, stderr: bool=True, display: bool=True):
self.stdout = stdout
self.stderr = stderr
self.display = display
self.shell = None

def __enter__(self):
def __enter__(self) -> CapturedIO:
from IPython.core.getipython import get_ipython
from IPython.core.displaypub import CapturingDisplayPublisher
from IPython.core.displayhook import CapturingDisplayHook
Expand Down Expand Up @@ -162,7 +164,7 @@ def __enter__(self):

return CapturedIO(stdout, stderr, outputs)

def __exit__(self, exc_type, exc_value, traceback):
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType]):
sys.stdout = self.sys_stdout
sys.stderr = self.sys_stderr
if self.display and self.shell:
Expand Down
Loading
Loading
0