Skip to content

Commit 56f6fad

Browse files
authored
Merge pull request RustPython#4064 from youknowone/unittests
Unittests
2 parents 8577a3f + bf53bb0 commit 56f6fad

39 files changed

Lines changed: 2162 additions & 1157 deletions

Lib/runpy.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
import sys
1414
import importlib.machinery # importlib first so we can test #15386 via -m
1515
import importlib.util
16+
import io
1617
import types
17-
from pkgutil import read_code, get_importer
18+
import os
1819

1920
__all__ = [
2021
"run_module", "run_path",
@@ -131,6 +132,9 @@ def _get_module_details(mod_name, error=ImportError):
131132
# importlib, where the latter raises other errors for cases where
132133
# pkgutil previously raised ImportError
133134
msg = "Error while finding module specification for {!r} ({}: {})"
135+
if mod_name.endswith(".py"):
136+
msg += (f". Try using '{mod_name[:-3]}' instead of "
137+
f"'{mod_name}' as the module name.")
134138
raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex
135139
if spec is None:
136140
raise error("No module named %s" % mod_name)
@@ -194,9 +198,24 @@ def _run_module_as_main(mod_name, alter_argv=True):
194198

195199
def run_module(mod_name, init_globals=None,
196200
run_name=None, alter_sys=False):
197-
"""Execute a module's code without importing it
201+
"""Execute a module's code without importing it.
198202
199-
Returns the resulting top level namespace dictionary
203+
mod_name -- an absolute module name or package name.
204+
205+
Optional arguments:
206+
init_globals -- dictionary used to pre-populate the module’s
207+
globals dictionary before the code is executed.
208+
209+
run_name -- if not None, this will be used for setting __name__;
210+
otherwise, __name__ will be set to mod_name + '__main__' if the
211+
named module is a package and to just mod_name otherwise.
212+
213+
alter_sys -- if True, sys.argv[0] is updated with the value of
214+
__file__ and sys.modules[__name__] is updated with a temporary
215+
module object for the module being executed. Both are
216+
restored to their original values before the function returns.
217+
218+
Returns the resulting module globals dictionary.
200219
"""
201220
mod_name, mod_spec, code = _get_module_details(mod_name)
202221
if run_name is None:
@@ -228,27 +247,35 @@ def _get_main_module_details(error=ImportError):
228247

229248
def _get_code_from_file(run_name, fname):
230249
# Check for a compiled file first
231-
with open(fname, "rb") as f:
250+
from pkgutil import read_code
251+
decoded_path = os.path.abspath(os.fsdecode(fname))
252+
with io.open_code(decoded_path) as f:
232253
code = read_code(f)
233254
if code is None:
234255
# That didn't work, so try it as normal source code
235-
with open(fname, "rb") as f:
256+
with io.open_code(decoded_path) as f:
236257
code = compile(f.read(), fname, 'exec')
237258
return code, fname
238259

239260
def run_path(path_name, init_globals=None, run_name=None):
240-
"""Execute code located at the specified filesystem location
261+
"""Execute code located at the specified filesystem location.
262+
263+
path_name -- filesystem location of a Python script, zipfile,
264+
or directory containing a top level __main__.py script.
265+
266+
Optional arguments:
267+
init_globals -- dictionary used to pre-populate the module’s
268+
globals dictionary before the code is executed.
241269
242-
Returns the resulting top level namespace dictionary
270+
run_name -- if not None, this will be used to set __name__;
271+
otherwise, '<run_path>' will be used for __name__.
243272
244-
The file path may refer directly to a Python script (i.e.
245-
one that could be directly executed with execfile) or else
246-
it may refer to a zipfile or directory containing a top
247-
level __main__.py script.
273+
Returns the resulting module globals dictionary.
248274
"""
249275
if run_name is None:
250276
run_name = "<run_path>"
251277
pkg_name = run_name.rpartition(".")[0]
278+
from pkgutil import get_importer
252279
importer = get_importer(path_name)
253280
# Trying to avoid importing imp so as to not consume the deprecation warning.
254281
is_NullImporter = False

Lib/sched.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,19 @@
2626
import time
2727
import heapq
2828
from collections import namedtuple
29+
from itertools import count
2930
import threading
3031
from time import monotonic as _time
3132

3233
__all__ = ["scheduler"]
3334

34-
class Event(namedtuple('Event', 'time, priority, action, argument, kwargs')):
35-
__slots__ = []
36-
def __eq__(s, o): return (s.time, s.priority) == (o.time, o.priority)
37-
def __lt__(s, o): return (s.time, s.priority) < (o.time, o.priority)
38-
def __le__(s, o): return (s.time, s.priority) <= (o.time, o.priority)
39-
def __gt__(s, o): return (s.time, s.priority) > (o.time, o.priority)
40-
def __ge__(s, o): return (s.time, s.priority) >= (o.time, o.priority)
41-
35+
Event = namedtuple('Event', 'time, priority, sequence, action, argument, kwargs')
4236
Event.time.__doc__ = ('''Numeric type compatible with the return value of the
4337
timefunc function passed to the constructor.''')
4438
Event.priority.__doc__ = ('''Events scheduled for the same time will be executed
4539
in the order of their priority.''')
40+
Event.sequence.__doc__ = ('''A continually increasing sequence number that
41+
separates events if time and priority are equal.''')
4642
Event.action.__doc__ = ('''Executing the event means executing
4743
action(*argument, **kwargs)''')
4844
Event.argument.__doc__ = ('''argument is a sequence holding the positional
@@ -61,6 +57,7 @@ def __init__(self, timefunc=_time, delayfunc=time.sleep):
6157
self._lock = threading.RLock()
6258
self.timefunc = timefunc
6359
self.delayfunc = delayfunc
60+
self._sequence_generator = count()
6461

6562
def enterabs(self, time, priority, action, argument=(), kwargs=_sentinel):
6663
"""Enter a new event in the queue at an absolute time.
@@ -71,8 +68,10 @@ def enterabs(self, time, priority, action, argument=(), kwargs=_sentinel):
7168
"""
7269
if kwargs is _sentinel:
7370
kwargs = {}
74-
event = Event(time, priority, action, argument, kwargs)
71+
7572
with self._lock:
73+
event = Event(time, priority, next(self._sequence_generator),
74+
action, argument, kwargs)
7675
heapq.heappush(self._queue, event)
7776
return event # The ID
7877

@@ -136,7 +135,8 @@ def run(self, blocking=True):
136135
with lock:
137136
if not q:
138137
break
139-
time, priority, action, argument, kwargs = q[0]
138+
(time, priority, sequence, action,
139+
argument, kwargs) = q[0]
140140
now = timefunc()
141141
if time > now:
142142
delay = True

Lib/secrets.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
import base64
1616
import binascii
17-
import os
1817

1918
from hmac import compare_digest
2019
from random import SystemRandom
@@ -44,7 +43,7 @@ def token_bytes(nbytes=None):
4443
"""
4544
if nbytes is None:
4645
nbytes = DEFAULT_ENTROPY
47-
return os.urandom(nbytes)
46+
return _sysrand.randbytes(nbytes)
4847

4948
def token_hex(nbytes=None):
5049
"""Return a random text string, in hexadecimal.

Lib/socket.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
socket() -- create a new socket object
1313
socketpair() -- create a pair of new socket objects [*]
1414
fromfd() -- create a socket object from an open file descriptor [*]
15+
send_fds() -- Send file descriptor to the socket.
16+
recv_fds() -- Recieve file descriptors from the socket.
1517
fromshare() -- create a socket object from data received from socket.share() [*]
1618
gethostname() -- return the current hostname
1719
gethostbyname() -- map a hostname to its IP number
@@ -104,7 +106,6 @@ def _intenum_converter(value, enum_klass):
104106
except ValueError:
105107
return value
106108

107-
_realsocket = socket
108109

109110
# WSA error codes
110111
if sys.platform.lower().startswith("win"):
@@ -336,6 +337,7 @@ def makefile(self, mode="r", buffering=None, *,
336337
buffer = io.BufferedWriter(raw, buffering)
337338
if binary:
338339
return buffer
340+
encoding = io.text_encoding(encoding)
339341
text = io.TextIOWrapper(buffer, encoding, errors, newline)
340342
text.mode = mode
341343
return text
@@ -376,7 +378,7 @@ def _sendfile_use_sendfile(self, file, offset=0, count=None):
376378
try:
377379
while True:
378380
if timeout and not selector_select(timeout):
379-
raise _socket.timeout('timed out')
381+
raise TimeoutError('timed out')
380382
if count:
381383
blocksize = count - total_sent
382384
if blocksize <= 0:
@@ -543,6 +545,40 @@ def fromfd(fd, family, type, proto=0):
543545
nfd = dup(fd)
544546
return socket(family, type, proto, nfd)
545547

548+
if hasattr(_socket.socket, "sendmsg"):
549+
import array
550+
551+
def send_fds(sock, buffers, fds, flags=0, address=None):
552+
""" send_fds(sock, buffers, fds[, flags[, address]]) -> integer
553+
554+
Send the list of file descriptors fds over an AF_UNIX socket.
555+
"""
556+
return sock.sendmsg(buffers, [(_socket.SOL_SOCKET,
557+
_socket.SCM_RIGHTS, array.array("i", fds))])
558+
__all__.append("send_fds")
559+
560+
if hasattr(_socket.socket, "recvmsg"):
561+
import array
562+
563+
def recv_fds(sock, bufsize, maxfds, flags=0):
564+
""" recv_fds(sock, bufsize, maxfds[, flags]) -> (data, list of file
565+
descriptors, msg_flags, address)
566+
567+
Receive up to maxfds file descriptors returning the message
568+
data and a list containing the descriptors.
569+
"""
570+
# Array of ints
571+
fds = array.array("i")
572+
msg, ancdata, flags, addr = sock.recvmsg(bufsize,
573+
_socket.CMSG_LEN(maxfds * fds.itemsize))
574+
for cmsg_level, cmsg_type, cmsg_data in ancdata:
575+
if (cmsg_level == _socket.SOL_SOCKET and cmsg_type == _socket.SCM_RIGHTS):
576+
fds.frombytes(cmsg_data[:
577+
len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
578+
579+
return msg, list(fds), flags, addr
580+
__all__.append("recv_fds")
581+
546582
if hasattr(_socket.socket, "share"):
547583
def fromshare(info):
548584
""" fromshare(info) -> socket object
@@ -671,7 +707,7 @@ def readinto(self, b):
671707
self._timeout_occurred = True
672708
raise
673709
except error as e:
674-
if e.args[0] in _blocking_errnos:
710+
if e.errno in _blocking_errnos:
675711
return None
676712
raise
677713

@@ -687,7 +723,7 @@ def write(self, b):
687723
return self._sock.send(b)
688724
except error as e:
689725
# XXX what about EINTR?
690-
if e.args[0] in _blocking_errnos:
726+
if e.errno in _blocking_errnos:
691727
return None
692728
raise
693729

@@ -746,8 +782,9 @@ def getfqdn(name=''):
746782
An empty argument is interpreted as meaning the local host.
747783
748784
First the hostname returned by gethostbyaddr() is checked, then
749-
possibly existing aliases. In case no FQDN is available, hostname
750-
from gethostname() is returned.
785+
possibly existing aliases. In case no FQDN is available and `name`
786+
was given, it is returned unchanged. If `name` was empty or '0.0.0.0',
787+
hostname from gethostname() is returned.
751788
"""
752789
name = name.strip()
753790
if not name or name == '0.0.0.0':

0 commit comments

Comments
 (0)