##// END OF EJS Templates
some more typechecking (#14535)
M Bussonnier -
r28895:a49046c7 merge
parent child Browse files
Show More
@@ -32,7 +32,7 b' def test_full_path_posix():'
32 32 spath = "/foo"
33 33 result = tt.full_path(spath, ["a.txt", "b.txt"])
34 34 assert result, ["/a.txt" == "/b.txt"]
35 result = tt.full_path(spath, "a.txt")
35 result = tt.full_path(spath, ["a.txt"])
36 36 assert result == ["/a.txt"]
37 37
38 38
@@ -44,7 +44,7 b' def test_full_path_win32():'
44 44 spath = "c:\\foo"
45 45 result = tt.full_path(spath, ["a.txt", "b.txt"])
46 46 assert result, ["c:\\a.txt" == "c:\\b.txt"]
47 result = tt.full_path(spath, "a.txt")
47 result = tt.full_path(spath, ["a.txt"])
48 48 assert result == ["c:\\a.txt"]
49 49
50 50
@@ -36,7 +36,7 b' from . import skipdoctest'
36 36 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
37 37
38 38 @doctest_deco
39 def full_path(startPath,files):
39 def full_path(startPath: str, files: list[str]) -> list[str]:
40 40 """Make full paths for all the listed files, based on startPath.
41 41
42 42 Only the base part of startPath is kept, since this routine is typically
@@ -49,7 +49,7 b' def full_path(startPath,files):'
49 49 Initial path to use as the base for the results. This path is split
50 50 using os.path.split() and only its first component is kept.
51 51
52 files : string or list
52 files : list
53 53 One or more files.
54 54
55 55 Examples
@@ -61,13 +61,8 b' def full_path(startPath,files):'
61 61 >>> full_path('/foo',['a.txt','b.txt'])
62 62 ['/a.txt', '/b.txt']
63 63
64 If a single file is given, the output is still a list::
65
66 >>> full_path('/foo','a.txt')
67 ['/a.txt']
68 64 """
69
70 files = list_strings(files)
65 assert isinstance(files, list)
71 66 base = os.path.split(startPath)[0]
72 67 return [ os.path.join(base,f) for f in files ]
73 68
@@ -16,7 +16,20 b' import warnings'
16 16 from string import Formatter
17 17 from pathlib import Path
18 18
19 from typing import List, Dict, Tuple, Optional, cast, Sequence, Mapping, Any
19 from typing import (
20 List,
21 Dict,
22 Tuple,
23 Optional,
24 cast,
25 Sequence,
26 Mapping,
27 Any,
28 Union,
29 Callable,
30 Iterator,
31 TypeVar,
32 )
20 33
21 34 if sys.version_info < (3, 12):
22 35 from typing_extensions import Self
@@ -138,8 +151,13 b' class SList(list):'
138 151
139 152 p = paths = property(get_paths)
140 153
141 def grep(self, pattern, prune = False, field = None):
142 """ Return all strings matching 'pattern' (a regex or callable)
154 def grep(
155 self,
156 pattern: Union[str, Callable[[Any], re.Match[str] | None]],
157 prune: bool = False,
158 field: Optional[int] = None,
159 ) -> Self:
160 """Return all strings matching 'pattern' (a regex or callable)
143 161
144 162 This is case-insensitive. If prune is true, return all items
145 163 NOT matching the pattern.
@@ -154,7 +172,7 b' class SList(list):'
154 172 a.grep('chm', field=-1)
155 173 """
156 174
157 def match_target(s):
175 def match_target(s: str) -> str:
158 176 if field is None:
159 177 return s
160 178 parts = s.split()
@@ -169,12 +187,12 b' class SList(list):'
169 187 else:
170 188 pred = pattern
171 189 if not prune:
172 return SList([el for el in self if pred(match_target(el))])
190 return type(self)([el for el in self if pred(match_target(el))])
173 191 else:
174 return SList([el for el in self if not pred(match_target(el))])
192 return type(self)([el for el in self if not pred(match_target(el))])
175 193
176 def fields(self, *fields):
177 """ Collect whitespace-separated fields from string list
194 def fields(self, *fields: List[str]) -> List[List[str]]:
195 """Collect whitespace-separated fields from string list
178 196
179 197 Allows quick awk-like usage of string lists.
180 198
@@ -209,8 +227,12 b' class SList(list):'
209 227
210 228 return res
211 229
212 def sort(self,field= None, nums = False):
213 """ sort by specified fields (see fields())
230 def sort( # type:ignore[override]
231 self,
232 field: Optional[List[str]] = None,
233 nums: bool = False,
234 ) -> Self:
235 """sort by specified fields (see fields())
214 236
215 237 Example::
216 238
@@ -236,7 +258,7 b' class SList(list):'
236 258
237 259
238 260 dsu.sort()
239 return SList([t[1] for t in dsu])
261 return type(self)([t[1] for t in dsu])
240 262
241 263
242 264 # FIXME: We need to reimplement type specific displayhook and then add this
@@ -255,7 +277,7 b' class SList(list):'
255 277 # print_slist = result_display.register(SList)(print_slist)
256 278
257 279
258 def indent(instr,nspaces=4, ntabs=0, flatten=False):
280 def indent(instr: str, nspaces: int = 4, ntabs: int = 0, flatten: bool = False) -> str:
259 281 """Indent a string a given number of spaces or tabstops.
260 282
261 283 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
@@ -275,7 +297,7 b' def indent(instr,nspaces=4, ntabs=0, flatten=False):'
275 297
276 298 Returns
277 299 -------
278 str|unicode : string indented by ntabs and nspaces.
300 str : string indented by ntabs and nspaces.
279 301
280 302 """
281 303 if instr is None:
@@ -292,7 +314,7 b' def indent(instr,nspaces=4, ntabs=0, flatten=False):'
292 314 return outstr
293 315
294 316
295 def list_strings(arg):
317 def list_strings(arg: Union[str, List[str]]) -> List[str]:
296 318 """Always return a list of strings, given a string or list of strings
297 319 as input.
298 320
@@ -316,7 +338,7 b' def list_strings(arg):'
316 338 return arg
317 339
318 340
319 def marquee(txt='',width=78,mark='*'):
341 def marquee(txt: str = "", width: int = 78, mark: str = "*") -> str:
320 342 """Return the input string centered in a 'marquee'.
321 343
322 344 Examples
@@ -343,7 +365,8 b" def marquee(txt='',width=78,mark='*'):"
343 365
344 366 ini_spaces_re = re.compile(r'^(\s+)')
345 367
346 def num_ini_spaces(strng):
368
369 def num_ini_spaces(strng: str) -> int:
347 370 """Return the number of initial spaces in a string"""
348 371 warnings.warn(
349 372 "`num_ini_spaces` is Pending Deprecation since IPython 8.17."
@@ -359,7 +382,7 b' def num_ini_spaces(strng):'
359 382 return 0
360 383
361 384
362 def format_screen(strng):
385 def format_screen(strng: str) -> str:
363 386 """Format a string for screen printing.
364 387
365 388 This removes some latex-type format codes."""
@@ -396,7 +419,7 b' def dedent(text: str) -> str:'
396 419 return '\n'.join([first, rest])
397 420
398 421
399 def wrap_paragraphs(text, ncols=80):
422 def wrap_paragraphs(text: str, ncols: int = 80) -> List[str]:
400 423 """Wrap multiple paragraphs to fit a specified width.
401 424
402 425 This is equivalent to textwrap.wrap, but with support for multiple
@@ -428,7 +451,7 b' def wrap_paragraphs(text, ncols=80):'
428 451 return out_ps
429 452
430 453
431 def strip_email_quotes(text):
454 def strip_email_quotes(text: str) -> str:
432 455 """Strip leading email quotation characters ('>').
433 456
434 457 Removes any combination of leading '>' interspersed with whitespace that
@@ -478,7 +501,7 b' def strip_email_quotes(text):'
478 501 return text
479 502
480 503
481 def strip_ansi(source):
504 def strip_ansi(source: str) -> str:
482 505 """
483 506 Remove ansi escape codes from text.
484 507
@@ -519,7 +542,8 b' class EvalFormatter(Formatter):'
519 542 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
520 543 Out[3]: 'll'
521 544 """
522 def get_field(self, name, args, kwargs):
545
546 def get_field(self, name: str, args: Any, kwargs: Any) -> Tuple[Any, str]:
523 547 v = eval(name, kwargs)
524 548 return v, name
525 549
@@ -606,11 +630,15 b' class DollarFormatter(FullEvalFormatter):'
606 630 In [4]: f.format('$a or {b}', a=1, b=2)
607 631 Out[4]: '1 or 2'
608 632 """
609 _dollar_pattern_ignore_single_quote = re.compile(r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)")
610 def parse(self, fmt_string):
611 for literal_txt, field_name, format_spec, conversion \
612 in Formatter.parse(self, fmt_string):
613
633
634 _dollar_pattern_ignore_single_quote = re.compile(
635 r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)"
636 )
637
638 def parse(self, fmt_string: str) -> Iterator[Tuple[Any, Any, Any, Any]]: # type: ignore
639 for literal_txt, field_name, format_spec, conversion in Formatter.parse(
640 self, fmt_string
641 ):
614 642 # Find $foo patterns in the literal text.
615 643 continue_from = 0
616 644 txt = ""
@@ -627,14 +655,17 b' class DollarFormatter(FullEvalFormatter):'
627 655 # Re-yield the {foo} style pattern
628 656 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
629 657
630 def __repr__(self):
658 def __repr__(self) -> str:
631 659 return "<DollarFormatter>"
632 660
633 661 #-----------------------------------------------------------------------------
634 662 # Utils to columnize a list of string
635 663 #-----------------------------------------------------------------------------
636 664
637 def _col_chunks(l, max_rows, row_first=False):
665
666 def _col_chunks(
667 l: List[int], max_rows: int, row_first: bool = False
668 ) -> Iterator[List[int]]:
638 669 """Yield successive max_rows-sized column chunks from l."""
639 670 if row_first:
640 671 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
@@ -646,7 +677,7 b' def _col_chunks(l, max_rows, row_first=False):'
646 677
647 678
648 679 def _find_optimal(
649 rlist: List[str], row_first: bool, separator_size: int, displaywidth: int
680 rlist: List[int], row_first: bool, separator_size: int, displaywidth: int
650 681 ) -> Dict[str, Any]:
651 682 """Calculate optimal info to columnize a list of string"""
652 683 for max_rows in range(1, len(rlist) + 1):
@@ -662,7 +693,10 b' def _find_optimal('
662 693 }
663 694
664 695
665 def _get_or_default(mylist, i, default=None):
696 T = TypeVar("T")
697
698
699 def _get_or_default(mylist: List[T], i: int, default: T) -> T:
666 700 """return list item number, or default if don't exist"""
667 701 if i >= len(mylist):
668 702 return default
@@ -740,9 +774,31 b' def compute_item_matrix('
740 774 )
741 775 nrow, ncol = info["max_rows"], info["num_columns"]
742 776 if row_first:
743 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
777 return (
778 [
779 [
780 _get_or_default(
781 items, r * ncol + c, default=empty
782 ) # type:ignore[misc]
783 for c in range(ncol)
784 ]
785 for r in range(nrow)
786 ],
787 info,
788 )
744 789 else:
745 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
790 return (
791 [
792 [
793 _get_or_default(
794 items, c * nrow + r, default=empty
795 ) # type:ignore[misc]
796 for c in range(ncol)
797 ]
798 for r in range(nrow)
799 ],
800 info,
801 )
746 802
747 803
748 804 def columnize(
@@ -795,7 +851,9 b' def columnize('
795 851 return "\n".join(map(sjoin, fmatrix)) + "\n"
796 852
797 853
798 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
854 def get_text_list(
855 list_: List[str], last_sep: str = " and ", sep: str = ", ", wrap_item_with: str = ""
856 ) -> str:
799 857 """
800 858 Return a string with a natural enumeration of items
801 859
@@ -150,12 +150,22 b' warn_redundant_casts = true'
150 150 module = [
151 151 "IPython.utils.text",
152 152 ]
153 disallow_untyped_defs = true
154 check_untyped_defs = false
155 disallow_untyped_decorators = true
156
157 [[tool.mypy.overrides]]
158 module = [
159 ]
153 160 disallow_untyped_defs = false
161 ignore_errors = true
162 ignore_missing_imports = true
163 disallow_untyped_calls = false
164 disallow_incomplete_defs = false
154 165 check_untyped_defs = false
155 166 disallow_untyped_decorators = false
156 167
157
158 # global ignore error
168 # gloabl ignore error
159 169 [[tool.mypy.overrides]]
160 170 module = [
161 171 "IPython",
General Comments 0
You need to be logged in to leave comments. Login now