2
2
gateway code for initiating popen, socket and ssh connections.
3
3
(c) 2004-2013, Holger Krekel and others
4
4
"""
5
+ from __future__ import annotations
6
+
5
7
import inspect
6
8
import linecache
7
9
import os
8
10
import textwrap
9
11
import types
12
+ from typing import TYPE_CHECKING
13
+ from typing import Any
14
+ from typing import Callable
10
15
11
16
import execnet
12
17
13
18
from . import gateway_base
19
+ from .gateway_base import IO
20
+ from .gateway_base import Channel
14
21
from .gateway_base import Message
22
+ from .multi import Group
23
+ from .xspec import XSpec
15
24
16
25
importdir = os .path .dirname (os .path .dirname (execnet .__file__ ))
17
26
18
27
19
28
class Gateway (gateway_base .BaseGateway ):
20
29
"""Gateway to a local or remote Python Interpreter."""
21
30
22
- def __init__ (self , io , spec ):
31
+ _group : Group
32
+
33
+ def __init__ (self , io : IO , spec : XSpec ) -> None :
23
34
super ().__init__ (io = io , id = spec .id , _startcount = 1 )
24
35
self .spec = spec
25
36
self ._initreceive ()
26
37
27
38
@property
28
- def remoteaddress (self ):
29
- return self ._io .remoteaddress
39
+ def remoteaddress (self ) -> str :
40
+ # Only defined for remote IO types.
41
+ return self ._io .remoteaddress # type: ignore[attr-defined,no-any-return]
30
42
31
- def __repr__ (self ):
43
+ def __repr__ (self ) -> str :
32
44
"""return string representing gateway type and status."""
33
45
try :
34
- r = self .hasreceiver () and "receive-live" or "not-receiving"
35
- i = len (self ._channelfactory .channels ())
46
+ r : str = self .hasreceiver () and "receive-live" or "not-receiving"
47
+ i = str ( len (self ._channelfactory .channels () ))
36
48
except AttributeError :
37
49
r = "uninitialized"
38
50
i = "no"
39
51
return "<{} id={!r} {}, {} model, {} active channels>" .format (
40
52
self .__class__ .__name__ , self .id , r , self .execmodel .backend , i
41
53
)
42
54
43
- def exit (self ):
55
+ def exit (self ) -> None :
44
56
"""trigger gateway exit. Defer waiting for finishing
45
57
of receiver-thread and subprocess activity to when
46
58
group.terminate() is called.
@@ -59,7 +71,9 @@ def exit(self):
59
71
self ._trace ("io-error: could not send termination sequence" )
60
72
self ._trace (" exception: %r" % exc )
61
73
62
- def reconfigure (self , py2str_as_py3str = True , py3str_as_py2str = False ):
74
+ def reconfigure (
75
+ self , py2str_as_py3str : bool = True , py3str_as_py2str : bool = False
76
+ ) -> None :
63
77
"""
64
78
set the string coercion for this gateway
65
79
the default is to try to convert py2 str as py3 str,
@@ -69,7 +83,7 @@ def reconfigure(self, py2str_as_py3str=True, py3str_as_py2str=False):
69
83
data = gateway_base .dumps_internal (self ._strconfig )
70
84
self ._send (Message .RECONFIGURE , data = data )
71
85
72
- def _rinfo (self , update = False ):
86
+ def _rinfo (self , update : bool = False ) -> RInfo :
73
87
"""return some sys/env information from remote."""
74
88
if update or not hasattr (self , "_cache_rinfo" ):
75
89
ch = self .remote_exec (rinfo_source )
@@ -79,11 +93,11 @@ def _rinfo(self, update=False):
79
93
ch .waitclose ()
80
94
return self ._cache_rinfo
81
95
82
- def hasreceiver (self ):
96
+ def hasreceiver (self ) -> bool :
83
97
"""return True if gateway is able to receive data."""
84
98
return self ._receivepool .active_count () > 0
85
99
86
- def remote_status (self ):
100
+ def remote_status (self ) -> RemoteStatus :
87
101
"""return information object about remote execution status."""
88
102
channel = self .newchannel ()
89
103
self ._send (Message .STATUS , channel .id )
@@ -93,7 +107,11 @@ def remote_status(self):
93
107
self ._channelfactory ._local_close (channel .id )
94
108
return RemoteStatus (statusdict )
95
109
96
- def remote_exec (self , source , ** kwargs ):
110
+ def remote_exec (
111
+ self ,
112
+ source : str | types .FunctionType | Callable [..., object ] | types .ModuleType ,
113
+ ** kwargs : object ,
114
+ ) -> Channel :
97
115
"""return channel object and connect it to a remote
98
116
execution thread where the given ``source`` executes.
99
117
@@ -113,7 +131,7 @@ def remote_exec(self, source, **kwargs):
113
131
file_name = None
114
132
if isinstance (source , types .ModuleType ):
115
133
file_name = inspect .getsourcefile (source )
116
- linecache .updatecache (file_name )
134
+ linecache .updatecache (file_name ) # type: ignore[arg-type]
117
135
source = inspect .getsource (source )
118
136
elif isinstance (source , types .FunctionType ):
119
137
call_name = source .__name__
@@ -133,24 +151,29 @@ def remote_exec(self, source, **kwargs):
133
151
)
134
152
return channel
135
153
136
- def remote_init_threads (self , num = None ):
154
+ def remote_init_threads (self , num : int | None = None ) -> None :
137
155
"""DEPRECATED. Is currently a NO-OPERATION already."""
138
156
print ("WARNING: remote_init_threads()" " is a no-operation in execnet-1.2" )
139
157
140
158
141
159
class RInfo :
142
- def __init__ (self , kwargs ):
160
+ def __init__ (self , kwargs ) -> None :
143
161
self .__dict__ .update (kwargs )
144
162
145
- def __repr__ (self ):
163
+ def __repr__ (self ) -> str :
146
164
info = ", " .join (f"{ k } ={ v } " for k , v in sorted (self .__dict__ .items ()))
147
165
return "<RInfo %r>" % info
148
166
167
+ if TYPE_CHECKING :
168
+
169
+ def __getattr__ (self , name : str ) -> Any :
170
+ ...
171
+
149
172
150
173
RemoteStatus = RInfo
151
174
152
175
153
- def rinfo_source (channel ):
176
+ def rinfo_source (channel ) -> None :
154
177
import os
155
178
import sys
156
179
@@ -165,7 +188,7 @@ def rinfo_source(channel):
165
188
)
166
189
167
190
168
- def _find_non_builtin_globals (source , codeobj ) :
191
+ def _find_non_builtin_globals (source : str , codeobj : types . CodeType ) -> list [ str ] :
169
192
import ast
170
193
import builtins
171
194
@@ -179,7 +202,7 @@ def _find_non_builtin_globals(source, codeobj):
179
202
]
180
203
181
204
182
- def _source_of_function (function ) :
205
+ def _source_of_function (function : types . FunctionType | Callable [..., object ]) -> str :
183
206
if function .__name__ == "<lambda>" :
184
207
raise ValueError ("can't evaluate lambda functions'" )
185
208
# XXX: we dont check before remote instantiation
0 commit comments