Skip to content

Commit e4d606f

Browse files
pre-commit and mypy fixes
1 parent 43939a0 commit e4d606f

19 files changed

+101
-362
lines changed

.pre-commit-config.yaml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ repos:
2525
hooks:
2626
- id: reorder-python-imports
2727
args: ['--application-directories=execnet', --py37-plus]
28-
- repo: local
28+
- repo: https://github.com/PyCQA/doc8
29+
rev: 'v1.1.1'
2930
hooks:
30-
- id: rst
31-
name: rst
32-
entry: rst-lint --encoding utf-8
33-
files: ^(CHANGELOG.rst|HOWTORELEASE.rst|README.rst)$
34-
language: python
35-
additional_dependencies: [pygments, restructuredtext_lint]
31+
- id: doc8
32+
args: ["--ignore", "D001"]
33+
34+
- repo: https://github.com/pre-commit/mirrors-mypy
35+
rev: 'v0.991'
36+
hooks:
37+
- id: mypy

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
* removed support for Python < 3.7
55
* apply pyupgrade --py37-plus
6+
* minimal mypy fixes and python2 support code drop
67
* migrate packaging to hatch
78

89

10+
911
1.9.0 (2021-06-13)
1012
------------------
1113

README.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ execnet: distributed Python deployment and communication
44
Important
55
---------
66

7-
**execnet currently is in maintenance-only mode, mostly because it is still the backend
8-
of the pytest-xdist plugin. Do not use in new projects.**
9-
107
.. image:: https://img.shields.io/pypi/v/execnet.svg
118
:target: https://pypi.org/project/execnet/
129

doc/example/remote1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# content of a module remote1.py
22

33
if __name__ == "__channelexec__":
4-
channel.send("initialization complete")
4+
channel.send("initialization complete") # type: ignore[name-defined]

doc/example/remotecmd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ def listdir(path):
1010

1111

1212
if __name__ == "__channelexec__":
13-
for item in channel:
14-
channel.send(eval(item))
13+
for item in channel: # type: ignore[name-defined]
14+
channel.send(eval(item)) # type: ignore[name-defined]

doc/example/servefiles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ def servefiles(channel):
99

1010

1111
if __name__ == "__channelexec__":
12-
servefiles(channel)
12+
servefiles(channel) # type: ignore[name-defined]

doc/example/taskserver.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import execnet
24

35
group = execnet.Group()
@@ -24,7 +26,7 @@ def process_item(channel):
2426

2527
# get a queue that gives us results
2628
q = mch.make_receive_queue(endmarker=-1)
27-
tasks = range(10) # a list of tasks, here just integers
29+
tasks: list[int] | None = list(range(10)) # a list of tasks, here just integers
2830
terminated = 0
2931
while 1:
3032
channel, item = q.get()
@@ -37,11 +39,11 @@ def process_item(channel):
3739
continue
3840
if item != "ready":
3941
print(f"other side {channel.gateway.id} returned {item!r}")
40-
if not tasks:
42+
if not tasks and tasks is not None:
4143
print("no tasks remain, sending termination request to all")
4244
mch.send_each(None)
43-
tasks = -1
44-
if tasks and tasks != -1:
45+
tasks = None
46+
if tasks:
4547
task = tasks.pop()
4648
channel.send(task)
4749
print(f"sent task {task!r} to {channel.gateway.id}")

execnet/gateway.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,8 @@ def _source_of_function(function):
199199
if not args or args[0] != "channel":
200200
raise ValueError("expected first function argument to be `channel`")
201201

202-
if gateway_base.ISPY3:
203-
closure = function.__closure__
204-
codeobj = function.__code__
205-
else:
206-
closure = function.func_closure
207-
codeobj = function.func_code
202+
closure = function.__closure__
203+
codeobj = function.__code__
208204

209205
if closure is not None:
210206
raise ValueError("functions with closures can't be passed")

execnet/gateway_base.py

Lines changed: 29 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -11,52 +11,26 @@
1111
- Ronny Pfannschmidt
1212
- many others
1313
"""
14+
from __future__ import annotations
15+
1416
import os
1517
import struct
1618
import sys
1719
import traceback
1820
import weakref
21+
from io import BytesIO
22+
from typing import Callable
1923

20-
# NOTE that we want to avoid try/except style importing
21-
# to avoid setting sys.exc_info() during import
22-
#
23-
24-
ISPY3 = sys.version_info >= (3, 0)
25-
if ISPY3:
26-
from io import BytesIO
27-
28-
exec("do_exec = exec")
29-
30-
def reraise(cls, val, tb):
31-
raise val.with_traceback(tb)
32-
33-
unicode = str
34-
_long_type = int
35-
from _thread import interrupt_main
3624

37-
SUBPROCESS32 = False
38-
else:
39-
from StringIO import StringIO as BytesIO
40-
41-
exec(
42-
"def do_exec(co, loc): exec co in loc\n"
43-
"def reraise(cls, val, tb): raise cls, val, tb\n"
44-
)
45-
bytes = str
46-
_long_type = long
47-
try:
48-
from thread import interrupt_main
49-
except ImportError:
50-
interrupt_main = None
51-
try:
52-
import subprocess32 # NOQA
25+
def reraise(cls, val, tb):
26+
raise val.with_traceback(tb)
5327

54-
SUBPROCESS32 = True
55-
except ImportError:
56-
SUBPROCESS32 = False
57-
sys.exc_clear()
5828

29+
unicode = str
30+
_long_type = int
31+
from _thread import interrupt_main
5932

33+
SUBPROCESS32 = False
6034
# f = open("/tmp/execnet-%s" % os.getpid(), "w")
6135
# def log_extra(*msg):
6236
# f.write(" ".join([str(x) for x in msg]) + "\n")
@@ -77,9 +51,9 @@ def get_execmodel(backend):
7751
"_thread::start_new_thread",
7852
],
7953
"threading": ["threading"],
80-
"queue": ["queue" if ISPY3 else "Queue"],
54+
"queue": ["queue"],
8155
"sleep": ["time::sleep"],
82-
"subprocess": ["subprocess32" if SUBPROCESS32 else "subprocess"],
56+
"subprocess": ["subprocess"],
8357
"socket": ["socket"],
8458
"_fdopen": ["os::fdopen"],
8559
"_lock": ["threading"],
@@ -414,7 +388,7 @@ def close_write(self):
414388
class Message:
415389
"""encapsulates Messages and their wire protocol."""
416390

417-
_types = []
391+
_types: list[Callable[[Message, BaseGateway], None]] = []
418392

419393
def __init__(self, msgcode, channelid=0, data=""):
420394
self.msgcode = msgcode
@@ -554,6 +528,7 @@ class Channel:
554528

555529
def __init__(self, gateway, id):
556530
assert isinstance(id, int)
531+
assert not isinstance(gateway, type)
557532
self.gateway = gateway
558533
# XXX: defaults copied from Unserializer
559534
self._strconfig = getattr(gateway, "_strconfig", (True, False))
@@ -1062,21 +1037,12 @@ def trace(msg):
10621037
def executetask(self, item):
10631038
try:
10641039
channel, (source, file_name, call_name, kwargs) = item
1065-
if not ISPY3 and kwargs:
1066-
# some python2 versions do not accept unicode keyword params
1067-
# note: Unserializer generally turns py2-str to py3-str objects
1068-
newkwargs = {}
1069-
for name, value in kwargs.items():
1070-
if isinstance(name, unicode):
1071-
name = name.encode("ascii")
1072-
newkwargs[name] = value
1073-
kwargs = newkwargs
10741040
loc = {"channel": channel, "__name__": "__channelexec__"}
10751041
self._trace(f"execution starts[{channel.id}]: {repr(source)[:50]}")
10761042
channel._executing = True
10771043
try:
10781044
co = compile(source + "\n", file_name or "<remote exec>", "exec")
1079-
do_exec(co, loc) # noqa
1045+
exec(co, loc)
10801046
if call_name:
10811047
self._trace("calling %s(**%60r)" % (call_name, kwargs))
10821048
function = loc[call_name]
@@ -1116,15 +1082,11 @@ class LoadError(DataFormatError):
11161082
"""Error while unserializing an object."""
11171083

11181084

1119-
if ISPY3:
1085+
def bchr(n):
1086+
return bytes([n])
11201087

1121-
def bchr(n):
1122-
return bytes([n])
11231088

1124-
else:
1125-
bchr = chr
1126-
1127-
DUMPFORMAT_VERSION = bchr(1)
1089+
DUMPFORMAT_VERSION = bchr(2)
11281090

11291091
FOUR_BYTE_INT_MAX = 2147483647
11301092

@@ -1139,7 +1101,9 @@ class _Stop(Exception):
11391101

11401102

11411103
class Unserializer:
1142-
num2func = {} # is filled after this class definition
1104+
num2func: dict[
1105+
int, Callable[[Unserializer], None]
1106+
] = {} # is filled after this class definition
11431107
py2str_as_py3str = True # True
11441108
py3str_as_py2str = False # false means py2 will get unicode
11451109

@@ -1193,18 +1157,8 @@ def load_longint(self):
11931157
s = self._read_byte_string()
11941158
self.stack.append(int(s))
11951159

1196-
if ISPY3:
1197-
load_long = load_int
1198-
load_longlong = load_longint
1199-
else:
1200-
1201-
def load_long(self):
1202-
i = self._read_int4()
1203-
self.stack.append(long(i))
1204-
1205-
def load_longlong(self):
1206-
l = self._read_byte_string()
1207-
self.stack.append(long(l))
1160+
load_long = load_int
1161+
load_longlong = load_longint
12081162

12091163
def load_float(self):
12101164
binary = self.stream.read(FLOAT_FORMAT_SIZE)
@@ -1224,15 +1178,15 @@ def _read_byte_string(self):
12241178

12251179
def load_py3string(self):
12261180
as_bytes = self._read_byte_string()
1227-
if not ISPY3 and self.py3str_as_py2str:
1181+
if self.py3str_as_py2str:
12281182
# XXX Should we try to decode into latin-1?
12291183
self.stack.append(as_bytes)
12301184
else:
12311185
self.stack.append(as_bytes.decode("utf-8"))
12321186

12331187
def load_py2string(self):
12341188
as_bytes = self._read_byte_string()
1235-
if ISPY3 and self.py2str_as_py3str:
1189+
if self.py2str_as_py3str:
12361190
s = as_bytes.decode("latin-1")
12371191
else:
12381192
s = as_bytes
@@ -1366,7 +1320,7 @@ def dumps_internal(obj):
13661320

13671321

13681322
class _Serializer:
1369-
_dispatch = {}
1323+
_dispatch = {object: Callable[["_Serializer", object], None]}
13701324

13711325
def __init__(self, write=None):
13721326
if write is None:
@@ -1413,21 +1367,9 @@ def save_bytes(self, bytes_):
14131367
self._write(opcode.BYTES)
14141368
self._write_byte_sequence(bytes_)
14151369

1416-
if ISPY3:
1417-
1418-
def save_str(self, s):
1419-
self._write(opcode.PY3STRING)
1420-
self._write_unicode_string(s)
1421-
1422-
else:
1423-
1424-
def save_str(self, s):
1425-
self._write(opcode.PY2STRING)
1426-
self._write_byte_sequence(s)
1427-
1428-
def save_unicode(self, s):
1429-
self._write(opcode.UNICODE)
1430-
self._write_unicode_string(s)
1370+
def save_str(self, s):
1371+
self._write(opcode.PY3STRING)
1372+
self._write_unicode_string(s)
14311373

14321374
def _write_unicode_string(self, s):
14331375
try:

execnet/gateway_io.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
try:
1111
from execnet.gateway_base import Popen2IO, Message
1212
except ImportError:
13-
from __main__ import Popen2IO, Message
13+
from __main__ import Popen2IO, Message # type: ignore[no-redef]
1414

1515
from functools import partial
1616

@@ -246,4 +246,4 @@ def controll(data):
246246

247247

248248
if __name__ == "__channelexec__":
249-
serve_proxy_io(channel) # noqa
249+
serve_proxy_io(channel) # type: ignore[name-defined]

0 commit comments

Comments
 (0)