Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 38 additions & 11 deletions Lib/runpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
import sys
import importlib.machinery # importlib first so we can test #15386 via -m
import importlib.util
import io
import types
from pkgutil import read_code, get_importer
import os

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

def run_module(mod_name, init_globals=None,
run_name=None, alter_sys=False):
"""Execute a module's code without importing it
"""Execute a module's code without importing it.

Returns the resulting top level namespace dictionary
mod_name -- an absolute module name or package name.

Optional arguments:
init_globals -- dictionary used to pre-populate the module’s
globals dictionary before the code is executed.

run_name -- if not None, this will be used for setting __name__;
otherwise, __name__ will be set to mod_name + '__main__' if the
named module is a package and to just mod_name otherwise.

alter_sys -- if True, sys.argv[0] is updated with the value of
__file__ and sys.modules[__name__] is updated with a temporary
module object for the module being executed. Both are
restored to their original values before the function returns.

Returns the resulting module globals dictionary.
"""
mod_name, mod_spec, code = _get_module_details(mod_name)
if run_name is None:
Expand Down Expand Up @@ -228,27 +247,35 @@ def _get_main_module_details(error=ImportError):

def _get_code_from_file(run_name, fname):
# Check for a compiled file first
with open(fname, "rb") as f:
from pkgutil import read_code
decoded_path = os.path.abspath(os.fsdecode(fname))
with io.open_code(decoded_path) as f:
code = read_code(f)
if code is None:
# That didn't work, so try it as normal source code
with open(fname, "rb") as f:
with io.open_code(decoded_path) as f:
code = compile(f.read(), fname, 'exec')
return code, fname

def run_path(path_name, init_globals=None, run_name=None):
"""Execute code located at the specified filesystem location
"""Execute code located at the specified filesystem location.

path_name -- filesystem location of a Python script, zipfile,
or directory containing a top level __main__.py script.

Optional arguments:
init_globals -- dictionary used to pre-populate the module’s
globals dictionary before the code is executed.

Returns the resulting top level namespace dictionary
run_name -- if not None, this will be used to set __name__;
otherwise, '<run_path>' will be used for __name__.

The file path may refer directly to a Python script (i.e.
one that could be directly executed with execfile) or else
it may refer to a zipfile or directory containing a top
level __main__.py script.
Returns the resulting module globals dictionary.
"""
if run_name is None:
run_name = "<run_path>"
pkg_name = run_name.rpartition(".")[0]
from pkgutil import get_importer
importer = get_importer(path_name)
# Trying to avoid importing imp so as to not consume the deprecation warning.
is_NullImporter = False
Expand Down
20 changes: 10 additions & 10 deletions Lib/sched.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,19 @@
import time
import heapq
from collections import namedtuple
from itertools import count
import threading
from time import monotonic as _time

__all__ = ["scheduler"]

class Event(namedtuple('Event', 'time, priority, action, argument, kwargs')):
__slots__ = []
def __eq__(s, o): return (s.time, s.priority) == (o.time, o.priority)
def __lt__(s, o): return (s.time, s.priority) < (o.time, o.priority)
def __le__(s, o): return (s.time, s.priority) <= (o.time, o.priority)
def __gt__(s, o): return (s.time, s.priority) > (o.time, o.priority)
def __ge__(s, o): return (s.time, s.priority) >= (o.time, o.priority)

Event = namedtuple('Event', 'time, priority, sequence, action, argument, kwargs')
Event.time.__doc__ = ('''Numeric type compatible with the return value of the
timefunc function passed to the constructor.''')
Event.priority.__doc__ = ('''Events scheduled for the same time will be executed
in the order of their priority.''')
Event.sequence.__doc__ = ('''A continually increasing sequence number that
separates events if time and priority are equal.''')
Event.action.__doc__ = ('''Executing the event means executing
action(*argument, **kwargs)''')
Event.argument.__doc__ = ('''argument is a sequence holding the positional
Expand All @@ -61,6 +57,7 @@ def __init__(self, timefunc=_time, delayfunc=time.sleep):
self._lock = threading.RLock()
self.timefunc = timefunc
self.delayfunc = delayfunc
self._sequence_generator = count()

def enterabs(self, time, priority, action, argument=(), kwargs=_sentinel):
"""Enter a new event in the queue at an absolute time.
Expand All @@ -71,8 +68,10 @@ def enterabs(self, time, priority, action, argument=(), kwargs=_sentinel):
"""
if kwargs is _sentinel:
kwargs = {}
event = Event(time, priority, action, argument, kwargs)

with self._lock:
event = Event(time, priority, next(self._sequence_generator),
action, argument, kwargs)
heapq.heappush(self._queue, event)
return event # The ID

Expand Down Expand Up @@ -136,7 +135,8 @@ def run(self, blocking=True):
with lock:
if not q:
break
time, priority, action, argument, kwargs = q[0]
(time, priority, sequence, action,
argument, kwargs) = q[0]
now = timefunc()
if time > now:
delay = True
Expand Down
3 changes: 1 addition & 2 deletions Lib/secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import base64
import binascii
import os

from hmac import compare_digest
from random import SystemRandom
Expand Down Expand Up @@ -44,7 +43,7 @@ def token_bytes(nbytes=None):
"""
if nbytes is None:
nbytes = DEFAULT_ENTROPY
return os.urandom(nbytes)
return _sysrand.randbytes(nbytes)

def token_hex(nbytes=None):
"""Return a random text string, in hexadecimal.
Expand Down
49 changes: 43 additions & 6 deletions Lib/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
socket() -- create a new socket object
socketpair() -- create a pair of new socket objects [*]
fromfd() -- create a socket object from an open file descriptor [*]
send_fds() -- Send file descriptor to the socket.
recv_fds() -- Recieve file descriptors from the socket.
fromshare() -- create a socket object from data received from socket.share() [*]
gethostname() -- return the current hostname
gethostbyname() -- map a hostname to its IP number
Expand Down Expand Up @@ -104,7 +106,6 @@ def _intenum_converter(value, enum_klass):
except ValueError:
return value

_realsocket = socket

# WSA error codes
if sys.platform.lower().startswith("win"):
Expand Down Expand Up @@ -336,6 +337,7 @@ def makefile(self, mode="r", buffering=None, *,
buffer = io.BufferedWriter(raw, buffering)
if binary:
return buffer
encoding = io.text_encoding(encoding)
text = io.TextIOWrapper(buffer, encoding, errors, newline)
text.mode = mode
return text
Expand Down Expand Up @@ -376,7 +378,7 @@ def _sendfile_use_sendfile(self, file, offset=0, count=None):
try:
while True:
if timeout and not selector_select(timeout):
raise _socket.timeout('timed out')
raise TimeoutError('timed out')
if count:
blocksize = count - total_sent
if blocksize <= 0:
Expand Down Expand Up @@ -543,6 +545,40 @@ def fromfd(fd, family, type, proto=0):
nfd = dup(fd)
return socket(family, type, proto, nfd)

if hasattr(_socket.socket, "sendmsg"):
import array

def send_fds(sock, buffers, fds, flags=0, address=None):
""" send_fds(sock, buffers, fds[, flags[, address]]) -> integer

Send the list of file descriptors fds over an AF_UNIX socket.
"""
return sock.sendmsg(buffers, [(_socket.SOL_SOCKET,
_socket.SCM_RIGHTS, array.array("i", fds))])
__all__.append("send_fds")

if hasattr(_socket.socket, "recvmsg"):
import array

def recv_fds(sock, bufsize, maxfds, flags=0):
""" recv_fds(sock, bufsize, maxfds[, flags]) -> (data, list of file
descriptors, msg_flags, address)

Receive up to maxfds file descriptors returning the message
data and a list containing the descriptors.
"""
# Array of ints
fds = array.array("i")
msg, ancdata, flags, addr = sock.recvmsg(bufsize,
_socket.CMSG_LEN(maxfds * fds.itemsize))
for cmsg_level, cmsg_type, cmsg_data in ancdata:
if (cmsg_level == _socket.SOL_SOCKET and cmsg_type == _socket.SCM_RIGHTS):
fds.frombytes(cmsg_data[:
len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])

return msg, list(fds), flags, addr
__all__.append("recv_fds")

if hasattr(_socket.socket, "share"):
def fromshare(info):
""" fromshare(info) -> socket object
Expand Down Expand Up @@ -671,7 +707,7 @@ def readinto(self, b):
self._timeout_occurred = True
raise
except error as e:
if e.args[0] in _blocking_errnos:
if e.errno in _blocking_errnos:
return None
raise

Expand All @@ -687,7 +723,7 @@ def write(self, b):
return self._sock.send(b)
except error as e:
# XXX what about EINTR?
if e.args[0] in _blocking_errnos:
if e.errno in _blocking_errnos:
return None
raise

Expand Down Expand Up @@ -746,8 +782,9 @@ def getfqdn(name=''):
An empty argument is interpreted as meaning the local host.

First the hostname returned by gethostbyaddr() is checked, then
possibly existing aliases. In case no FQDN is available, hostname
from gethostname() is returned.
possibly existing aliases. In case no FQDN is available and `name`
was given, it is returned unchanged. If `name` was empty or '0.0.0.0',
hostname from gethostname() is returned.
"""
name = name.strip()
if not name or name == '0.0.0.0':
Expand Down
Loading