Skip to content

Commit 5835bbf

Browse files
Mypy types for autocomplete.py
Running mypy in CI on this one file.
1 parent d9305d7 commit 5835bbf

File tree

13 files changed

+129
-20
lines changed

13 files changed

+129
-20
lines changed

.github/workflows/lint.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,20 @@ jobs:
2626
with:
2727
skip: '*.po'
2828
ignore_words_list: ba,te,deltion
29+
30+
mypy:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v2
34+
- name: Set up Python
35+
uses: actions/setup-python@v2
36+
- name: Install dependencies
37+
run: |
38+
python -m pip install --upgrade pip
39+
pip install mypy
40+
pip install -r requirements.txt
41+
pip install urwid twisted watchdog "jedi >=0.16" babel "sphinx >=1.5"
42+
pip install types-backports types-requests types-setuptools types-toml
43+
- name: Check with mypy
44+
# for now only run on a few files to avoid slipping backward
45+
run: mypy --ignore-missing-imports bpython/autocomplete.py

bpython/args.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def callback(group):
197197
logger.info(f"curtsies: {curtsies.__version__}")
198198
logger.info(f"cwcwidth: {cwcwidth.__version__}")
199199
logger.info(f"greenlet: {greenlet.__version__}")
200-
logger.info(f"pygments: {pygments.__version__}")
200+
logger.info(f"pygments: {pygments.__version__}") # type: ignore
201201
logger.info(f"requests: {requests.__version__}")
202202
logger.info(
203203
"environment:\n{}".format(

bpython/autocomplete.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,18 @@
3333
import builtins
3434

3535
from enum import Enum
36-
from typing import Any, Dict, Iterator, List, Match, NoReturn, Set, Union, Tuple
36+
from typing import (
37+
Any,
38+
Dict,
39+
Iterator,
40+
List,
41+
Match,
42+
Set,
43+
Union,
44+
Tuple,
45+
Type,
46+
Sequence,
47+
)
3748
from . import inspection
3849
from . import line as lineparts
3950
from .line import LinePart
@@ -180,15 +191,15 @@ def few_enough_underscores(current, match) -> bool:
180191
return not match.startswith("_")
181192

182193

183-
def method_match_none(word, size, text) -> bool:
194+
def method_match_none(word: str, size: int, text: str) -> bool:
184195
return False
185196

186197

187-
def method_match_simple(word, size, text) -> bool:
198+
def method_match_simple(word: str, size: int, text: str) -> bool:
188199
return word[:size] == text
189200

190201

191-
def method_match_substring(word, size, text) -> bool:
202+
def method_match_substring(word: str, size: int, text: str) -> bool:
192203
return text in word
193204

194205

@@ -265,16 +276,20 @@ def shown_before_tab(self) -> bool:
265276
class CumulativeCompleter(BaseCompletionType):
266277
"""Returns combined matches from several completers"""
267278

268-
def __init__(self, completers, mode=AutocompleteModes.SIMPLE) -> None:
279+
def __init__(
280+
self,
281+
completers: Sequence[BaseCompletionType],
282+
mode: AutocompleteModes = AutocompleteModes.SIMPLE,
283+
) -> None:
269284
if not completers:
270285
raise ValueError(
271286
"CumulativeCompleter requires at least one completer"
272287
)
273-
self._completers = completers
288+
self._completers: Sequence[BaseCompletionType] = completers
274289

275290
super().__init__(True, mode)
276291

277-
def locate(self, current_offset: int, line: str) -> Union[None, NoReturn]:
292+
def locate(self, current_offset, line):
278293
for completer in self._completers:
279294
return_value = completer.locate(current_offset, line)
280295
if return_value is not None:
@@ -573,7 +588,7 @@ def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
573588
import jedi
574589
except ImportError:
575590

576-
class MultilineJediCompletion(BaseCompletionType):
591+
class MultilineJediCompletion(BaseCompletionType): # type: ignore [no-redef]
577592
def matches(self, cursor_offset, line, **kwargs) -> None:
578593
return None
579594

@@ -630,7 +645,7 @@ def locate(self, cursor_offset: int, line: str) -> LinePart:
630645
end = cursor_offset
631646
return LinePart(start, end, line[start:end])
632647

633-
class MultilineJediCompletion(JediCompletion):
648+
class MultilineJediCompletion(JediCompletion): # type: ignore [no-redef]
634649
def matches(self, cursor_offset, line, **kwargs) -> Union[Set, None]:
635650
if "current_block" not in kwargs or "history" not in kwargs:
636651
return None

bpython/curtsiesfrontend/filewatch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def ModuleChangedEventHandler(*args):
1414

1515
else:
1616

17-
class ModuleChangedEventHandler(FileSystemEventHandler):
17+
class ModuleChangedEventHandler(FileSystemEventHandler): # type: ignore [no-redef]
1818
def __init__(self, paths, on_change):
1919
self.dirs = defaultdict(set)
2020
self.on_change = on_change

bpython/lazyre.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
# THE SOFTWARE.
2222

2323
import re
24-
from typing import Optional, Iterator
24+
from typing import Optional, Iterator, Pattern, Match, Optional
2525

2626
try:
2727
from functools import cached_property
2828
except ImportError:
29-
from backports.cached_property import cached_property # type: ignore
29+
from backports.cached_property import cached_property # type: ignore [no-redef]
3030

3131

3232
class LazyReCompile:
@@ -40,7 +40,7 @@ def __init__(self, regex: str, flags: int = 0) -> None:
4040
self.flags = flags
4141

4242
@cached_property
43-
def compiled(self):
43+
def compiled(self) -> Pattern[str]:
4444
return re.compile(self.regex, self.flags)
4545

4646
def finditer(self, *args, **kwargs):
@@ -49,7 +49,7 @@ def finditer(self, *args, **kwargs):
4949
def search(self, *args, **kwargs):
5050
return self.compiled.search(*args, **kwargs)
5151

52-
def match(self, *args, **kwargs):
52+
def match(self, *args, **kwargs) -> Optional[Match[str]]:
5353
return self.compiled.match(*args, **kwargs)
5454

5555
def sub(self, *args, **kwargs) -> str:

bpython/patch_linecache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def _bpython_clear_linecache():
6464

6565
# Monkey-patch the linecache module so that we're able
6666
# to hold our command history there and have it persist
67-
linecache.cache = BPythonLinecache(linecache.cache)
67+
linecache.cache = BPythonLinecache(linecache.cache) # type: ignore
6868
linecache.clearcache = _bpython_clear_linecache
6969

7070

bpython/repl.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
import textwrap
3434
import time
3535
import traceback
36+
from abc import abstractmethod
3637
from itertools import takewhile
3738
from pathlib import Path
3839
from pygments.lexers import Python3Lexer
3940
from pygments.token import Token
4041
from types import ModuleType
42+
from typing import cast
4143

4244
have_pyperclip = True
4345
try:
@@ -451,11 +453,11 @@ def __init__(self, interp, config):
451453

452454
@property
453455
def ps1(self) -> str:
454-
return getattr(sys, "ps1", ">>> ")
456+
return cast(str, getattr(sys, "ps1", ">>> "))
455457

456458
@property
457459
def ps2(self) -> str:
458-
return getattr(sys, "ps2", "... ")
460+
return cast(str, getattr(sys, "ps2", "... "))
459461

460462
def startup(self):
461463
"""
@@ -769,6 +771,10 @@ def line_is_empty(line):
769771
indentation = 0
770772
return indentation
771773

774+
@abstractmethod
775+
def getstdout(self) -> str:
776+
raise NotImplementedError()
777+
772778
def get_session_formatted_for_file(self) -> str:
773779
"""Format the stdout buffer to something suitable for writing to disk,
774780
i.e. without >>> and ... at input lines and with "# OUT: " prepended to

bpython/translations/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
import locale
33
import os.path
44
import sys
5+
from typing import cast
56

67
from .. import package_dir
78

8-
translator = None
9+
translator: gettext.GNUTranslations = cast(gettext.GNUTranslations, None)
910

1011

11-
def _(message):
12+
def _(message) -> str:
1213
return translator.gettext(message)
1314

1415

setup.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,12 @@ msgid_bugs_address = https://github.com/bpython/bpython/issues
6565
builder = man
6666
source_dir = doc/sphinx/source
6767
build_dir = build
68+
69+
[mypy]
70+
warn_return_any = True
71+
warn_unused_configs = True
72+
mypy_path=stubs
73+
files=bpython
74+
75+
[mypy-jedi]
76+
ignore_missing_imports = True

stubs/blessings.pyi

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from typing import ContextManager, Text, IO
2+
3+
class Terminal:
4+
def __init__(self, stream=None, force_styling=False):
5+
# type: (IO, bool) -> None
6+
pass
7+
def location(self, x=None, y=None):
8+
# type: (int, int) -> ContextManager
9+
pass
10+
@property
11+
def hide_cursor(self):
12+
# type: () -> Text
13+
pass
14+
@property
15+
def normal_cursor(self):
16+
# type: () -> Text
17+
pass
18+
@property
19+
def height(self):
20+
# type: () -> int
21+
pass
22+
@property
23+
def width(self):
24+
# type: () -> int
25+
pass
26+
def fullscreen(self):
27+
# type: () -> ContextManager
28+
pass
29+
def move(self, y, x):
30+
# type: (int, int) -> Text
31+
pass
32+
@property
33+
def clear_eol(self):
34+
# type: () -> Text
35+
pass
36+
@property
37+
def clear_bol(self):
38+
# type: () -> Text
39+
pass
40+
@property
41+
def clear_eos(self):
42+
# type: () -> Text
43+
pass
44+
@property
45+
def clear_eos(self):
46+
# type: () -> Text
47+
pass

stubs/cwcwidth.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# official typing seems to require a second arg
2+
def wcswidth(s: str, n=100000000): ...
3+
4+
__version__: str

stubs/msvcrt.pyi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# The real types seem only available on the Windows platform,
2+
# but it seems annoying to need to run typechecking once per platform
3+
# https://github.com/python/typeshed/blob/master/stdlib/msvcrt.pyi
4+
def locking(__fd: int, __mode: int, __nbytes: int) -> None: ...
5+
6+
LK_NBLCK: int
7+
LK_UNLCK: int

stubs/rlcompleter.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from typing import Any
2+
3+
def get_class_members(class_: Any): ...

0 commit comments

Comments
 (0)