Branch merge
diff --git a/Doc/library/random.rst b/Doc/library/random.rst
index f0c4add..3040411 100644
--- a/Doc/library/random.rst
+++ b/Doc/library/random.rst
@@ -43,6 +43,12 @@
uses the system function :func:`os.urandom` to generate random numbers
from sources provided by the operating system.
+.. warning::
+
+ The generators of the :mod:`random` module should not be used for security
+ purposes. Use :func:`ssl.RAND_bytes` if you require a cryptographically
+ secure pseudorandom number generator.
+
Bookkeeping functions:
diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst
index ed547f5e..a4c9b63 100644
--- a/Doc/library/socketserver.rst
+++ b/Doc/library/socketserver.rst
@@ -153,8 +153,21 @@
.. method:: BaseServer.serve_forever(poll_interval=0.5)
Handle requests until an explicit :meth:`shutdown` request. Polls for
- shutdown every *poll_interval* seconds.
+ shutdown every *poll_interval* seconds. It also calls
+ :meth:`service_actions` which may be used by a subclass or Mixin to provide
+ various cleanup actions. For e.g. ForkingMixin class uses
+ :meth:`service_actions` to cleanup the zombie child processes.
+ .. versionchanged:: 3.3
+ Added service_actions call to the serve_forever method.
+
+
+.. method:: BaseServer.service_actions()
+
+ This is called by the serve_forever loop. This method is can be overridden
+ by Mixin's to add cleanup or service specific actions.
+
+ .. versionadded:: 3.3
.. method:: BaseServer.shutdown()
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index a528a03..ca71d20 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -164,7 +164,16 @@
.. function:: RAND_bytes(num)
- Returns *num* cryptographically strong pseudo-random bytes.
+ Returns *num* cryptographically strong pseudo-random bytes. Raises an
+ :class:`SSLError` if the PRNG has not been seeded with enough data or if the
+ operation is not supported by the current RAND method. :func:`RAND_status`
+ can be used to check the status of the PRNG and :func:`RAND_add` can be used
+ to seed the PRNG.
+
+ Read the Wikipedia article, `Cryptographically secure pseudorandom number
+ generator (CSPRNG)
+ <http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator>`_,
+ to get the requirements of a cryptographically generator.
.. versionadded:: 3.3
@@ -172,7 +181,13 @@
Returns (bytes, is_cryptographic): bytes are *num* pseudo-random bytes,
is_cryptographic is True if the bytes generated are cryptographically
- strong.
+ strong. Raises an :class:`SSLError` if the operation is not supported by the
+ current RAND method.
+
+ Generated pseudo-random byte sequences will be unique if they are of
+ sufficient length, but are not necessarily unpredictable. They can be used
+ for non-cryptographic purposes and for certain purposes in cryptographic
+ protocols, but usually not for key generation etc.
.. versionadded:: 3.3
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index 529665f..2b9bd11 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -124,6 +124,14 @@
(Patch submitted by Giampaolo Rodolà in :issue:`10784`.)
+pydoc
+-----
+
+The Tk GUI and the :func:`~pydoc.serve` function have been removed from the
+:mod:`pydoc` module: ``pydoc -g`` and :func:`~pydoc.serve` have been deprecated
+in Python 3.2.
+
+
sys
---
diff --git a/Include/import.h b/Include/import.h
index 6331edf..45544111 100644
--- a/Include/import.h
+++ b/Include/import.h
@@ -44,7 +44,7 @@
const char *name /* UTF-8 encoded string */
);
PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(
- char *name, /* UTF-8 encoded string */
+ const char *name, /* UTF-8 encoded string */
PyObject *globals,
PyObject *locals,
PyObject *fromlist,
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index a3b89e7..265edab 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -558,7 +558,11 @@
if not data:
break
res += data
- return bytes(res)
+ if res:
+ return bytes(res)
+ else:
+ # b'' or None
+ return data
def readinto(self, b):
"""Read up to len(b) bytes into bytearray b.
@@ -940,6 +944,12 @@
# Special case for when the number of bytes to read is unspecified.
if n is None or n == -1:
self._reset_read_buf()
+ if hasattr(self.raw, 'readall'):
+ chunk = self.raw.readall()
+ if chunk is None:
+ return buf[pos:] or None
+ else:
+ return buf[pos:] + chunk
chunks = [buf[pos:]] # Strip the consumed bytes.
current_size = 0
while True:
diff --git a/Lib/bz2.py b/Lib/bz2.py
index 9506b4a..8ffeaac 100644
--- a/Lib/bz2.py
+++ b/Lib/bz2.py
@@ -155,7 +155,7 @@
if not self.seekable():
self._check_not_closed()
raise io.UnsupportedOperation("Seeking is only supported "
- "on files opening for reading")
+ "on files open for reading")
# Fill the readahead buffer if it is empty. Returns False on EOF.
def _fill_buffer(self):
diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index e4c204d..6815f94 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -137,9 +137,7 @@
rv = f.close()
if rv == 10:
raise OSError('objdump command not found')
- with contextlib.closing(os.popen(cmd)) as f:
- data = f.read()
- res = re.search(r'\sSONAME\s+([^\s]+)', data)
+ res = re.search(r'\sSONAME\s+([^\s]+)', dump)
if not res:
return None
return res.group(1)
diff --git a/Lib/imaplib.py b/Lib/imaplib.py
index 142e27b..1b54065 100644
--- a/Lib/imaplib.py
+++ b/Lib/imaplib.py
@@ -249,15 +249,7 @@
def read(self, size):
"""Read 'size' bytes from remote."""
- chunks = []
- read = 0
- while read < size:
- data = self.file.read(min(size-read, 4096))
- if not data:
- break
- read += len(data)
- chunks.append(data)
- return b''.join(chunks)
+ return self.file.read(size)
def readline(self):
diff --git a/Lib/packaging/tests/support.py b/Lib/packaging/tests/support.py
index 6d60b9e..66b5583 100644
--- a/Lib/packaging/tests/support.py
+++ b/Lib/packaging/tests/support.py
@@ -253,6 +253,15 @@
return d
+def fake_dec(*args, **kw):
+ """Fake decorator"""
+ def _wrap(func):
+ def __wrap(*args, **kw):
+ return func(*args, **kw)
+ return __wrap
+ return _wrap
+
+
try:
from test.support import skip_unless_symlink
except ImportError:
diff --git a/Lib/packaging/tests/test_install.py b/Lib/packaging/tests/test_install.py
index 01c3dcf..c0924bf 100644
--- a/Lib/packaging/tests/test_install.py
+++ b/Lib/packaging/tests/test_install.py
@@ -6,13 +6,14 @@
from packaging.pypi.xmlrpc import Client
from packaging.metadata import Metadata
-from packaging.tests.support import LoggingCatcher, TempdirManager, unittest
+from packaging.tests.support import (LoggingCatcher, TempdirManager, unittest,
+ fake_dec)
try:
import threading
from packaging.tests.pypi_server import use_xmlrpc_server
except ImportError:
threading = None
- use_xmlrpc_server = None
+ use_xmlrpc_server = fake_dec
class InstalledDist:
diff --git a/Lib/packaging/tests/test_pypi_dist.py b/Lib/packaging/tests/test_pypi_dist.py
index b7f4e98..0c88c9b 100644
--- a/Lib/packaging/tests/test_pypi_dist.py
+++ b/Lib/packaging/tests/test_pypi_dist.py
@@ -7,12 +7,13 @@
from packaging.pypi.errors import HashDoesNotMatch, UnsupportedHashName
from packaging.tests import unittest
-from packaging.tests.support import TempdirManager, requires_zlib
+from packaging.tests.support import TempdirManager, requires_zlib, fake_dec
try:
import threading
from packaging.tests.pypi_server import use_pypi_server
except ImportError:
- threading = use_pypi_server = None
+ threading = None
+ use_pypi_server = fake_dec
def Dist(*args, **kwargs):
diff --git a/Lib/packaging/tests/test_pypi_simple.py b/Lib/packaging/tests/test_pypi_simple.py
index d50e3f4..bd50d01 100644
--- a/Lib/packaging/tests/test_pypi_simple.py
+++ b/Lib/packaging/tests/test_pypi_simple.py
@@ -10,9 +10,19 @@
from packaging.pypi.simple import Crawler
from packaging.tests import unittest
-from packaging.tests.support import TempdirManager, LoggingCatcher
-from packaging.tests.pypi_server import (use_pypi_server, PyPIServer,
- PYPI_DEFAULT_STATIC_PATH)
+from packaging.tests.support import (TempdirManager, LoggingCatcher,
+ fake_dec)
+
+try:
+ import _thread
+ from packaging.tests.pypi_server import (use_pypi_server, PyPIServer,
+ PYPI_DEFAULT_STATIC_PATH)
+except ImportError:
+ _thread = None
+ use_pypi_server = fake_dec
+ PYPI_DEFAULT_STATIC_PATH = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'pypiserver')
+
class SimpleCrawlerTestCase(TempdirManager,
@@ -28,6 +38,7 @@
return Crawler(server.full_address + base_url, *args,
**kwargs)
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server()
def test_bad_urls(self, server):
crawler = Crawler()
@@ -84,6 +95,7 @@
'http://www.famfamfam.com/">')
crawler._process_url(url, page)
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server("test_found_links")
def test_found_links(self, server):
# Browse the index, asking for a specified release version
@@ -139,6 +151,7 @@
self.assertTrue(
crawler._is_browsable("http://pypi.example.org/a/path"))
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server("with_externals")
def test_follow_externals(self, server):
# Include external pages
@@ -149,6 +162,7 @@
self.assertIn(server.full_address + "/external/external.html",
crawler._processed_urls)
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server("with_real_externals")
def test_restrict_hosts(self, server):
# Only use a list of allowed hosts is possible
@@ -159,6 +173,7 @@
self.assertNotIn(server.full_address + "/external/external.html",
crawler._processed_urls)
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server(static_filesystem_paths=["with_externals"],
static_uri_paths=["simple", "external"])
def test_links_priority(self, server):
@@ -192,6 +207,7 @@
releases[0].dists['sdist'].url['hashval'])
self.assertEqual('md5', releases[0].dists['sdist'].url['hashname'])
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server(static_filesystem_paths=["with_norel_links"],
static_uri_paths=["simple", "external"])
def test_not_scan_all_links(self, server):
@@ -217,6 +233,7 @@
self.assertIn("%s/foobar-2.0.tar.gz" % server.full_address,
crawler._processed_urls) # linked from external homepage (rel)
+ @unittest.skipIf(_thread is None, 'needs threads')
def test_uses_mirrors(self):
# When the main repository seems down, try using the given mirrors"""
server = PyPIServer("foo_bar_baz")
@@ -314,6 +331,7 @@
self.assertIn('http://example.org/some/simpleurl', found_links)
self.assertIn('http://example.org/some/download', found_links)
+ @unittest.skipIf(_thread is None, 'needs threads')
@use_pypi_server("project_list")
def test_search_projects(self, server):
# we can search the index for some projects, on their names
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 8581d63..548e71c 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -22,11 +22,6 @@
open a Web browser to interactively browse documentation. The -p option
can be used with the -b option to explicitly specify the server port.
-For platforms without a command line, "pydoc -g" starts the HTTP server
-and also pops up a little window for controlling it. This option is
-deprecated, since the server can now be controlled directly from HTTP
-clients.
-
Run "pydoc -w <name>" to write out the HTML documentation for a module
to a file named "<name>.html".
@@ -2056,272 +2051,6 @@
warnings.filterwarnings('ignore') # ignore problems during import
ModuleScanner().run(callback, key, onerror=onerror)
-# --------------------------------------------------- Web browser interface
-
-def serve(port, callback=None, completer=None):
- import http.server, email.message, select
-
- msg = 'the pydoc.serve() function is deprecated'
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
-
- class DocHandler(http.server.BaseHTTPRequestHandler):
- def send_document(self, title, contents):
- try:
- self.send_response(200)
- self.send_header('Content-Type', 'text/html; charset=UTF-8')
- self.end_headers()
- self.wfile.write(html.page(title, contents).encode('utf-8'))
- except IOError: pass
-
- def do_GET(self):
- path = self.path
- if path[-5:] == '.html': path = path[:-5]
- if path[:1] == '/': path = path[1:]
- if path and path != '.':
- try:
- obj = locate(path, forceload=1)
- except ErrorDuringImport as value:
- self.send_document(path, html.escape(str(value)))
- return
- if obj:
- self.send_document(describe(obj), html.document(obj, path))
- else:
- self.send_document(path,
-'no Python documentation found for %s' % repr(path))
- else:
- heading = html.heading(
-'<big><big><strong>Python: Index of Modules</strong></big></big>',
-'#ffffff', '#7799ee')
- def bltinlink(name):
- return '<a href="%s.html">%s</a>' % (name, name)
- names = [x for x in sys.builtin_module_names if x != '__main__']
- contents = html.multicolumn(names, bltinlink)
- indices = ['<p>' + html.bigsection(
- 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
-
- seen = {}
- for dir in sys.path:
- indices.append(html.index(dir, seen))
- contents = heading + ' '.join(indices) + '''<p align=right>
-<font color="#909090" face="helvetica, arial"><strong>
-pydoc</strong> by Ka-Ping Yee <ping@lfw.org></font>'''
- self.send_document('Index of Modules', contents)
-
- def log_message(self, *args): pass
-
- class DocServer(http.server.HTTPServer):
- def __init__(self, port, callback):
- host = 'localhost'
- self.address = (host, port)
- self.url = 'http://%s:%d/' % (host, port)
- self.callback = callback
- self.base.__init__(self, self.address, self.handler)
-
- def serve_until_quit(self):
- import select
- self.quit = False
- while not self.quit:
- rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
- if rd: self.handle_request()
- self.server_close()
-
- def server_activate(self):
- self.base.server_activate(self)
- if self.callback: self.callback(self)
-
- DocServer.base = http.server.HTTPServer
- DocServer.handler = DocHandler
- DocHandler.MessageClass = email.message.Message
- try:
- try:
- DocServer(port, callback).serve_until_quit()
- except (KeyboardInterrupt, select.error):
- pass
- finally:
- if completer: completer()
-
-# ----------------------------------------------------- graphical interface
-
-def gui():
- """Graphical interface (starts Web server and pops up a control window)."""
-
- msg = ('the pydoc.gui() function and "pydoc -g" option are deprecated\n',
- 'use "pydoc.browse() function and "pydoc -b" option instead.')
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
-
- class GUI:
- def __init__(self, window, port=7464):
- self.window = window
- self.server = None
- self.scanner = None
-
- import tkinter
- self.server_frm = tkinter.Frame(window)
- self.title_lbl = tkinter.Label(self.server_frm,
- text='Starting server...\n ')
- self.open_btn = tkinter.Button(self.server_frm,
- text='open browser', command=self.open, state='disabled')
- self.quit_btn = tkinter.Button(self.server_frm,
- text='quit serving', command=self.quit, state='disabled')
-
- self.search_frm = tkinter.Frame(window)
- self.search_lbl = tkinter.Label(self.search_frm, text='Search for')
- self.search_ent = tkinter.Entry(self.search_frm)
- self.search_ent.bind('<Return>', self.search)
- self.stop_btn = tkinter.Button(self.search_frm,
- text='stop', pady=0, command=self.stop, state='disabled')
- if sys.platform == 'win32':
- # Trying to hide and show this button crashes under Windows.
- self.stop_btn.pack(side='right')
-
- self.window.title('pydoc')
- self.window.protocol('WM_DELETE_WINDOW', self.quit)
- self.title_lbl.pack(side='top', fill='x')
- self.open_btn.pack(side='left', fill='x', expand=1)
- self.quit_btn.pack(side='right', fill='x', expand=1)
- self.server_frm.pack(side='top', fill='x')
-
- self.search_lbl.pack(side='left')
- self.search_ent.pack(side='right', fill='x', expand=1)
- self.search_frm.pack(side='top', fill='x')
- self.search_ent.focus_set()
-
- font = ('helvetica', sys.platform == 'win32' and 8 or 10)
- self.result_lst = tkinter.Listbox(window, font=font, height=6)
- self.result_lst.bind('<Button-1>', self.select)
- self.result_lst.bind('<Double-Button-1>', self.goto)
- self.result_scr = tkinter.Scrollbar(window,
- orient='vertical', command=self.result_lst.yview)
- self.result_lst.config(yscrollcommand=self.result_scr.set)
-
- self.result_frm = tkinter.Frame(window)
- self.goto_btn = tkinter.Button(self.result_frm,
- text='go to selected', command=self.goto)
- self.hide_btn = tkinter.Button(self.result_frm,
- text='hide results', command=self.hide)
- self.goto_btn.pack(side='left', fill='x', expand=1)
- self.hide_btn.pack(side='right', fill='x', expand=1)
-
- self.window.update()
- self.minwidth = self.window.winfo_width()
- self.minheight = self.window.winfo_height()
- self.bigminheight = (self.server_frm.winfo_reqheight() +
- self.search_frm.winfo_reqheight() +
- self.result_lst.winfo_reqheight() +
- self.result_frm.winfo_reqheight())
- self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
- self.expanded = 0
- self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
- self.window.wm_minsize(self.minwidth, self.minheight)
- self.window.tk.willdispatch()
-
- import threading
- threading.Thread(
- target=serve, args=(port, self.ready, self.quit)).start()
-
- def ready(self, server):
- self.server = server
- self.title_lbl.config(
- text='Python documentation server at\n' + server.url)
- self.open_btn.config(state='normal')
- self.quit_btn.config(state='normal')
-
- def open(self, event=None, url=None):
- url = url or self.server.url
- import webbrowser
- webbrowser.open(url)
-
- def quit(self, event=None):
- if self.server:
- self.server.quit = 1
- self.window.quit()
-
- def search(self, event=None):
- key = self.search_ent.get()
- self.stop_btn.pack(side='right')
- self.stop_btn.config(state='normal')
- self.search_lbl.config(text='Searching for "%s"...' % key)
- self.search_ent.forget()
- self.search_lbl.pack(side='left')
- self.result_lst.delete(0, 'end')
- self.goto_btn.config(state='disabled')
- self.expand()
-
- import threading
- if self.scanner:
- self.scanner.quit = 1
- self.scanner = ModuleScanner()
- threading.Thread(target=self.scanner.run,
- args=(self.update, key, self.done)).start()
-
- def update(self, path, modname, desc):
- if modname[-9:] == '.__init__':
- modname = modname[:-9] + ' (package)'
- self.result_lst.insert('end',
- modname + ' - ' + (desc or '(no description)'))
-
- def stop(self, event=None):
- if self.scanner:
- self.scanner.quit = 1
- self.scanner = None
-
- def done(self):
- self.scanner = None
- self.search_lbl.config(text='Search for')
- self.search_lbl.pack(side='left')
- self.search_ent.pack(side='right', fill='x', expand=1)
- if sys.platform != 'win32': self.stop_btn.forget()
- self.stop_btn.config(state='disabled')
-
- def select(self, event=None):
- self.goto_btn.config(state='normal')
-
- def goto(self, event=None):
- selection = self.result_lst.curselection()
- if selection:
- modname = self.result_lst.get(selection[0]).split()[0]
- self.open(url=self.server.url + modname + '.html')
-
- def collapse(self):
- if not self.expanded: return
- self.result_frm.forget()
- self.result_scr.forget()
- self.result_lst.forget()
- self.bigwidth = self.window.winfo_width()
- self.bigheight = self.window.winfo_height()
- self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
- self.window.wm_minsize(self.minwidth, self.minheight)
- self.expanded = 0
-
- def expand(self):
- if self.expanded: return
- self.result_frm.pack(side='bottom', fill='x')
- self.result_scr.pack(side='right', fill='y')
- self.result_lst.pack(side='top', fill='both', expand=1)
- self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
- self.window.wm_minsize(self.minwidth, self.bigminheight)
- self.expanded = 1
-
- def hide(self, event=None):
- self.stop()
- self.collapse()
-
- import tkinter
- try:
- root = tkinter.Tk()
- # Tk will crash if pythonw.exe has an XP .manifest
- # file and the root has is not destroyed explicitly.
- # If the problem is ever fixed in Tk, the explicit
- # destroy can go.
- try:
- gui = GUI(root)
- root.mainloop()
- finally:
- root.destroy()
- except KeyboardInterrupt:
- pass
-
-
# --------------------------------------- enhanced Web browser interface
def _start_server(urlhandler, port):
@@ -2778,15 +2507,12 @@
sys.path.insert(0, '.')
try:
- opts, args = getopt.getopt(sys.argv[1:], 'bgk:p:w')
+ opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
writing = False
start_server = False
open_browser = False
port = None
for opt, val in opts:
- if opt == '-g':
- gui()
- return
if opt == '-b':
start_server = True
open_browser = True
@@ -2847,9 +2573,6 @@
to interactively browse documentation. The -p option can be used with
the -b option to explicitly specify the server port.
-{cmd} -g
- Deprecated.
-
{cmd} -w <name> ...
Write out the HTML documentation for a module to a file in the current
directory. If <name> contains a '{sep}', it is treated as a filename; if
diff --git a/Lib/socketserver.py b/Lib/socketserver.py
index 089b3ba..a2f0f39 100644
--- a/Lib/socketserver.py
+++ b/Lib/socketserver.py
@@ -82,7 +82,7 @@
data is stored externally (e.g. in the file system), a synchronous
class will essentially render the service "deaf" while one request is
being handled -- which may be for a very long time if a client is slow
-to reqd all the data it has requested. Here a threading or forking
+to recv all the data it has requested. Here a threading or forking
server is appropriate.
In some cases, it may be appropriate to process part of a request
@@ -170,6 +170,7 @@
- process_request(request, client_address)
- shutdown_request(request)
- close_request(request)
+ - service_actions()
- handle_error()
Methods for derived classes:
@@ -225,6 +226,8 @@
r, w, e = select.select([self], [], [], poll_interval)
if self in r:
self._handle_request_noblock()
+
+ self.service_actions()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
@@ -239,6 +242,14 @@
self.__shutdown_request = True
self.__is_shut_down.wait()
+ def service_actions(self):
+ """Called by the serve_forever() loop.
+
+ May be overridden by a subclass / Mixin to implement any code that
+ needs to be run during the loop.
+ """
+ pass
+
# The distinction between handling, getting, processing and
# finishing a request is fairly arbitrary. Remember:
#
@@ -539,9 +550,15 @@
"""
self.collect_children()
+ def service_actions(self):
+ """Collect the zombie child processes regularly in the ForkingMixin.
+
+ service_actions is called in the BaseServer's serve_forver loop.
+ """
+ self.collect_children()
+
def process_request(self, request, client_address):
"""Fork a new subprocess to process the request."""
- self.collect_children()
pid = os.fork()
if pid:
# Parent process
diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
index 59073f4..d07784d 100644
--- a/Lib/sysconfig.py
+++ b/Lib/sysconfig.py
@@ -287,14 +287,16 @@
variables.remove(name)
if name.startswith('PY_') \
- and name[3:] in renamed_variables:
+ and name[3:] in renamed_variables:
name = name[3:]
if name not in done:
done[name] = value
else:
- # bogus variable reference; just drop it since we can't deal
+ # bogus variable reference (e.g. "prefix=$/opt/python");
+ # just drop it since we can't deal
+ done[name] = value
variables.remove(name)
# strip spurious spaces
diff --git a/Lib/test/cjkencodings/hz-utf8.txt b/Lib/test/cjkencodings/hz-utf8.txt
new file mode 100644
index 0000000..7c11735
--- /dev/null
+++ b/Lib/test/cjkencodings/hz-utf8.txt
@@ -0,0 +1,2 @@
+This sentence is in ASCII.
+The next sentence is in GB.己所不欲,勿施於人。Bye.
diff --git a/Lib/test/cjkencodings/hz.txt b/Lib/test/cjkencodings/hz.txt
new file mode 100644
index 0000000..f882d46
--- /dev/null
+++ b/Lib/test/cjkencodings/hz.txt
@@ -0,0 +1,2 @@
+This sentence is in ASCII.
+The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye.
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 04e87e3..b5e5127 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -794,17 +794,14 @@
def replace_stdout():
"""Set stdout encoder error handler to backslashreplace (as stderr error
handler) to avoid UnicodeEncodeError when printing a traceback"""
- if os.name == "nt":
- # Replace sys.stdout breaks the stdout newlines on Windows: issue #8533
- return
-
import atexit
stdout = sys.stdout
sys.stdout = open(stdout.fileno(), 'w',
encoding=stdout.encoding,
errors="backslashreplace",
- closefd=False)
+ closefd=False,
+ newline='\n')
def restore_stdout():
sys.stdout.close()
diff --git a/Lib/test/test_bool.py b/Lib/test/test_bool.py
index b296870..4bab28b 100644
--- a/Lib/test/test_bool.py
+++ b/Lib/test/test_bool.py
@@ -330,6 +330,16 @@
except (Exception) as e_len:
self.assertEqual(str(e_bool), str(e_len))
+ def test_real_and_imag(self):
+ self.assertEqual(True.real, 1)
+ self.assertEqual(True.imag, 0)
+ self.assertIs(type(True.real), int)
+ self.assertIs(type(True.imag), int)
+ self.assertEqual(False.real, 0)
+ self.assertEqual(False.imag, 0)
+ self.assertIs(type(False.real), int)
+ self.assertIs(type(False.imag), int)
+
def test_main():
support.run_unittest(BoolTest)
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index b094a65..97619cf 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -385,6 +385,8 @@
except:
self.assertEqual(len(dir(sys.exc_info()[2])), 4)
+ # test that object has a __dir__()
+ self.assertEqual(sorted([].__dir__()), dir([]))
def test_divmod(self):
self.assertEqual(divmod(12, 7), (1, 5))
diff --git a/Lib/test/test_codecencodings_cn.py b/Lib/test/test_codecencodings_cn.py
index a2d9718..dca9f10 100644
--- a/Lib/test/test_codecencodings_cn.py
+++ b/Lib/test/test_codecencodings_cn.py
@@ -50,6 +50,35 @@
)
has_iso10646 = True
+class Test_HZ(test_multibytecodec_support.TestBase, unittest.TestCase):
+ encoding = 'hz'
+ tstring = test_multibytecodec_support.load_teststring('hz')
+ codectests = (
+ # test '~\n' (3 lines)
+ (b'This sentence is in ASCII.\n'
+ b'The next sentence is in GB.~{<:Ky2;S{#,~}~\n'
+ b'~{NpJ)l6HK!#~}Bye.\n',
+ 'strict',
+ 'This sentence is in ASCII.\n'
+ 'The next sentence is in GB.'
+ '\u5df1\u6240\u4e0d\u6b32\uff0c\u52ff\u65bd\u65bc\u4eba\u3002'
+ 'Bye.\n'),
+ # test '~\n' (4 lines)
+ (b'This sentence is in ASCII.\n'
+ b'The next sentence is in GB.~\n'
+ b'~{<:Ky2;S{#,NpJ)l6HK!#~}~\n'
+ b'Bye.\n',
+ 'strict',
+ 'This sentence is in ASCII.\n'
+ 'The next sentence is in GB.'
+ '\u5df1\u6240\u4e0d\u6b32\uff0c\u52ff\u65bd\u65bc\u4eba\u3002'
+ 'Bye.\n'),
+ # invalid bytes
+ (b'ab~cd', 'replace', 'ab\uFFFDd'),
+ (b'ab\xffcd', 'replace', 'ab\uFFFDcd'),
+ (b'ab~{\x81\x81\x41\x44~}cd', 'replace', 'ab\uFFFD\uFFFD\u804Acd'),
+ )
+
def test_main():
support.run_unittest(__name__)
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 31731d2..0fae2df 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1631,12 +1631,7 @@
for attr, obj in env.items():
setattr(X, attr, obj)
setattr(X, name, ErrDescr())
- try:
- runner(X())
- except MyException:
- pass
- else:
- self.fail("{0!r} didn't raise".format(name))
+ self.assertRaises(MyException, runner, X())
def test_specials(self):
# Testing special operators...
diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py
index c3355b9..f495e18 100644
--- a/Lib/test/test_descrtut.py
+++ b/Lib/test/test_descrtut.py
@@ -170,6 +170,7 @@
'__contains__',
'__delattr__',
'__delitem__',
+ '__dir__',
'__doc__',
'__eq__',
'__format__',
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 3724b5c..c0dc6ec 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -833,14 +833,17 @@
# Inject some None's in there to simulate EWOULDBLOCK
rawio = self.MockRawIO((b"abc", b"d", None, b"efg", None, None, None))
bufio = self.tp(rawio)
-
self.assertEqual(b"abcd", bufio.read(6))
self.assertEqual(b"e", bufio.read(1))
self.assertEqual(b"fg", bufio.read())
self.assertEqual(b"", bufio.peek(1))
- self.assertTrue(None is bufio.read())
+ self.assertIsNone(bufio.read())
self.assertEqual(b"", bufio.read())
+ rawio = self.MockRawIO((b"a", None, None))
+ self.assertEqual(b"a", rawio.readall())
+ self.assertIsNone(rawio.readall())
+
def test_read_past_eof(self):
rawio = self.MockRawIO((b"abc", b"d", b"efg"))
bufio = self.tp(rawio)
@@ -2512,6 +2515,8 @@
self.assertRaises(ValueError, f.read)
if hasattr(f, "read1"):
self.assertRaises(ValueError, f.read1, 1024)
+ if hasattr(f, "readall"):
+ self.assertRaises(ValueError, f.readall)
if hasattr(f, "readinto"):
self.assertRaises(ValueError, f.readinto, bytearray(1024))
self.assertRaises(ValueError, f.readline)
diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py
index fe772e1..86c68dc 100644
--- a/Lib/test/test_multibytecodec.py
+++ b/Lib/test/test_multibytecodec.py
@@ -256,6 +256,36 @@
# Any ISO 2022 codec will cause the segfault
myunichr(x).encode('iso_2022_jp', 'ignore')
+class TestStateful(unittest.TestCase):
+ text = '\u4E16\u4E16'
+ encoding = 'iso-2022-jp'
+ expected = b'\x1b$B@$@$'
+ expected_reset = b'\x1b$B@$@$\x1b(B'
+
+ def test_encode(self):
+ self.assertEqual(self.text.encode(self.encoding), self.expected_reset)
+
+ def test_incrementalencoder(self):
+ encoder = codecs.getincrementalencoder(self.encoding)()
+ output = b''.join(
+ encoder.encode(char)
+ for char in self.text)
+ self.assertEqual(output, self.expected)
+
+ def test_incrementalencoder_final(self):
+ encoder = codecs.getincrementalencoder(self.encoding)()
+ last_index = len(self.text) - 1
+ output = b''.join(
+ encoder.encode(char, index == last_index)
+ for index, char in enumerate(self.text))
+ self.assertEqual(output, self.expected_reset)
+
+class TestHZStateful(TestStateful):
+ text = '\u804a\u804a'
+ encoding = 'hz'
+ expected = b'~{ADAD'
+ expected_reset = b'~{ADAD~}'
+
def test_main():
support.run_unittest(__name__)
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index 3134031..cdd3f3e 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -226,10 +226,16 @@
TIMEOUT_FULL = 10
TIMEOUT_HALF = 5
- def check_signum(self, *signals):
+ def handler(self, signum, frame):
+ pass
+
+ def check_signum(self, *signals, **kw):
data = os.read(self.read, len(signals)+1)
raised = struct.unpack('%uB' % len(data), data)
- self.assertSequenceEqual(raised, signals)
+ if kw.get('unordered', False):
+ raised = set(raised)
+ signals = set(signals)
+ self.assertEqual(raised, signals)
def test_wakeup_fd_early(self):
import select
@@ -259,16 +265,38 @@
self.check_signum(signal.SIGALRM)
def test_signum(self):
- old_handler = signal.signal(signal.SIGUSR1, lambda x,y:None)
+ old_handler = signal.signal(signal.SIGUSR1, self.handler)
self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)
os.kill(os.getpid(), signal.SIGUSR1)
os.kill(os.getpid(), signal.SIGALRM)
self.check_signum(signal.SIGUSR1, signal.SIGALRM)
+ @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
+ 'need signal.pthread_sigmask()')
+ @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
+ 'need signal.pthread_kill()')
+ def test_pending(self):
+ signum1 = signal.SIGUSR1
+ signum2 = signal.SIGUSR2
+ tid = threading.current_thread().ident
+
+ old_handler = signal.signal(signum1, self.handler)
+ self.addCleanup(signal.signal, signum1, old_handler)
+ old_handler = signal.signal(signum2, self.handler)
+ self.addCleanup(signal.signal, signum2, old_handler)
+
+ signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
+ signal.pthread_kill(tid, signum1)
+ signal.pthread_kill(tid, signum2)
+ # Unblocking the 2 signals calls the C signal handler twice
+ signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
+
+ self.check_signum(signum1, signum2, unordered=True)
+
def setUp(self):
import fcntl
- self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None)
+ self.alrm = signal.signal(signal.SIGALRM, self.handler)
self.read, self.write = os.pipe()
flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0)
flags = flags | os.O_NONBLOCK
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 8c21975..5193c15 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -109,6 +109,8 @@
if v:
data = ssl.RAND_bytes(16)
self.assertEqual(len(data), 16)
+ else:
+ self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
try:
ssl.RAND_egd(1)
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index 77c2364..96f75f2 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -14,12 +14,12 @@
_get_default_scheme, _expand_vars,
get_scheme_names, get_config_var, _main)
+
class TestSysConfig(unittest.TestCase):
def setUp(self):
super(TestSysConfig, self).setUp()
self.sys_path = sys.path[:]
- self.makefile = None
# patching os.uname
if hasattr(os, 'uname'):
self.uname = os.uname
@@ -47,8 +47,6 @@
def tearDown(self):
sys.path[:] = self.sys_path
- if self.makefile is not None:
- os.unlink(self.makefile)
self._cleanup_testfn()
if self.uname is not None:
os.uname = self.uname
@@ -208,9 +206,9 @@
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3'%(arch,))
+ '-dynamic -DNDEBUG -g -O3' % arch)
- self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,))
+ self.assertEqual(get_platform(), 'macosx-10.4-%s' % arch)
# linux debian sarge
os.name = 'posix'
@@ -228,12 +226,6 @@
config_h = sysconfig.get_config_h_filename()
self.assertTrue(os.path.isfile(config_h), config_h)
- @unittest.skipIf(sys.platform.startswith('win'),
- 'Test is not Windows compatible')
- def test_get_makefile_filename(self):
- makefile = sysconfig.get_makefile_filename()
- self.assertTrue(os.path.isfile(makefile), makefile)
-
def test_get_scheme_names(self):
wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user',
'posix_home', 'posix_prefix', 'posix_user')
@@ -329,8 +321,34 @@
self.assertEqual(my_platform, test_platform)
+class MakefileTests(unittest.TestCase):
+
+ @unittest.skipIf(sys.platform.startswith('win'),
+ 'Test is not Windows compatible')
+ def test_get_makefile_filename(self):
+ makefile = sysconfig.get_makefile_filename()
+ self.assertTrue(os.path.isfile(makefile), makefile)
+
+ def test_parse_makefile(self):
+ self.addCleanup(unlink, TESTFN)
+ with open(TESTFN, "w") as makefile:
+ print("var1=a$(VAR2)", file=makefile)
+ print("VAR2=b$(var3)", file=makefile)
+ print("var3=42", file=makefile)
+ print("var4=$/invalid", file=makefile)
+ print("var5=dollar$$5", file=makefile)
+ vars = sysconfig._parse_makefile(TESTFN)
+ self.assertEqual(vars, {
+ 'var1': 'ab42',
+ 'VAR2': 'b42',
+ 'var3': 42,
+ 'var4': '$/invalid',
+ 'var5': 'dollar$5',
+ })
+
+
def test_main():
- run_unittest(TestSysConfig)
+ run_unittest(TestSysConfig, MakefileTests)
if __name__ == "__main__":
test_main()
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 04d126f..dff1252 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -908,8 +908,8 @@
MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR)
XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax
LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \
- tkinter/test/test_ttk site-packages test \
- test/decimaltestdata test/xmltestdata test/subprocessdata \
+ tkinter/test/test_ttk site-packages test \
+ test/cjkencodings test/decimaltestdata test/xmltestdata test/subprocessdata \
test/tracedmodules test/encoded_modules \
collections concurrent concurrent/futures encodings \
email email/mime email/test email/test/data \
diff --git a/Misc/NEWS b/Misc/NEWS
index 967e2ef..b7f3907 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,11 @@
Core and Builtins
-----------------
+- Issue #12166: Move implementations of dir() specialized for various types into
+ the __dir__() methods of those types.
+
+- Issue #5715: In socketserver, close the server socket in the child process.
+
- Correct lookup of __dir__ on objects. Among other things, this causes errors
besides AttributeError found on lookup to be propagated.
@@ -156,6 +161,39 @@
Library
-------
+- Issue #12175: BufferedReader.read(-1) now calls raw.readall() if available.
+
+- Issue #12175: FileIO.readall() now only reads the file position and size
+ once.
+
+- Issue #12180: Fixed a few remaining errors in test_packaging when no
+ threading.
+
+- Issue #12175: RawIOBase.readall() now returns None if read() returns None.
+
+- Issue #12175: FileIO.readall() now raises a ValueError instead of an IOError
+ if the file is closed.
+
+- Issue #11109: New service_action method for BaseServer, used by ForkingMixin
+ class for cleanup. Initial Patch by Justin Wark.
+
+- Issue #12045: Avoid duplicate execution of command in
+ ctypes.util._get_soname(). Patch by Sijin Joseph.
+
+- Issue #10818: Remove the Tk GUI and the serve() function of the pydoc module,
+ pydoc -g has been deprecated in Python 3.2 and it has a new enhanced web
+ server.
+
+- Issue #1441530: In imaplib, read the data in one chunk to speed up large
+ reads and simplify code.
+
+- Issue #12070: Fix the Makefile parser of the sysconfig module to handle
+ correctly references to "bogus variable" (e.g. "prefix=$/opt/python").
+
+- Issue #12100: Don't reset incremental encoders of CJK codecs at each call to
+ their encode() method anymore, but continue to call the reset() method if the
+ final argument is True.
+
- Issue #12049: Add RAND_bytes() and RAND_pseudo_bytes() functions to the ssl
module.
@@ -804,7 +842,11 @@
C-API
-----
-- PY_PATCHLEVEL_REVISION has been removed, since it's meaningless with Mercurial.
+- PY_PATCHLEVEL_REVISION has been removed, since it's meaningless with
+ Mercurial.
+
+- Issue #12173: The first argument of PyImport_ImportModuleLevel is now `const
+ char *` instead of `char *1`.
Documentation
-------------
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 44bdac6..6f5bd48 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -36,6 +36,7 @@
PyObject *_PyIO_str_read;
PyObject *_PyIO_str_read1;
PyObject *_PyIO_str_readable;
+PyObject *_PyIO_str_readall;
PyObject *_PyIO_str_readinto;
PyObject *_PyIO_str_readline;
PyObject *_PyIO_str_reset;
@@ -767,6 +768,8 @@
goto fail;
if (!(_PyIO_str_readable = PyUnicode_InternFromString("readable")))
goto fail;
+ if (!(_PyIO_str_readall = PyUnicode_InternFromString("readall")))
+ goto fail;
if (!(_PyIO_str_readinto = PyUnicode_InternFromString("readinto")))
goto fail;
if (!(_PyIO_str_readline = PyUnicode_InternFromString("readline")))
diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h
index 925e4f2..9174bdd 100644
--- a/Modules/_io/_iomodule.h
+++ b/Modules/_io/_iomodule.h
@@ -155,6 +155,7 @@
extern PyObject *_PyIO_str_read;
extern PyObject *_PyIO_str_read1;
extern PyObject *_PyIO_str_readable;
+extern PyObject *_PyIO_str_readall;
extern PyObject *_PyIO_str_readinto;
extern PyObject *_PyIO_str_readline;
extern PyObject *_PyIO_str_reset;
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 3b8b7e9..63ae1cb 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1407,32 +1407,57 @@
_bufferedreader_read_all(buffered *self)
{
Py_ssize_t current_size;
- PyObject *res, *data = NULL;
- PyObject *chunks = PyList_New(0);
-
- if (chunks == NULL)
- return NULL;
+ PyObject *res, *data = NULL, *chunk, *chunks;
/* First copy what we have in the current buffer. */
current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
if (current_size) {
data = PyBytes_FromStringAndSize(
self->buffer + self->pos, current_size);
- if (data == NULL) {
- Py_DECREF(chunks);
+ if (data == NULL)
return NULL;
- }
}
_bufferedreader_reset_buf(self);
/* We're going past the buffer's bounds, flush it */
if (self->writable) {
res = _bufferedwriter_flush_unlocked(self, 1);
- if (res == NULL) {
- Py_DECREF(chunks);
+ if (res == NULL)
return NULL;
- }
Py_CLEAR(res);
}
+
+ if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
+ chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
+ if (chunk == NULL)
+ return NULL;
+ if (chunk != Py_None && !PyBytes_Check(chunk)) {
+ Py_XDECREF(data);
+ Py_DECREF(chunk);
+ PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
+ return NULL;
+ }
+ if (chunk == Py_None) {
+ if (current_size == 0)
+ return chunk;
+ else {
+ Py_DECREF(chunk);
+ return data;
+ }
+ }
+ else if (current_size) {
+ PyBytes_Concat(&data, chunk);
+ Py_DECREF(chunk);
+ if (data == NULL)
+ return NULL;
+ return data;
+ } else
+ return chunk;
+ }
+
+ chunks = PyList_New(0);
+ if (chunks == NULL)
+ return NULL;
+
while (1) {
if (data) {
if (PyList_Append(chunks, data) < 0) {
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 1aa5ee9..b3b9e44 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -547,14 +547,14 @@
}
static size_t
-new_buffersize(fileio *self, size_t currentsize)
+new_buffersize(fileio *self, size_t currentsize
+#ifdef HAVE_FSTAT
+ , off_t pos, off_t end
+#endif
+ )
{
#ifdef HAVE_FSTAT
- off_t pos, end;
- struct stat st;
- if (fstat(self->fd, &st) == 0) {
- end = st.st_size;
- pos = lseek(self->fd, 0L, SEEK_CUR);
+ if (end != (off_t)-1) {
/* Files claiming a size smaller than SMALLCHUNK may
actually be streaming pseudo-files. In this case, we
apply the more aggressive algorithm below.
@@ -579,10 +579,17 @@
static PyObject *
fileio_readall(fileio *self)
{
+#ifdef HAVE_FSTAT
+ struct stat st;
+ off_t pos, end;
+#endif
PyObject *result;
Py_ssize_t total = 0;
int n;
+ size_t newsize;
+ if (self->fd < 0)
+ return err_closed();
if (!_PyVerify_fd(self->fd))
return PyErr_SetFromErrno(PyExc_IOError);
@@ -590,8 +597,23 @@
if (result == NULL)
return NULL;
+#ifdef HAVE_FSTAT
+#if defined(MS_WIN64) || defined(MS_WINDOWS)
+ pos = _lseeki64(self->fd, 0L, SEEK_CUR);
+#else
+ pos = lseek(self->fd, 0L, SEEK_CUR);
+#endif
+ if (fstat(self->fd, &st) == 0)
+ end = st.st_size;
+ else
+ end = (off_t)-1;
+#endif
while (1) {
- size_t newsize = new_buffersize(self, total);
+#ifdef HAVE_FSTAT
+ newsize = new_buffersize(self, total, pos, end);
+#else
+ newsize = new_buffersize(self, total);
+#endif
if (newsize > PY_SSIZE_T_MAX || newsize <= 0) {
PyErr_SetString(PyExc_OverflowError,
"unbounded read returned more bytes "
@@ -630,6 +652,9 @@
return NULL;
}
total += n;
+#ifdef HAVE_FSTAT
+ pos += n;
+#endif
}
if (PyBytes_GET_SIZE(result) > total) {
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index ec7a242..f06f562 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -815,6 +815,14 @@
Py_DECREF(chunks);
return NULL;
}
+ if (data == Py_None) {
+ if (PyList_GET_SIZE(chunks) == 0) {
+ Py_DECREF(chunks);
+ return data;
+ }
+ Py_DECREF(data);
+ break;
+ }
if (!PyBytes_Check(data)) {
Py_DECREF(chunks);
Py_DECREF(data);
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 35bd922..70d062b 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1513,8 +1513,13 @@
PyObject *decoded;
if (bytes == NULL)
goto fail;
- decoded = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_decode,
- bytes, Py_True, NULL);
+
+ if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type)
+ decoded = _PyIncrementalNewlineDecoder_decode(self->decoder,
+ bytes, 1);
+ else
+ decoded = PyObject_CallMethodObjArgs(
+ self->decoder, _PyIO_str_decode, bytes, Py_True, NULL);
Py_DECREF(bytes);
if (decoded == NULL)
goto fail;
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index bf10cbb..af0d971 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -1,7 +1,7 @@
/* Authors: Gregory P. Smith & Jeffrey Yasskin */
#include "Python.h"
-#ifdef HAVE_PIPE2
-#define _GNU_SOURCE
+#if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
#endif
#include <unistd.h>
#include <fcntl.h>
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index e137ff6..bb8176f 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -479,7 +479,7 @@
MultibyteEncodeBuffer buf;
Py_ssize_t finalsize, r = 0;
- if (datalen == 0)
+ if (datalen == 0 && !(flags & MBENC_RESET))
return PyBytes_FromStringAndSize(NULL, 0);
buf.excobj = NULL;
@@ -515,7 +515,7 @@
break;
}
- if (codec->encreset != NULL)
+ if (codec->encreset != NULL && (flags & MBENC_RESET))
for (;;) {
Py_ssize_t outleft;
@@ -785,8 +785,8 @@
inbuf_end = inbuf + datalen;
r = multibytecodec_encode(ctx->codec, &ctx->state,
- (const Py_UNICODE **)&inbuf,
- datalen, ctx->errors, final ? MBENC_FLUSH : 0);
+ (const Py_UNICODE **)&inbuf, datalen,
+ ctx->errors, final ? MBENC_FLUSH | MBENC_RESET : 0);
if (r == NULL) {
/* recover the original pending buffer */
if (origpending > 0)
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 83c47ce..46c2c42 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -1005,9 +1005,10 @@
faulthandler_env_options(void)
{
PyObject *xoptions, *key, *module, *res;
- int enable;
if (!Py_GETENV("PYTHONFAULTHANDLER")) {
+ int has_key;
+
xoptions = PySys_GetXOptions();
if (xoptions == NULL)
return -1;
@@ -1016,13 +1017,11 @@
if (key == NULL)
return -1;
- enable = PyDict_Contains(xoptions, key);
+ has_key = PyDict_Contains(xoptions, key);
Py_DECREF(key);
- if (!enable)
+ if (!has_key)
return 0;
}
- else
- enable = 1;
module = PyImport_ImportModule("faulthandler");
if (module == NULL) {
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index ff65f04..6d27ab3 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -177,17 +177,18 @@
trip_signal(int sig_num)
{
unsigned char byte;
+
Handlers[sig_num].tripped = 1;
+ if (wakeup_fd != -1) {
+ byte = (unsigned char)sig_num;
+ write(wakeup_fd, &byte, 1);
+ }
if (is_tripped)
return;
/* Set is_tripped after setting .tripped, as it gets
cleared in PyErr_CheckSignals() before .tripped. */
is_tripped = 1;
Py_AddPendingCall(checksignals_witharg, NULL);
- if (wakeup_fd != -1) {
- byte = (unsigned char)sig_num;
- write(wakeup_fd, &byte, 1);
- }
}
static void
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 8107b98..d18b5b1 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2782,6 +2782,7 @@
PyErr_Format(PyExc_TypeError,
"sendto() takes 2 or 3 arguments (%d given)",
arglen);
+ return NULL;
}
if (PyErr_Occurred())
return NULL;
@@ -3144,7 +3145,7 @@
}
return PyErr_SetExcFromWindowsErr(PyExc_WindowsError, GetLastError());
}
- return PyUnicode_FromUnicode(buf, size);
+ return PyUnicode_FromUnicode(buf, size);
#else
char buf[1024];
int res;
@@ -4038,7 +4039,7 @@
static PyObject *
socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
{
- static char* kwnames[] = {"host", "port", "family", "type", "proto",
+ static char* kwnames[] = {"host", "port", "family", "type", "proto",
"flags", 0};
struct addrinfo hints, *res;
struct addrinfo *res0 = NULL;
@@ -4053,7 +4054,7 @@
family = socktype = protocol = flags = 0;
family = AF_UNSPEC;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iiii:getaddrinfo",
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iiii:getaddrinfo",
kwnames, &hobj, &pobj, &family, &socktype,
&protocol, &flags)) {
return NULL;
@@ -4289,7 +4290,7 @@
PyObject *list;
int i;
struct if_nameindex *ni;
-
+
ni = if_nameindex();
if (ni == NULL) {
PyErr_SetFromErrno(socket_error);
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index de89a76..a83bf8b 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -1196,7 +1196,7 @@
int *p_ispackage, PyObject **p_modpath)
{
PyObject *code = NULL, *toc_entry, *subname;
- PyObject *path, *fullpath;
+ PyObject *path, *fullpath = NULL;
struct st_zip_searchorder *zso;
subname = get_subname(fullname);
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 0106ba3..fb7864f 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -499,7 +499,7 @@
Py_CLEAR(self->code);
if (size == 1)
self->code = PyTuple_GET_ITEM(args, 0);
- else if (size > 1)
+ else /* size > 1 */
self->code = args;
Py_INCREF(self->code);
return 0;
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 06f58d8..3817ef3 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -413,6 +413,34 @@
return 0;
}
+static PyObject *
+module_dir(PyObject *self, PyObject *args)
+{
+ PyObject *result = NULL;
+ PyObject *dict = PyObject_GetAttrString(self, "__dict__");
+
+ if (dict != NULL) {
+ if (PyDict_Check(dict))
+ result = PyDict_Keys(dict);
+ else {
+ const char *name = PyModule_GetName(self);
+ if (name)
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.__dict__ is not a dictionary",
+ name);
+ }
+ }
+
+ Py_XDECREF(dict);
+ return result;
+}
+
+static PyMethodDef module_methods[] = {
+ {"__dir__", module_dir, METH_NOARGS,
+ PyDoc_STR("__dir__() -> list\nspecialized dir() implementation")},
+ {0}
+};
+
PyDoc_STRVAR(module_doc,
"module(name[, doc])\n\
@@ -449,7 +477,7 @@
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ module_methods, /* tp_methods */
module_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
diff --git a/Objects/object.c b/Objects/object.c
index d8e2ffb..e42c1d9 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1182,66 +1182,6 @@
return x->ob_type->tp_call != NULL;
}
-/* ------------------------- PyObject_Dir() helpers ------------------------- */
-
-/* Helper for PyObject_Dir.
- Merge the __dict__ of aclass into dict, and recursively also all
- the __dict__s of aclass's base classes. The order of merging isn't
- defined, as it's expected that only the final set of dict keys is
- interesting.
- Return 0 on success, -1 on error.
-*/
-
-static int
-merge_class_dict(PyObject* dict, PyObject* aclass)
-{
- PyObject *classdict;
- PyObject *bases;
-
- assert(PyDict_Check(dict));
- assert(aclass);
-
- /* Merge in the type's dict (if any). */
- classdict = PyObject_GetAttrString(aclass, "__dict__");
- if (classdict == NULL)
- PyErr_Clear();
- else {
- int status = PyDict_Update(dict, classdict);
- Py_DECREF(classdict);
- if (status < 0)
- return -1;
- }
-
- /* Recursively merge in the base types' (if any) dicts. */
- bases = PyObject_GetAttrString(aclass, "__bases__");
- if (bases == NULL)
- PyErr_Clear();
- else {
- /* We have no guarantee that bases is a real tuple */
- Py_ssize_t i, n;
- n = PySequence_Size(bases); /* This better be right */
- if (n < 0)
- PyErr_Clear();
- else {
- for (i = 0; i < n; i++) {
- int status;
- PyObject *base = PySequence_GetItem(bases, i);
- if (base == NULL) {
- Py_DECREF(bases);
- return -1;
- }
- status = merge_class_dict(dict, base);
- Py_DECREF(base);
- if (status < 0) {
- Py_DECREF(bases);
- return -1;
- }
- }
- }
- Py_DECREF(bases);
- }
- return 0;
-}
/* Helper for PyObject_Dir without arguments: returns the local scope. */
static PyObject *
@@ -1269,133 +1209,34 @@
return names;
}
-/* Helper for PyObject_Dir of type objects: returns __dict__ and __bases__.
- We deliberately don't suck up its __class__, as methods belonging to the
- metaclass would probably be more confusing than helpful.
-*/
-static PyObject *
-_specialized_dir_type(PyObject *obj)
-{
- PyObject *result = NULL;
- PyObject *dict = PyDict_New();
-
- if (dict != NULL && merge_class_dict(dict, obj) == 0)
- result = PyDict_Keys(dict);
-
- Py_XDECREF(dict);
- return result;
-}
-
-/* Helper for PyObject_Dir of module objects: returns the module's __dict__. */
-static PyObject *
-_specialized_dir_module(PyObject *obj)
-{
- PyObject *result = NULL;
- PyObject *dict = PyObject_GetAttrString(obj, "__dict__");
-
- if (dict != NULL) {
- if (PyDict_Check(dict))
- result = PyDict_Keys(dict);
- else {
- const char *name = PyModule_GetName(obj);
- if (name)
- PyErr_Format(PyExc_TypeError,
- "%.200s.__dict__ is not a dictionary",
- name);
- }
- }
-
- Py_XDECREF(dict);
- return result;
-}
-
-/* Helper for PyObject_Dir of generic objects: returns __dict__, __class__,
- and recursively up the __class__.__bases__ chain.
-*/
-static PyObject *
-_generic_dir(PyObject *obj)
-{
- PyObject *result = NULL;
- PyObject *dict = NULL;
- PyObject *itsclass = NULL;
-
- /* Get __dict__ (which may or may not be a real dict...) */
- dict = PyObject_GetAttrString(obj, "__dict__");
- if (dict == NULL) {
- PyErr_Clear();
- dict = PyDict_New();
- }
- else if (!PyDict_Check(dict)) {
- Py_DECREF(dict);
- dict = PyDict_New();
- }
- else {
- /* Copy __dict__ to avoid mutating it. */
- PyObject *temp = PyDict_Copy(dict);
- Py_DECREF(dict);
- dict = temp;
- }
-
- if (dict == NULL)
- goto error;
-
- /* Merge in attrs reachable from its class. */
- itsclass = PyObject_GetAttrString(obj, "__class__");
- if (itsclass == NULL)
- /* XXX(tomer): Perhaps fall back to obj->ob_type if no
- __class__ exists? */
- PyErr_Clear();
- else {
- if (merge_class_dict(dict, itsclass) != 0)
- goto error;
- }
-
- result = PyDict_Keys(dict);
- /* fall through */
-error:
- Py_XDECREF(itsclass);
- Py_XDECREF(dict);
- return result;
-}
-
-/* Helper for PyObject_Dir: object introspection.
- This calls one of the above specialized versions if no __dir__ method
- exists. */
+/* Helper for PyObject_Dir: object introspection. */
static PyObject *
_dir_object(PyObject *obj)
{
- PyObject *result = NULL;
+ PyObject *result;
static PyObject *dir_str = NULL;
PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str);
assert(obj);
if (dirfunc == NULL) {
- if (PyErr_Occurred())
- return NULL;
- /* use default implementation */
- if (PyModule_Check(obj))
- result = _specialized_dir_module(obj);
- else if (PyType_Check(obj))
- result = _specialized_dir_type(obj);
- else
- result = _generic_dir(obj);
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_TypeError, "object does not provide __dir__");
+ return NULL;
}
- else {
- /* use __dir__ */
- result = PyObject_CallFunctionObjArgs(dirfunc, NULL);
- Py_DECREF(dirfunc);
- if (result == NULL)
- return NULL;
+ /* use __dir__ */
+ result = PyObject_CallFunctionObjArgs(dirfunc, NULL);
+ Py_DECREF(dirfunc);
+ if (result == NULL)
+ return NULL;
- /* result must be a list */
- /* XXX(gbrandl): could also check if all items are strings */
- if (!PyList_Check(result)) {
- PyErr_Format(PyExc_TypeError,
- "__dir__() must return a list, not %.200s",
- Py_TYPE(result)->tp_name);
- Py_DECREF(result);
- result = NULL;
- }
+ /* result must be a list */
+ /* XXX(gbrandl): could also check if all items are strings */
+ if (!PyList_Check(result)) {
+ PyErr_Format(PyExc_TypeError,
+ "__dir__() must return a list, not %.200s",
+ Py_TYPE(result)->tp_name);
+ Py_DECREF(result);
+ result = NULL;
}
return result;
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 48edad8..ebfddb3 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -607,16 +607,18 @@
goto done;
newsize = PyUnicode_GET_SIZE(listrepr);
result = PyUnicode_FromUnicode(NULL, newsize);
- if (result) {
- u = PyUnicode_AS_UNICODE(result);
- *u++ = '{';
- /* Omit the brackets from the listrepr */
- Py_UNICODE_COPY(u, PyUnicode_AS_UNICODE(listrepr)+1,
- PyUnicode_GET_SIZE(listrepr)-2);
- u += newsize-2;
- *u++ = '}';
- }
+ if (result == NULL)
+ goto done;
+
+ u = PyUnicode_AS_UNICODE(result);
+ *u++ = '{';
+ /* Omit the brackets from the listrepr */
+ Py_UNICODE_COPY(u, PyUnicode_AS_UNICODE(listrepr)+1,
+ newsize-2);
+ u += newsize-2;
+ *u = '}';
Py_DECREF(listrepr);
+
if (Py_TYPE(so) != &PySet_Type) {
PyObject *tmp = PyUnicode_FromFormat("%s(%U)",
Py_TYPE(so)->tp_name,
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 434608f..02f86ef 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2572,6 +2572,82 @@
return PyDict_New();
}
+/*
+ Merge the __dict__ of aclass into dict, and recursively also all
+ the __dict__s of aclass's base classes. The order of merging isn't
+ defined, as it's expected that only the final set of dict keys is
+ interesting.
+ Return 0 on success, -1 on error.
+*/
+
+static int
+merge_class_dict(PyObject *dict, PyObject *aclass)
+{
+ PyObject *classdict;
+ PyObject *bases;
+
+ assert(PyDict_Check(dict));
+ assert(aclass);
+
+ /* Merge in the type's dict (if any). */
+ classdict = PyObject_GetAttrString(aclass, "__dict__");
+ if (classdict == NULL)
+ PyErr_Clear();
+ else {
+ int status = PyDict_Update(dict, classdict);
+ Py_DECREF(classdict);
+ if (status < 0)
+ return -1;
+ }
+
+ /* Recursively merge in the base types' (if any) dicts. */
+ bases = PyObject_GetAttrString(aclass, "__bases__");
+ if (bases == NULL)
+ PyErr_Clear();
+ else {
+ /* We have no guarantee that bases is a real tuple */
+ Py_ssize_t i, n;
+ n = PySequence_Size(bases); /* This better be right */
+ if (n < 0)
+ PyErr_Clear();
+ else {
+ for (i = 0; i < n; i++) {
+ int status;
+ PyObject *base = PySequence_GetItem(bases, i);
+ if (base == NULL) {
+ Py_DECREF(bases);
+ return -1;
+ }
+ status = merge_class_dict(dict, base);
+ Py_DECREF(base);
+ if (status < 0) {
+ Py_DECREF(bases);
+ return -1;
+ }
+ }
+ }
+ Py_DECREF(bases);
+ }
+ return 0;
+}
+
+/* __dir__ for type objects: returns __dict__ and __bases__.
+ We deliberately don't suck up its __class__, as methods belonging to the
+ metaclass would probably be more confusing than helpful.
+*/
+static PyObject *
+type_dir(PyObject *self, PyObject *args)
+{
+ PyObject *result = NULL;
+ PyObject *dict = PyDict_New();
+
+ if (dict != NULL && merge_class_dict(dict, self) == 0)
+ result = PyDict_Keys(dict);
+
+ Py_XDECREF(dict);
+ return result;
+}
+
static PyMethodDef type_methods[] = {
{"mro", (PyCFunction)mro_external, METH_NOARGS,
PyDoc_STR("mro() -> list\nreturn a type's method resolution order")},
@@ -2582,9 +2658,11 @@
PyDoc_STR("__prepare__() -> dict\n"
"used to create the namespace for the class statement")},
{"__instancecheck__", type___instancecheck__, METH_O,
- PyDoc_STR("__instancecheck__() -> check if an object is an instance")},
+ PyDoc_STR("__instancecheck__() -> bool\ncheck if an object is an instance")},
{"__subclasscheck__", type___subclasscheck__, METH_O,
- PyDoc_STR("__subclasscheck__() -> check if a class is a subclass")},
+ PyDoc_STR("__subclasscheck__() -> bool\ncheck if a class is a subclass")},
+ {"__dir__", type_dir, METH_NOARGS,
+ PyDoc_STR("__dir__() -> list\nspecialized __dir__ implementation for types")},
{0}
};
@@ -3438,6 +3516,53 @@
return PyLong_FromSsize_t(res);
}
+/* __dir__ for generic objects: returns __dict__, __class__,
+ and recursively up the __class__.__bases__ chain.
+*/
+static PyObject *
+object_dir(PyObject *self, PyObject *args)
+{
+ PyObject *result = NULL;
+ PyObject *dict = NULL;
+ PyObject *itsclass = NULL;
+
+ /* Get __dict__ (which may or may not be a real dict...) */
+ dict = PyObject_GetAttrString(self, "__dict__");
+ if (dict == NULL) {
+ PyErr_Clear();
+ dict = PyDict_New();
+ }
+ else if (!PyDict_Check(dict)) {
+ Py_DECREF(dict);
+ dict = PyDict_New();
+ }
+ else {
+ /* Copy __dict__ to avoid mutating it. */
+ PyObject *temp = PyDict_Copy(dict);
+ Py_DECREF(dict);
+ dict = temp;
+ }
+
+ if (dict == NULL)
+ goto error;
+
+ /* Merge in attrs reachable from its class. */
+ itsclass = PyObject_GetAttrString(self, "__class__");
+ if (itsclass == NULL)
+ /* XXX(tomer): Perhaps fall back to obj->ob_type if no
+ __class__ exists? */
+ PyErr_Clear();
+ else if (merge_class_dict(dict, itsclass) != 0)
+ goto error;
+
+ result = PyDict_Keys(dict);
+ /* fall through */
+error:
+ Py_XDECREF(itsclass);
+ Py_XDECREF(dict);
+ return result;
+}
+
static PyMethodDef object_methods[] = {
{"__reduce_ex__", object_reduce_ex, METH_VARARGS,
PyDoc_STR("helper for pickle")},
@@ -3448,7 +3573,9 @@
{"__format__", object_format, METH_VARARGS,
PyDoc_STR("default object formatter")},
{"__sizeof__", object_sizeof, METH_NOARGS,
- PyDoc_STR("__sizeof__() -> size of object in memory, in bytes")},
+ PyDoc_STR("__sizeof__() -> int\nsize of object in memory, in bytes")},
+ {"__dir__", object_dir, METH_NOARGS,
+ PyDoc_STR("__dir__() -> list\ndefault dir() implementation")},
{0}
};
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 4361908..309159c 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -6474,7 +6474,7 @@
}
}
/* 0-terminate the output string */
- *output++ = '\0';
+ *output = '\0';
Py_XDECREF(exc);
Py_XDECREF(errorHandler);
return 0;
diff --git a/Python/compile.c b/Python/compile.c
index 53f5a12..d195967 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -3747,11 +3747,11 @@
a->a_lnotab_off += 2;
if (d_bytecode) {
*lnotab++ = d_bytecode;
- *lnotab++ = d_lineno;
+ *lnotab = d_lineno;
}
else { /* First line of a block; def stmt, etc. */
*lnotab++ = 0;
- *lnotab++ = d_lineno;
+ *lnotab = d_lineno;
}
a->a_lineno = i->i_lineno;
a->a_lineno_off = a->a_offset;
@@ -3796,7 +3796,7 @@
if (i->i_hasarg) {
assert(size == 3 || size == 6);
*code++ = arg & 0xff;
- *code++ = arg >> 8;
+ *code = arg >> 8;
}
return 1;
}
diff --git a/Python/import.c b/Python/import.c
index 5360d57..1f28d22 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -1733,7 +1733,6 @@
Py_UNICODE buf[MAXPATHLEN+1];
Py_ssize_t buflen = MAXPATHLEN+1;
PyObject *path_unicode, *filename;
- const Py_UNICODE *base;
Py_ssize_t len;
struct stat statbuf;
static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
@@ -1751,7 +1750,6 @@
else
return 0;
- base = PyUnicode_AS_UNICODE(path_unicode);
len = PyUnicode_GET_SIZE(path_unicode);
if (len + 2 + PyUnicode_GET_SIZE(name) + MAXSUFFIXSIZE >= buflen) {
Py_DECREF(path_unicode);
@@ -2275,12 +2273,10 @@
static int
find_init_module(PyObject *directory)
{
- size_t len;
struct stat statbuf;
PyObject *filename;
int match;
- len = PyUnicode_GET_SIZE(directory);
filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP);
if (filename == NULL)
return -1;
@@ -2818,7 +2814,7 @@
}
PyObject *
-PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals,
+PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals,
PyObject *fromlist, int level)
{
PyObject *nameobj, *mod;
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index b55dc5b..232d7be 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1593,7 +1593,7 @@
moduleName = PyObject_GetAttrString(type, "__module__");
if (moduleName == NULL || !PyUnicode_Check(moduleName))
{
- Py_DECREF(moduleName);
+ Py_XDECREF(moduleName);
err = PyFile_WriteString("<unknown>", f);
}
else {
diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py
index 53e652d..5db62cd 100644
--- a/Tools/msi/msi.py
+++ b/Tools/msi/msi.py
@@ -1031,6 +1031,8 @@
lib.glob("*.0")
if dir=='tests' and parent.physical=='distutils':
lib.add_file("Setup.sample")
+ if dir=='cjkencodings':
+ lib.glob("*.txt")
if dir=='decimaltestdata':
lib.glob("*.decTest")
if dir=='xmltestdata':