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 : |
|
|
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 |
|
|
190 | return type(self)([el for el in self if pred(match_target(el))]) | |
|
173 | 191 | else: |
|
174 |
return |
|
|
192 | return type(self)([el for el in self if not pred(match_target(el))]) | |
|
175 | 193 | |
|
176 | def fields(self, *fields): | |
|
177 |
""" |
|
|
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 |
|
|
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 |
|
|
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= |
|
|
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[ |
|
|
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,11 +150,21 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 | 168 | # gloabl ignore error |
|
159 | 169 | [[tool.mypy.overrides]] |
|
160 | 170 | module = [ |
General Comments 0
You need to be logged in to leave comments.
Login now