Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 74904ca

Browse files
claudeCarreau
authored andcommitted
Extend MonkeyType annotations to terminal, testing, and more utils modules
Apply MonkeyType-generated type annotations to 12 additional files, completing coverage across all modules traced during the test suite run. Files annotated: - IPython/terminal/prompts.py: Prompts.__init__ shell param, out_prompt_tokens, write_format_data - IPython/terminal/shortcuts/filters.py: has_focus, preceding_text, following_text, eval_node, filter_from_string return types - IPython/testing/decorators.py: skipif, skip, onlyif -> MarkDecorator; module_not_available -> bool - IPython/testing/ipunittest.py: Doc2UnitTester.__init__ verbose param - IPython/testing/plugin/pytest_ipdoctest.py: from_parent return, get_optionflags, _get_continue_on_failure - IPython/testing/skipdoctest.py: skip_doctest f/return -> Callable - IPython/testing/tools.py: parse_test_output, default_argv, default_config, get_ipython_cmd, ipexec, ipexec_validate, mktmp, AssertPrints - IPython/utils/capture.py: CapturedIO.__init__, stdout/stderr properties, capture_output context manager - IPython/utils/ipstruct.py: __setitem__, __setattr__, __getattr__ -> Any - IPython/utils/py3compat.py: encode, cast_unicode - IPython/utils/strdispatch.py: add_s - IPython/utils/terminal.py: toggle_set_term_title Manual corrections applied: - prompts.py: circular import with interactiveshell fixed via TYPE_CHECKING + string annotation - pytest_ipdoctest.py: removed self-referential circular import of IPDoctestItem - filters.py: replaced verbose private prompt_toolkit internal types with public Filter/Condition; removed unused Buffer/Container/UIControl imports - ipstruct.py: replaced over-specific CommandChainDispatcher with Any for general dict methods - tools.py: options: None -> Optional[List[str]], commands: Tuple[()] -> Tuple[str, ...] - capture.py/tools.py: __exit__ None params -> proper Optional[Type[BaseException]] etc. - py3compat.py: encoding: None -> Optional[str] Tests: 146 passed, 6 skipped. https://claude.ai/code/session_01L2i6WEqHEX3HyCMWgimmEp
1 parent 24b00d7 commit 74904ca

12 files changed

Lines changed: 58 additions & 42 deletions

File tree

IPython/terminal/prompts.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
"""Terminal input and output prompts."""
22

3-
from pygments.token import Token
3+
from pygments.token import _TokenType, Token
44
import sys
55

66
from IPython.core.displayhook import DisplayHook
77

88
from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens
99
from prompt_toolkit.shortcuts import print_formatted_text
1010
from prompt_toolkit.enums import EditingMode
11+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
12+
13+
if TYPE_CHECKING:
14+
from IPython.terminal.interactiveshell import TerminalInteractiveShell
1115

1216

1317
class Prompts:
14-
def __init__(self, shell):
18+
def __init__(self, shell: "TerminalInteractiveShell"):
1519
self.shell = shell
1620

1721
def vi_mode(self):
@@ -84,7 +88,7 @@ def rewrite_prompt_tokens(self):
8488
(Token.Prompt, ('-' * (width - 2)) + '> '),
8589
]
8690

87-
def out_prompt_tokens(self):
91+
def out_prompt_tokens(self) -> List[Tuple[_TokenType, str]]:
8892
return [
8993
(Token.OutPrompt, 'Out['),
9094
(Token.OutPromptNum, str(self.shell.execution_count - 1)),
@@ -128,7 +132,7 @@ def write_output_prompt(self):
128132
else:
129133
sys.stdout.write(prompt_txt)
130134

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

IPython/terminal/shortcuts/filters.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import re
1010
import signal
1111
import sys
12-
from typing import Dict, Union
12+
from typing import Optional, Dict, Union
1313
from collections.abc import Callable
1414

1515
from prompt_toolkit.application.current import get_app
@@ -40,7 +40,7 @@ def cursor_in_leading_ws():
4040
return (not before) or before.isspace()
4141

4242

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

104104

105-
def preceding_text(pattern: Union[str, Callable]):
105+
def preceding_text(pattern: Union[str, Callable]) -> Condition:
106106
if pattern in _preceding_text_cache:
107107
return _preceding_text_cache[pattern]
108108

@@ -129,7 +129,7 @@ def _preceding_text():
129129
return condition
130130

131131

132-
def following_text(pattern):
132+
def following_text(pattern: str) -> Condition:
133133
try:
134134
return _following_text_cache[pattern]
135135
except KeyError:
@@ -284,7 +284,7 @@ def __call__(self):
284284
}
285285

286286

287-
def eval_node(node: Union[ast.AST, None]):
287+
def eval_node(node: Union[ast.AST, None]) -> Optional[Filter]:
288288
if node is None:
289289
return None
290290
if isinstance(node, ast.Expression):
@@ -315,7 +315,7 @@ def eval_node(node: Union[ast.AST, None]):
315315
raise ValueError("Unhandled node", ast.dump(node))
316316

317317

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

IPython/testing/decorators.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
# Expose the unittest-driven decorators
1010
from .ipunittest import ipdoctest, ipdocstring
11+
from _pytest.mark.structures import MarkDecorator
12+
from typing import Optional
1113

12-
def skipif(skip_condition, msg=None):
14+
def skipif(skip_condition: bool, msg: Optional[str]=None) -> MarkDecorator:
1315
"""Make function raise SkipTest exception if skip_condition is true
1416
1517
Parameters
@@ -39,7 +41,7 @@ def skipif(skip_condition, msg=None):
3941

4042
# A version with the condition set to true, common case just to attach a message
4143
# to a skip decorator
42-
def skip(msg=None):
44+
def skip(msg: Optional[str]=None) -> MarkDecorator:
4345
"""Decorator factory - mark a test function for skipping from test suite.
4446
4547
Parameters
@@ -61,15 +63,15 @@ def skip(msg=None):
6163
return skipif(True, msg)
6264

6365

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

6769
return skipif(not condition, msg)
6870

6971

7072
# -----------------------------------------------------------------------------
7173
# Utility functions for decorators
72-
def module_not_available(module):
74+
def module_not_available(module: str) -> bool:
7375
"""Can module be imported? Returns true if module does NOT import.
7476
7577
This is used to make a decorator to skip tests that require module to be

IPython/testing/ipunittest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class Doc2UnitTester:
122122
no attempt is made at turning it into a singleton, there is no need for
123123
that).
124124
"""
125-
def __init__(self, verbose=False):
125+
def __init__(self, verbose: bool=False):
126126
"""New decorator.
127127
128128
Parameters

IPython/testing/plugin/pytest_ipdoctest.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from _pytest.compat import safe_getattr
3737
from _pytest.config import Config
3838
from _pytest.config.argparsing import Parser
39+
from _pytest.fixtures import TopRequest
3940

4041
try:
4142
from _pytest.fixtures import TopRequest as FixtureRequest
@@ -300,7 +301,7 @@ def from_parent( # type: ignore
300301
name: str,
301302
runner: "IPDocTestRunner",
302303
dtest: "doctest.DocTest",
303-
):
304+
) -> "IPDoctestItem":
304305
# incompatible signature due to imposed limits on subclass
305306
"""The public named constructor."""
306307
return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest)
@@ -475,7 +476,7 @@ def _get_flag_lookup() -> Dict[str, int]:
475476
)
476477

477478

478-
def get_optionflags(parent):
479+
def get_optionflags(parent: "IPDoctestModule") -> int:
479480
optionflags_str = parent.config.getini("ipdoctest_optionflags")
480481
flag_lookup_table = _get_flag_lookup()
481482
flag_acc = 0
@@ -484,7 +485,7 @@ def get_optionflags(parent):
484485
return flag_acc
485486

486487

487-
def _get_continue_on_failure(config):
488+
def _get_continue_on_failure(config: Config) -> bool:
488489
continue_on_failure = config.getvalue("ipdoctest_continue_on_failure")
489490
if continue_on_failure:
490491
# We need to turn off this if we use pdb since we should stop at

IPython/testing/skipdoctest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
numpy and sympy if they're present. Since this decorator is used in core parts
55
of IPython, it's in a separate module so that running IPython doesn't trigger
66
those imports."""
7+
from typing import Callable
78

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

1112

12-
def skip_doctest(f):
13+
def skip_doctest(f: Callable) -> Callable:
1314
"""Decorator - mark a function or method for skipping its doctest.
1415
1516
This decorator allows you to mark a function whose docstring you wish to

IPython/testing/tools.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
from . import decorators as dec
3131
from . import skipdoctest
32+
from types import TracebackType
33+
from typing import List, Optional, Tuple, Type
3234

3335

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

6971

70-
def parse_test_output(txt):
72+
def parse_test_output(txt: str) -> Tuple[int, int]:
7173
"""Parse the output of a test run and return errors, failures.
7274
7375
Parameters
@@ -113,7 +115,7 @@ def parse_test_output(txt):
113115
parse_test_output.__test__ = False
114116

115117

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

119121
return [
@@ -126,7 +128,7 @@ def default_argv():
126128
]
127129

128130

129-
def default_config():
131+
def default_config() -> Config:
130132
"""Return a config object with good defaults for testing."""
131133
config = Config()
132134
config.TerminalInteractiveShell.colors = "nocolor"
@@ -139,7 +141,7 @@ def default_config():
139141
return config
140142

141143

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

158160
return ipython_cmd
159161

160-
def ipexec(fname, options=None, commands=()):
162+
def ipexec(fname: str, options: Optional[List[str]]=None, commands: Tuple[str, ...]=()) -> Tuple[str, str]:
161163
"""Utility to call 'ipython filename'.
162164
163165
Starts IPython with a minimal and safe configuration to make startup as fast
@@ -215,8 +217,8 @@ def ipexec(fname, options=None, commands=()):
215217
return out, err
216218

217219

218-
def ipexec_validate(fname, expected_out, expected_err='',
219-
options=None, commands=()):
220+
def ipexec_validate(fname: str, expected_out: str, expected_err: str='',
221+
options: Optional[List[str]]=None, commands: Tuple[str, ...]=()):
220222
"""Utility to call 'ipython filename' and validate output/error.
221223
222224
This function raises an AssertionError if the validation fails.
@@ -267,7 +269,7 @@ class TempFileMixin(unittest.TestCase):
267269
268270
Meant as a mixin class for test cases."""
269271

270-
def mktmp(self, src, ext='.py'):
272+
def mktmp(self, src: str, ext: str='.py'):
271273
"""Make a valid python temp file."""
272274
fname = temp_pyfile(src, ext)
273275
if not hasattr(self, 'tmps'):
@@ -318,7 +320,7 @@ class AssertPrints:
318320
abcd
319321
def
320322
"""
321-
def __init__(self, s, channel='stdout', suppress=True):
323+
def __init__(self, s: str, channel: str='stdout', suppress: bool=True):
322324
self.s = s
323325
if isinstance(self.s, (str, _re_type)):
324326
self.s = [self.s]
@@ -331,7 +333,7 @@ def __enter__(self):
331333
self.tee = Tee(self.buffer, channel=self.channel)
332334
setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
333335

334-
def __exit__(self, etype, value, traceback):
336+
def __exit__(self, etype: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType]):
335337
__tracebackhide__ = True
336338

337339
try:

IPython/utils/capture.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import sys
99
from io import StringIO
10+
from types import TracebackType
11+
from typing import Any, List, Optional, Type
1012

1113
#-----------------------------------------------------------------------------
1214
# Classes and functions
@@ -72,7 +74,7 @@ class CapturedIO:
7274
above in the same order, and can be invoked simply via ``c()``.
7375
"""
7476

75-
def __init__(self, stdout, stderr, outputs=None):
77+
def __init__(self, stdout: StringIO, stderr: StringIO, outputs: Optional[List[Any]]=None):
7678
self._stdout = stdout
7779
self._stderr = stderr
7880
if outputs is None:
@@ -83,14 +85,14 @@ def __str__(self):
8385
return self.stdout
8486

8587
@property
86-
def stdout(self):
88+
def stdout(self) -> str:
8789
"Captured standard output"
8890
if not self._stdout:
8991
return ''
9092
return self._stdout.getvalue()
9193

9294
@property
93-
def stderr(self):
95+
def stderr(self) -> str:
9496
"Captured standard error"
9597
if not self._stderr:
9698
return ''
@@ -127,13 +129,13 @@ class capture_output:
127129
stderr = True
128130
display = True
129131

130-
def __init__(self, stdout=True, stderr=True, display=True):
132+
def __init__(self, stdout: bool=True, stderr: bool=True, display: bool=True):
131133
self.stdout = stdout
132134
self.stderr = stderr
133135
self.display = display
134136
self.shell = None
135137

136-
def __enter__(self):
138+
def __enter__(self) -> CapturedIO:
137139
from IPython.core.getipython import get_ipython
138140
from IPython.core.displaypub import CapturingDisplayPublisher
139141
from IPython.core.displayhook import CapturingDisplayHook
@@ -162,7 +164,7 @@ def __enter__(self):
162164

163165
return CapturedIO(stdout, stderr, outputs)
164166

165-
def __exit__(self, exc_type, exc_value, traceback):
167+
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType]):
166168
sys.stdout = self.sys_stdout
167169
sys.stderr = self.sys_stderr
168170
if self.display and self.shell:

IPython/utils/ipstruct.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* Fernando Perez (original)
77
* Brian Granger (refactoring to a dict subclass)
88
"""
9+
from typing import Any
10+
from typing import Any
911

1012
#-----------------------------------------------------------------------------
1113
# Copyright (C) 2008-2011 The IPython Development Team
@@ -62,7 +64,7 @@ def __init__(self, *args, **kw):
6264
object.__setattr__(self, '_allownew', True)
6365
dict.__init__(self, *args, **kw)
6466

65-
def __setitem__(self, key, value):
67+
def __setitem__(self, key: str, value: Any):
6668
"""Set an item with check for allownew.
6769
6870
Examples
@@ -85,7 +87,7 @@ def __setitem__(self, key, value):
8587
"can't create new attribute %s when allow_new_attr(False)" % key)
8688
dict.__setitem__(self, key, value)
8789

88-
def __setattr__(self, key, value):
90+
def __setattr__(self, key: str, value: Any):
8991
"""Set an attr with protection of class members.
9092
9193
This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to
@@ -119,7 +121,7 @@ def __setattr__(self, key, value):
119121
except KeyError as e:
120122
raise AttributeError(e) from e
121123

122-
def __getattr__(self, key):
124+
def __getattr__(self, key: str) -> Any:
123125
"""Get an attr by calling :meth:`dict.__getitem__`.
124126
125127
Like :meth:`__setattr__`, this method converts :exc:`KeyError` to

0 commit comments

Comments
 (0)