summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgtags1
-rw-r--r--Doc/c-api/intro.rst4
-rw-r--r--Doc/distutils/install.rst15
-rw-r--r--Doc/distutils/introduction.rst10
-rw-r--r--Doc/documenting/markup.rst11
-rw-r--r--Doc/library/builtins.rst4
-rw-r--r--Doc/library/collections.rst2
-rw-r--r--Doc/library/concurrent.futures.rst19
-rw-r--r--Doc/library/constants.rst2
-rw-r--r--Doc/library/logging.handlers.rst15
-rw-r--r--Doc/library/logging.rst23
-rw-r--r--Doc/library/mmap.rst12
-rw-r--r--Doc/library/multiprocessing.rst14
-rw-r--r--Doc/library/os.rst17
-rw-r--r--Doc/library/packaging.compiler.rst6
-rw-r--r--Doc/license.rst4
-rw-r--r--Doc/packaging/setupcfg.rst89
-rw-r--r--Doc/reference/datamodel.rst3
-rw-r--r--Doc/tutorial/interpreter.rst2
-rw-r--r--Doc/using/cmdline.rst2
-rw-r--r--Lib/argparse.py15
-rw-r--r--Lib/concurrent/futures/process.py105
-rw-r--r--Lib/idlelib/config-main.def4
-rw-r--r--Lib/importlib/test/__main__.py7
-rw-r--r--Lib/inspect.py8
-rw-r--r--Lib/logging/__init__.py7
-rw-r--r--Lib/logging/handlers.py6
-rw-r--r--Lib/multiprocessing/connection.py149
-rw-r--r--Lib/multiprocessing/forking.py35
-rw-r--r--Lib/multiprocessing/process.py12
-rw-r--r--Lib/multiprocessing/queues.py6
-rw-r--r--Lib/multiprocessing/util.py20
-rw-r--r--Lib/netrc.py12
-rw-r--r--Lib/ntpath.py11
-rw-r--r--Lib/packaging/command/sdist.py21
-rw-r--r--Lib/packaging/config.py69
-rw-r--r--Lib/packaging/create.py8
-rw-r--r--Lib/packaging/database.py6
-rw-r--r--Lib/packaging/depgraph.py29
-rw-r--r--Lib/packaging/dist.py8
-rw-r--r--Lib/packaging/install.py19
-rw-r--r--Lib/packaging/pypi/dist.py6
-rw-r--r--Lib/packaging/pypi/simple.py7
-rw-r--r--Lib/packaging/run.py21
-rw-r--r--Lib/packaging/tests/test_command_bdist_dumb.py1
-rw-r--r--Lib/packaging/tests/test_command_build_py.py4
-rw-r--r--Lib/packaging/tests/test_command_install_dist.py2
-rw-r--r--Lib/packaging/tests/test_command_install_distinfo.py2
-rw-r--r--Lib/packaging/tests/test_command_install_lib.py2
-rw-r--r--Lib/packaging/tests/test_command_sdist.py25
-rw-r--r--Lib/packaging/tests/test_command_upload.py2
-rw-r--r--Lib/packaging/tests/test_config.py42
-rw-r--r--Lib/packaging/tests/test_create.py137
-rw-r--r--Lib/packaging/tests/test_dist.py2
-rw-r--r--Lib/packaging/tests/test_install.py14
-rw-r--r--Lib/packaging/tests/test_util.py48
-rw-r--r--Lib/packaging/util.py57
-rwxr-xr-xLib/smtplib.py28
-rw-r--r--Lib/sysconfig.cfg14
-rw-r--r--Lib/test/support.py3
-rw-r--r--Lib/test/test_argparse.py61
-rw-r--r--Lib/test/test_builtin.py10
-rw-r--r--Lib/test/test_concurrent_futures.py20
-rw-r--r--Lib/test/test_inspect.py17
-rw-r--r--Lib/test/test_logging.py8
-rw-r--r--Lib/test/test_mmap.py29
-rw-r--r--Lib/test/test_multiprocessing.py37
-rw-r--r--Lib/test/test_netrc.py131
-rw-r--r--Lib/test/test_ossaudiodev.py16
-rw-r--r--Lib/test/test_platform.py35
-rw-r--r--Lib/test/test_posix.py19
-rw-r--r--Lib/test/test_signal.py81
-rw-r--r--Lib/test/test_smtplib.py15
-rw-r--r--Lib/test/test_subprocess.py5
-rw-r--r--Lib/test/test_zipfile.py18
-rw-r--r--Lib/zipfile.py18
-rw-r--r--Makefile.pre.in2
-rw-r--r--Misc/ACKS4
-rw-r--r--Misc/NEWS55
-rw-r--r--Modules/_multiprocessing/win32_functions.c390
-rw-r--r--Modules/arraymodule.c2
-rw-r--r--Modules/mmapmodule.c32
-rw-r--r--Modules/nismodule.c2
-rw-r--r--Modules/ossaudiodev.c91
-rw-r--r--Modules/posixmodule.c124
-rw-r--r--Modules/signalmodule.c2
-rw-r--r--Objects/object.c50
-rw-r--r--Python/dynload_win.c25
-rwxr-xr-xconfigure520
-rw-r--r--configure.in4
-rw-r--r--pyconfig.h.in3
-rw-r--r--setup.py16
92 files changed, 2218 insertions, 853 deletions
diff --git a/.hgtags b/.hgtags
index 407bbcb..c12bf22 100644
--- a/.hgtags
+++ b/.hgtags
@@ -76,6 +76,7 @@ a69a031ac1402dede8b1ef80096436bca6d371f3 v3.1
d18e9d71f369d8211f6ac87252c6d3211f9bd09f v3.1.3rc1
a4f75773c0060cee38b0bb651a7aba6f56b0e996 v3.1.3
32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1
+c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4
b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1
56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2
da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3
diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst
index 83b98f9..843707d 100644
--- a/Doc/c-api/intro.rst
+++ b/Doc/c-api/intro.rst
@@ -588,8 +588,8 @@ frequently-used builds will be described in the remainder of this section.
Compiling the interpreter with the :c:macro:`Py_DEBUG` macro defined produces
what is generally meant by "a debug build" of Python. :c:macro:`Py_DEBUG` is
-enabled in the Unix build by adding :option:`--with-pydebug` to the
-:file:`configure` command. It is also implied by the presence of the
+enabled in the Unix build by adding ``--with-pydebug`` to the
+:file:`./configure` command. It is also implied by the presence of the
not-Python-specific :c:macro:`_DEBUG` macro. When :c:macro:`Py_DEBUG` is enabled
in the Unix build, compiler optimization is disabled.
diff --git a/Doc/distutils/install.rst b/Doc/distutils/install.rst
index 31c1d7f..f8d6305 100644
--- a/Doc/distutils/install.rst
+++ b/Doc/distutils/install.rst
@@ -96,10 +96,16 @@ in the name of the downloaded archive, e.g. :file:`foo-1.0.tar.gz` or
directory: :file:`foo-1.0` or :file:`widget-0.9.7`. Additionally, the
distribution will contain a setup script :file:`setup.py`, and a file named
:file:`README.txt` or possibly just :file:`README`, which should explain that
-building and installing the module distribution is a simple matter of running ::
+building and installing the module distribution is a simple matter of running
+one command from a terminal::
python setup.py install
+For Windows, this command should be run from a command prompt windows ("DOS
+box")::
+
+ setup.py install
+
If all these things are true, then you already know how to build and install the
modules you've just downloaded: Run the command above. Unless you need to
install things in a non-standard way or customize the build process, you don't
@@ -113,14 +119,11 @@ Standard Build and Install
==========================
As described in section :ref:`inst-new-standard`, building and installing a module
-distribution using the Distutils is usually one simple command::
+distribution using the Distutils is usually one simple command to run from a
+terminal::
python setup.py install
-On Unix, you'd run this command from a shell prompt; on Windows, you have to
-open a command prompt window ("DOS box") and do it there; on Mac OS X, you open
-a :command:`Terminal` window to get a shell prompt.
-
.. _inst-platform-variations:
diff --git a/Doc/distutils/introduction.rst b/Doc/distutils/introduction.rst
index 8dc604d..57d34a4 100644
--- a/Doc/distutils/introduction.rst
+++ b/Doc/distutils/introduction.rst
@@ -79,11 +79,17 @@ Some observations:
for an example)
To create a source distribution for this module, you would create a setup
-script, :file:`setup.py`, containing the above code, and run::
+script, :file:`setup.py`, containing the above code, and run this command from a
+terminal::
python setup.py sdist
-which will create an archive file (e.g., tarball on Unix, ZIP file on Windows)
+For Windows, open a command prompt windows ("DOS box") and change the command
+to::
+
+ setup.py sdist
+
+:command:`sdist` will create an archive file (e.g., tarball on Unix, ZIP file on Windows)
containing your setup script :file:`setup.py`, and your module :file:`foo.py`.
The archive file will be named :file:`foo-1.0.tar.gz` (or :file:`.zip`), and
will unpack into a directory :file:`foo-1.0`.
diff --git a/Doc/documenting/markup.rst b/Doc/documenting/markup.rst
index 57d9eeb..c005d0c 100644
--- a/Doc/documenting/markup.rst
+++ b/Doc/documenting/markup.rst
@@ -98,11 +98,12 @@ following example shows all of the features of this directive type::
Spam or ham the foo.
-The signatures of object methods or data attributes should always include the
-type name (``.. method:: FileInput.input(...)``), even if it is obvious from the
-context which type they belong to; this is to enable consistent
-cross-references. If you describe methods belonging to an abstract protocol,
-such as "context managers", include a (pseudo-)type name too to make the
+The signatures of object methods or data attributes should not include the
+class name, but be nested in a class directive. The generated files will
+reflect this nesting, and the target identifiers (for HTML output) will use
+both the class and method name, to enable consistent cross-references. If you
+describe methods belonging to an abstract protocol such as context managers,
+use a class directive with a (pseudo-)type name too to make the
index entries more informative.
The directives are:
diff --git a/Doc/library/builtins.rst b/Doc/library/builtins.rst
index c495728..d4199d2 100644
--- a/Doc/library/builtins.rst
+++ b/Doc/library/builtins.rst
@@ -7,7 +7,9 @@
This module provides direct access to all 'built-in' identifiers of Python; for
example, ``builtins.open`` is the full name for the built-in function
-:func:`open`.
+:func:`open`. See :ref:`built-in-funcs` and :ref:`built-in-consts` for
+documentation.
+
This module is not normally accessed explicitly by most applications, but can be
useful in modules that provide objects with the same name as a built-in value,
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index 6c9b1e5..39a03dd 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -83,7 +83,7 @@ The class can be used to simulate nested scopes and is useful in templating.
creating subcontexts that can be updated without altering values in any
of the parent mappings.
- .. attribute:: parents()
+ .. method:: parents()
Returns a new :class:`ChainMap` containing all of the maps in the current
instance except the first one. This is useful for skipping the first map
diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst
index e5d13f3..3bd4531 100644
--- a/Doc/library/concurrent.futures.rst
+++ b/Doc/library/concurrent.futures.rst
@@ -169,6 +169,12 @@ to a :class:`ProcessPoolExecutor` will result in deadlock.
of at most *max_workers* processes. If *max_workers* is ``None`` or not
given, it will default to the number of processors on the machine.
+ .. versionchanged:: 3.3
+ When one of the worker processes terminates abruptly, a
+ :exc:`BrokenProcessPool` error is now raised. Previously, behaviour
+ was undefined but operations on the executor or its futures would often
+ freeze or deadlock.
+
.. _processpoolexecutor-example:
@@ -369,3 +375,16 @@ Module Functions
:pep:`3148` -- futures - execute computations asynchronously
The proposal which described this feature for inclusion in the Python
standard library.
+
+
+Exception classes
+-----------------
+
+.. exception:: BrokenProcessPool
+
+ Derived from :exc:`RuntimeError`, this exception class is raised when
+ one of the workers of a :class:`ProcessPoolExecutor` has terminated
+ in a non-clean fashion (for example, if it was killed from the outside).
+
+ .. versionadded:: 3.3
+
diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst
index 51a1c26..fa61f68 100644
--- a/Doc/library/constants.rst
+++ b/Doc/library/constants.rst
@@ -1,3 +1,5 @@
+.. _built-in-consts:
+
Built-in Constants
==================
diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst
index 9346e99..e8353ea 100644
--- a/Doc/library/logging.handlers.rst
+++ b/Doc/library/logging.handlers.rst
@@ -436,6 +436,21 @@ supports sending logging messages to a remote or local Unix syslog.
The record is formatted, and then sent to the syslog server. If exception
information is present, it is *not* sent to the server.
+ .. versionchanged:: 3.2.1
+ (See: :issue:`12168`.) In earlier versions, the message sent to the
+ syslog daemons was always terminated with a NUL byte, because early
+ versions of these daemons expected a NUL terminated message - even
+ though it's not in the relevant specification (RF 5424). More recent
+ versions of these daemons don't expect the NUL byte but strip it off
+ if it's there, and even more recent daemons (which adhere more closely
+ to RFC 5424) pass the NUL byte on as part of the message.
+
+ To enable easier handling of syslog messages in the face of all these
+ differing daemon behaviours, the appending of the NUL byte has been
+ made configurable, through the use of a class-level attribute,
+ ``append_nul``. This defaults to ``True`` (preserving the existing
+ behaviour) but can be set to ``False`` on a ``SysLogHandler`` instance
+ in order for that instance to *not* append the NUL terminator.
.. method:: encodePriority(facility, priority)
diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
index eb2c718..5070487 100644
--- a/Doc/library/logging.rst
+++ b/Doc/library/logging.rst
@@ -453,6 +453,26 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on
record. Otherwise, the ISO8601 format is used. The resulting string is
returned.
+ This function uses a user-configurable function to convert the creation
+ time to a tuple. By default, :func:`time.localtime` is used; to change
+ this for a particular formatter instance, set the ``converter`` attribute
+ to a function with the same signature as :func:`time.localtime` or
+ :func:`time.gmtime`. To change it for all formatters, for example if you
+ want all logging times to be shown in GMT, set the ``converter``
+ attribute in the ``Formatter`` class.
+
+ .. versionchanged:: 3.3
+ Previously, the default ISO 8601 format was hard-coded as in this
+ example: ``2010-09-06 22:38:15,292`` where the part before the comma is
+ handled by a strptime format string (``'%Y-%m-%d %H:%M:%S'``), and the
+ part after the comma is a millisecond value. Because strptime does not
+ have a format placeholder for milliseconds, the millisecond value is
+ appended using another format string, ``'%s,%03d'`` – and both of these
+ format strings have been hardcoded into this method. With the change,
+ these strings are defined as class-level attributes which can be
+ overridden at the instance level when desired. The names of the
+ attributes are ``default_time_format`` (for the strptime format string)
+ and ``default_msec_format`` (for appending the millisecond value).
.. method:: formatException(exc_info)
@@ -544,6 +564,9 @@ wire).
:param name: The name of the logger used to log the event represented by
this LogRecord.
:param level: The numeric level of the logging event (one of DEBUG, INFO etc.)
+ Note that this is converted to *two* attributes of the LogRecord:
+ ``levelno`` for the numeric value and ``levelname`` for the
+ corresponding level name.
:param pathname: The full pathname of the source file where the logging call
was made.
:param lineno: The line number in the source file where the logging call was
diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst
index 7a901c9..7708028 100644
--- a/Doc/library/mmap.rst
+++ b/Doc/library/mmap.rst
@@ -190,12 +190,16 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
move will raise a :exc:`TypeError` exception.
- .. method:: read(num)
+ .. method:: read([n])
- Return a :class:`bytes` containing up to *num* bytes starting from the
- current file position; the file position is updated to point after the
- bytes that were returned.
+ Return a :class:`bytes` containing up to *n* bytes starting from the
+ current file position. If the argument is omitted, *None* or negative,
+ return all bytes from the current file position to the end of the
+ mapping. The file position is updated to point after the bytes that were
+ returned.
+ .. versionchanged:: 3.3
+ Argument can be omitted or *None*.
.. method:: read_byte()
diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst
index e1f4382..0e220d6 100644
--- a/Doc/library/multiprocessing.rst
+++ b/Doc/library/multiprocessing.rst
@@ -411,6 +411,20 @@ The :mod:`multiprocessing` package mostly replicates the API of the
See :ref:`multiprocessing-auth-keys`.
+ .. attribute:: sentinel
+
+ A numeric handle of a system object which will become "ready" when
+ the process ends.
+
+ On Windows, this is an OS handle usable with the ``WaitForSingleObject``
+ and ``WaitForMultipleObjects`` family of API calls. On Unix, this is
+ a file descriptor usable with primitives from the :mod:`select` module.
+
+ You can use this value if you want to wait on several events at once.
+ Otherwise calling :meth:`join()` is simpler.
+
+ .. versionadded:: 3.3
+
.. method:: terminate()
Terminate the process. On Unix this is done using the ``SIGTERM`` signal;
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index c62a00d..0a097d4 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -219,6 +219,17 @@ process and user.
Availability: Unix.
+.. function:: getgrouplist(user, group)
+
+ Return list of group ids that *user* belongs to. If *group* is not in the
+ list, it is included; typically, *group* is specified as the group ID
+ field from the password record for *user*.
+
+ Availability: Unix.
+
+ .. versionadded:: 3.3
+
+
.. function:: getgroups()
Return list of supplemental group ids associated with the current process.
@@ -1019,11 +1030,11 @@ as internal buffering of data.
Availability: Unix, Windows.
-.. function:: pipe2(flags=0)
+.. function:: pipe2(flags)
Create a pipe with *flags* set atomically.
- *flags* is optional and can be constructed by ORing together zero or more of
- these values: :data:`O_NONBLOCK`, :data:`O_CLOEXEC`.
+ *flags* can be constructed by ORing together one or more of these values:
+ :data:`O_NONBLOCK`, :data:`O_CLOEXEC`.
Return a pair of file descriptors ``(r, w)`` usable for reading and writing,
respectively.
diff --git a/Doc/library/packaging.compiler.rst b/Doc/library/packaging.compiler.rst
index dac6263..cf88685 100644
--- a/Doc/library/packaging.compiler.rst
+++ b/Doc/library/packaging.compiler.rst
@@ -569,10 +569,10 @@ extension modules.
.. class:: Extension
The Extension class describes a single C or C++ extension module. It accepts
- the following keyword arguments in its constructor
+ the following keyword arguments in its constructor:
+------------------------+--------------------------------+---------------------------+
- | argument name | value | type |
+ | argument name | value | type [#]_ |
+========================+================================+===========================+
| *name* | the full name of the | string |
| | extension, including any | |
@@ -670,3 +670,5 @@ extension modules.
| | from the source extensions if | |
| | not provided. | |
+------------------------+--------------------------------+---------------------------+
+
+.. [#] For values documented as lists, the given type is the type of each element.
diff --git a/Doc/license.rst b/Doc/license.rst
index 6c9ecf5..615b18c 100644
--- a/Doc/license.rst
+++ b/Doc/license.rst
@@ -847,7 +847,7 @@ expat
-----
The :mod:`pyexpat` extension is built using an included copy of the expat
-sources unless the build is configured :option:`--with-system-expat`::
+sources unless the build is configured ``--with-system-expat``::
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
and Clark Cooper
@@ -876,7 +876,7 @@ libffi
------
The :mod:`_ctypes` extension is built using an included copy of the libffi
-sources unless the build is configured :option:`--with-system-libffi`::
+sources unless the build is configured ``--with-system-libffi``::
Copyright (c) 1996-2008 Red Hat, Inc and others.
diff --git a/Doc/packaging/setupcfg.rst b/Doc/packaging/setupcfg.rst
index 92ddb8b..2b01ffb 100644
--- a/Doc/packaging/setupcfg.rst
+++ b/Doc/packaging/setupcfg.rst
@@ -141,13 +141,16 @@ files
Modules, scripts, data, documentation and other files to include in the
distribution.
+extension sections
+ Options used to build extension modules.
+
command sections
Options given for specific commands, identical to those that can be given
on the command line.
Global options
-==============
+--------------
Contains global options for Packaging. This section is shared with Distutils.
@@ -173,19 +176,23 @@ compilers
compilers =
hotcompiler.SmartCCompiler
-setup_hook
- defines a callable that will be called right after the
- :file:`setup.cfg` file is read. The callable receives the configuration
- in form of a mapping and can make some changes to it. *optional*
+setup_hooks
+ Defines a list of callables to be called right after the :file:`setup.cfg`
+ file is read, before any other processing. The callables are executed in the
+ order they're found in the file; if one of them cannot be found, tools should
+ not stop, but for example produce a warning and continue with the next line.
+ Each callable receives the configuration as a dictionary (keys are
+ :file:`setup.cfg` sections, values are dictionaries of fields) and can make
+ any changes to it. *optional*, *multi*
Example::
[global]
- setup_hook = package.setup.customize_dist
+ setup_hooks = package.setup.customize_dist
Metadata
-========
+--------
The metadata section contains the metadata for the project as described in
:PEP:`345`. Field names are case-insensitive.
@@ -265,9 +272,9 @@ obsoletes-dist
Same format than *requires-dist*. *optional*, *multi*, *environ*
requires-python
- Specifies the Python version the distribution requires.
- The value is a version number, as described in PEP 345.
- *optional*, *multi*, *environ*
+ Specifies the Python version the distribution requires. The value is a
+ comma-separated list of version predicates, as described in PEP 345.
+ *optional*, *environ*
requires-externals
a dependency in the system. This field is free-form,
@@ -282,6 +289,7 @@ One extra field not present in PEP 345 is supported:
description-file
Path to a text file that will be used to fill the ``description`` field.
+ Multiple values are accepted; they must be separated by whitespace.
``description-file`` and ``description`` are mutually exclusive. *optional*
@@ -308,7 +316,7 @@ from the fields present in the file.
Files
-=====
+-----
This section describes the files included in the project.
@@ -352,7 +360,7 @@ Example::
Resources
----------
+^^^^^^^^^
This section describes the files used by the project which must not be installed
in the same place that python modules or libraries, they are called
@@ -448,10 +456,10 @@ Where {datafir} category will be platform-dependent.
More control on source part
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""""""""
Glob syntax
-"""""""""""
+'''''''''''
When you declare source file, you can use a glob-like syntax to match multiples file, for example::
@@ -469,7 +477,7 @@ Glob tokens are:
.. TODO Add examples
Order of declaration
-""""""""""""""""""""
+''''''''''''''''''''
The order of declaration is important if one file match multiple rules. The last
rules matched by file is used, this is useful if you have this source tree::
@@ -492,7 +500,7 @@ one by one, you can declare them in this way::
doc/README = {help}
Exclude
-"""""""
+'''''''
You can exclude some files of resources declaration by giving no destination, it
can be useful if you have a non-resources file in the same directory of
@@ -513,12 +521,12 @@ Your **files** section will be::
doc/RELEASES =
More control on destination part
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""""""""""""""
.. _setupcfg-resources-base-prefix:
Defining a base prefix
-""""""""""""""""""""""
+''''''''''''''''''''''
When you define your resources, you can have more control of how the final path
is computed.
@@ -577,7 +585,7 @@ path will be::
Overwriting paths for categories
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""""""""""""""
This part is intended for system administrators or downstream OS packagers.
@@ -614,18 +622,18 @@ The platform-dependent categories are:
Defining extra categories
-^^^^^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""""""
.. TODO
Examples
-^^^^^^^^
+""""""""
These examples are incremental but work unitarily.
Resources in root dir
-"""""""""""""""""""""
+'''''''''''''''''''''
Source tree::
@@ -647,7 +655,7 @@ So babar.sh and launch.sh will be placed in {scripts} directory.
Now let's move all the scripts into a scripts directory.
Resources in sub-directory
-""""""""""""""""""""""""""
+''''''''''''''''''''''''''
Source tree::
@@ -673,7 +681,7 @@ scripts into {scripts} instead of {scripts}/scripts.
Now let's add some docs.
Resources in multiple sub-directories
-"""""""""""""""""""""""""""""""""""""
+'''''''''''''''''''''''''''''''''''''
Source tree::
@@ -706,7 +714,7 @@ file is used.
Now let's add some scripts for windows users.
Complete example
-""""""""""""""""
+''''''''''''''''
Source tree::
@@ -736,8 +744,37 @@ We use brace expansion syntax to place all the shell and batch scripts into
{scripts} category.
+Extension sections
+------------------
+
+If a project includes extension modules written in C or C++, each one of them
+needs to have its options defined in a dedicated section. Here's an example::
+
+ [files]
+ packages = coconut
+
+ [extension=_fastcoconut]
+ name = coconut._fastcoconut
+ language = cxx
+ sources = cxx_src/cononut_utils.cxx
+ cxx_src/python_module.cxx
+ include_dirs = /usr/include/gecode
+ /usr/include/blitz
+ extra_compile_args =
+ -fPIC -O2
+ -DGECODE_VERSION=$(./gecode_version) -- sys.platform != 'win32'
+ /DGECODE_VERSION='win32' -- sys.platform == 'win32'
+
+The section name must start with ``extension=``; the righ-hand part is currently
+discarded. Valid fields and their values are listed in the documentation of the
+:class:`packaging.compiler.extension.Extension` class; values documented as
+Python lists translate to multi-line values in the configuration file. In
+addition, multi-line values accept environment markers on each line, after a
+``--``.
+
+
Command sections
-================
+----------------
To pass options to commands without having to type them on the command line
for each invocation, you can write them in the :file:`setup.cfg` file, in a
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index 129f987..e628a02 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -1343,7 +1343,8 @@ access (use of, assignment to, or deletion of ``x.name``) for class instances.
.. method:: object.__dir__(self)
- Called when :func:`dir` is called on the object. A list must be returned.
+ Called when :func:`dir` is called on the object. A sequence must be
+ returned. :func:`dir` converts the returned sequence to a list and sorts it.
.. _descriptors:
diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst
index eeddf76..4b83170 100644
--- a/Doc/tutorial/interpreter.rst
+++ b/Doc/tutorial/interpreter.rst
@@ -169,6 +169,8 @@ also be ``.pyw``, in that case, the console window that normally appears is
suppressed.
+.. _tut-source-encoding:
+
Source Code Encoding
--------------------
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
index 72b77cd..29c5772 100644
--- a/Doc/using/cmdline.rst
+++ b/Doc/using/cmdline.rst
@@ -511,7 +511,7 @@ Debug-mode variables
~~~~~~~~~~~~~~~~~~~~
Setting these variables only has an effect in a debug build of Python, that is,
-if Python was configured with the :option:`--with-pydebug` build option.
+if Python was configured with the ``--with-pydebug`` build option.
.. envvar:: PYTHONTHREADDEBUG
diff --git a/Lib/argparse.py b/Lib/argparse.py
index 0658472..f0cfe27 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1969,17 +1969,12 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
# if we didn't consume all the argument strings, there were extras
extras.extend(arg_strings[stop_index:])
- # if we didn't use all the Positional objects, there were too few
- # arg strings supplied.
- if positionals:
- self.error(_('too few arguments'))
-
# make sure all required actions were present
- for action in self._actions:
- if action.required:
- if action not in seen_actions:
- name = _get_action_name(action)
- self.error(_('argument %s is required') % name)
+ required_actions = [_get_action_name(action) for action in self._actions
+ if action.required and action not in seen_actions]
+ if required_actions:
+ self.error(_('the following arguments are required: %s') %
+ ', '.join(required_actions))
# make sure all required groups had one option present
for group in self._mutually_exclusive_groups:
diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py
index f0bf6d5..c2331e7 100644
--- a/Lib/concurrent/futures/process.py
+++ b/Lib/concurrent/futures/process.py
@@ -46,10 +46,11 @@ Process #1..n:
__author__ = 'Brian Quinlan (brian@sweetapp.com)'
import atexit
+import os
from concurrent.futures import _base
import queue
import multiprocessing
-from multiprocessing.queues import SimpleQueue
+from multiprocessing.queues import SimpleQueue, SentinelReady
import threading
import weakref
@@ -122,7 +123,7 @@ def _process_worker(call_queue, result_queue):
call_item = call_queue.get(block=True)
if call_item is None:
# Wake up queue management thread
- result_queue.put(None)
+ result_queue.put(os.getpid())
return
try:
r = call_item.fn(*call_item.args, **call_item.kwargs)
@@ -194,29 +195,63 @@ def _queue_management_worker(executor_reference,
result_queue: A multiprocessing.Queue of _ResultItems generated by the
process workers.
"""
- nb_shutdown_processes = 0
- def shutdown_one_process():
- """Tell a worker to terminate, which will in turn wake us again"""
- nonlocal nb_shutdown_processes
- call_queue.put(None)
- nb_shutdown_processes += 1
+
+ def shutdown_worker():
+ # This is an upper bound
+ nb_children_alive = sum(p.is_alive() for p in processes.values())
+ for i in range(0, nb_children_alive):
+ call_queue.put(None)
+ # If .join() is not called on the created processes then
+ # some multiprocessing.Queue methods may deadlock on Mac OS
+ # X.
+ for p in processes.values():
+ p.join()
+
while True:
_add_call_item_to_queue(pending_work_items,
work_ids_queue,
call_queue)
- result_item = result_queue.get()
- if result_item is not None:
- work_item = pending_work_items[result_item.work_id]
- del pending_work_items[result_item.work_id]
-
- if result_item.exception:
- work_item.future.set_exception(result_item.exception)
- else:
- work_item.future.set_result(result_item.result)
- continue
- # If we come here, we either got a timeout or were explicitly woken up.
- # In either case, check whether we should start shutting down.
+ sentinels = [p.sentinel for p in processes.values()]
+ assert sentinels
+ try:
+ result_item = result_queue.get(sentinels=sentinels)
+ except SentinelReady as e:
+ # Mark the process pool broken so that submits fail right now.
+ executor = executor_reference()
+ if executor is not None:
+ executor._broken = True
+ executor._shutdown_thread = True
+ del executor
+ # All futures in flight must be marked failed
+ for work_id, work_item in pending_work_items.items():
+ work_item.future.set_exception(
+ BrokenProcessPool(
+ "A process in the process pool was "
+ "terminated abruptly while the future was "
+ "running or pending."
+ ))
+ pending_work_items.clear()
+ # Terminate remaining workers forcibly: the queues or their
+ # locks may be in a dirty state and block forever.
+ for p in processes.values():
+ p.terminate()
+ for p in processes.values():
+ p.join()
+ return
+ if isinstance(result_item, int):
+ # Clean shutdown of a worker using its PID
+ # (avoids marking the executor broken)
+ del processes[result_item]
+ elif result_item is not None:
+ work_item = pending_work_items.pop(result_item.work_id, None)
+ # work_item can be None if another process terminated (see above)
+ if work_item is not None:
+ if result_item.exception:
+ work_item.future.set_exception(result_item.exception)
+ else:
+ work_item.future.set_result(result_item.result)
+ # Check whether we should start shutting down.
executor = executor_reference()
# No more work items can be added if:
# - The interpreter is shutting down OR
@@ -226,17 +261,11 @@ def _queue_management_worker(executor_reference,
# Since no new work items can be added, it is safe to shutdown
# this thread if there are no pending work items.
if not pending_work_items:
- while nb_shutdown_processes < len(processes):
- shutdown_one_process()
- # If .join() is not called on the created processes then
- # some multiprocessing.Queue methods may deadlock on Mac OS
- # X.
- for p in processes:
- p.join()
+ shutdown_worker()
return
else:
# Start shutting down by telling a process it can exit.
- shutdown_one_process()
+ call_queue.put(None)
del executor
_system_limits_checked = False
@@ -264,6 +293,14 @@ def _check_system_limits():
_system_limited = "system provides too few semaphores (%d available, 256 necessary)" % nsems_max
raise NotImplementedError(_system_limited)
+
+class BrokenProcessPool(RuntimeError):
+ """
+ Raised when a process in a ProcessPoolExecutor terminated abruptly
+ while a future was in the running state.
+ """
+
+
class ProcessPoolExecutor(_base.Executor):
def __init__(self, max_workers=None):
"""Initializes a new ProcessPoolExecutor instance.
@@ -288,11 +325,13 @@ class ProcessPoolExecutor(_base.Executor):
self._result_queue = SimpleQueue()
self._work_ids = queue.Queue()
self._queue_management_thread = None
- self._processes = set()
+ # Map of pids to processes
+ self._processes = {}
# Shutdown is a two-step process.
self._shutdown_thread = False
self._shutdown_lock = threading.Lock()
+ self._broken = False
self._queue_count = 0
self._pending_work_items = {}
@@ -302,6 +341,8 @@ class ProcessPoolExecutor(_base.Executor):
def weakref_cb(_, q=self._result_queue):
q.put(None)
if self._queue_management_thread is None:
+ # Start the processes so that their sentinels are known.
+ self._adjust_process_count()
self._queue_management_thread = threading.Thread(
target=_queue_management_worker,
args=(weakref.ref(self, weakref_cb),
@@ -321,10 +362,13 @@ class ProcessPoolExecutor(_base.Executor):
args=(self._call_queue,
self._result_queue))
p.start()
- self._processes.add(p)
+ self._processes[p.pid] = p
def submit(self, fn, *args, **kwargs):
with self._shutdown_lock:
+ if self._broken:
+ raise BrokenProcessPool('A child process terminated '
+ 'abruptly, the process pool is not usable anymore')
if self._shutdown_thread:
raise RuntimeError('cannot schedule new futures after shutdown')
@@ -338,7 +382,6 @@ class ProcessPoolExecutor(_base.Executor):
self._result_queue.put(None)
self._start_queue_management_thread()
- self._adjust_process_count()
return f
submit.__doc__ = _base.Executor.submit.__doc__
diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def
index 5ddd098..9546e2b 100644
--- a/Lib/idlelib/config-main.def
+++ b/Lib/idlelib/config-main.def
@@ -46,8 +46,8 @@
[General]
editor-on-startup= 0
autosave= 0
-print-command-posix=lpr %s
-print-command-win=start /min notepad /p %s
+print-command-posix=lpr %%s
+print-command-win=start /min notepad /p %%s
delete-exitfunc= 1
[EditorWindow]
diff --git a/Lib/importlib/test/__main__.py b/Lib/importlib/test/__main__.py
index decc53d..a1990b1 100644
--- a/Lib/importlib/test/__main__.py
+++ b/Lib/importlib/test/__main__.py
@@ -4,7 +4,6 @@ Specifying the ``--builtin`` flag will run tests, where applicable, with
builtins.__import__ instead of importlib.__import__.
"""
-import importlib
from importlib.test.import_ import util
import os.path
from test.support import run_unittest
@@ -13,11 +12,7 @@ import unittest
def test_main():
- if '__pycache__' in __file__:
- parts = __file__.split(os.path.sep)
- start_dir = sep.join(parts[:-2])
- else:
- start_dir = os.path.dirname(__file__)
+ start_dir = os.path.dirname(__file__)
top_dir = os.path.dirname(os.path.dirname(start_dir))
test_loader = unittest.TestLoader()
if '--builtin' in sys.argv:
diff --git a/Lib/inspect.py b/Lib/inspect.py
index f200a82..aa4c30f 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -518,9 +518,13 @@ def findsource(object):
or code object. The source code is returned as a list of all the lines
in the file and the line number indexes a line in that list. An IOError
is raised if the source code cannot be retrieved."""
- file = getsourcefile(object)
- if not file:
+
+ file = getfile(object)
+ sourcefile = getsourcefile(object)
+ if not sourcefile and file[0] + file[-1] != '<>':
raise IOError('source code not available')
+ file = sourcefile if sourcefile else file
+
module = getmodule(object, file)
if module:
lines = linecache.getlines(file, module.__dict__)
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index 1a4b241..509dae6 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -467,6 +467,9 @@ class Formatter(object):
self._fmt = self._style._fmt
self.datefmt = datefmt
+ default_time_format = '%Y-%m-%d %H:%M:%S'
+ default_msec_format = '%s,%03d'
+
def formatTime(self, record, datefmt=None):
"""
Return the creation time of the specified LogRecord as formatted text.
@@ -489,8 +492,8 @@ class Formatter(object):
if datefmt:
s = time.strftime(datefmt, ct)
else:
- t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
- s = "%s,%03d" % (t, record.msecs) # the use of % here is internal
+ t = time.strftime(self.default_time_format, ct)
+ s = self.default_msec_format % (t, record.msecs)
return s
def formatException(self, ei):
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index f17db0e..5779a7d 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -769,6 +769,8 @@ class SysLogHandler(logging.Handler):
"""
return self.priority_map.get(levelName, "warning")
+ append_nul = True # some old syslog daemons expect a NUL terminator
+
def emit(self, record):
"""
Emit a record.
@@ -776,7 +778,9 @@ class SysLogHandler(logging.Handler):
The record is formatted, and then sent to the syslog server. If
exception information is present, it is NOT sent to the server.
"""
- msg = self.format(record) + '\000'
+ msg = self.format(record)
+ if self.append_nul:
+ msg += '\000'
"""
We need to convert record level to lowercase, maybe this will
change in the future.
diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py
index 415e210..ede2908 100644
--- a/Lib/multiprocessing/connection.py
+++ b/Lib/multiprocessing/connection.py
@@ -48,14 +48,18 @@ import itertools
import _multiprocessing
from multiprocessing import current_process, AuthenticationError, BufferTooShort
-from multiprocessing.util import get_temp_dir, Finalize, sub_debug, debug
+from multiprocessing.util import (
+ get_temp_dir, Finalize, sub_debug, debug, _eintr_retry)
try:
from _multiprocessing import win32
+ from _subprocess import WAIT_OBJECT_0, WAIT_TIMEOUT, INFINITE
except ImportError:
if sys.platform == 'win32':
raise
win32 = None
+_select = _eintr_retry(select.select)
+
#
#
#
@@ -118,6 +122,15 @@ def address_type(address):
else:
raise ValueError('address type of %r unrecognized' % address)
+
+class SentinelReady(Exception):
+ """
+ Raised when a sentinel is ready when polling.
+ """
+ def __init__(self, *args):
+ Exception.__init__(self, *args)
+ self.sentinels = args[0]
+
#
# Connection classes
#
@@ -253,19 +266,17 @@ class _ConnectionBase:
(offset + size) // itemsize])
return size
- def recv(self):
+ def recv(self, sentinels=None):
"""Receive a (picklable) object"""
self._check_closed()
self._check_readable()
- buf = self._recv_bytes()
+ buf = self._recv_bytes(sentinels=sentinels)
return pickle.loads(buf.getbuffer())
def poll(self, timeout=0.0):
"""Whether there is any input available to be read"""
self._check_closed()
self._check_readable()
- if timeout < 0.0:
- timeout = None
return self._poll(timeout)
@@ -274,61 +285,88 @@ if win32:
class PipeConnection(_ConnectionBase):
"""
Connection class based on a Windows named pipe.
+ Overlapped I/O is used, so the handles must have been created
+ with FILE_FLAG_OVERLAPPED.
"""
+ _buffered = b''
def _close(self):
win32.CloseHandle(self._handle)
def _send_bytes(self, buf):
- nwritten = win32.WriteFile(self._handle, buf)
+ overlapped = win32.WriteFile(self._handle, buf, overlapped=True)
+ nwritten, complete = overlapped.GetOverlappedResult(True)
+ assert complete
assert nwritten == len(buf)
- def _recv_bytes(self, maxsize=None):
+ def _recv_bytes(self, maxsize=None, sentinels=()):
+ if sentinels:
+ self._poll(-1.0, sentinels)
buf = io.BytesIO()
- bufsize = 512
- if maxsize is not None:
- bufsize = min(bufsize, maxsize)
- try:
- firstchunk, complete = win32.ReadFile(self._handle, bufsize)
- except IOError as e:
- if e.errno == win32.ERROR_BROKEN_PIPE:
- raise EOFError
- raise
- lenfirstchunk = len(firstchunk)
- buf.write(firstchunk)
- if complete:
- return buf
+ firstchunk = self._buffered
+ if firstchunk:
+ lenfirstchunk = len(firstchunk)
+ buf.write(firstchunk)
+ self._buffered = b''
+ else:
+ # A reasonable size for the first chunk transfer
+ bufsize = 128
+ if maxsize is not None and maxsize < bufsize:
+ bufsize = maxsize
+ try:
+ overlapped = win32.ReadFile(self._handle, bufsize, overlapped=True)
+ lenfirstchunk, complete = overlapped.GetOverlappedResult(True)
+ firstchunk = overlapped.getbuffer()
+ assert lenfirstchunk == len(firstchunk)
+ except IOError as e:
+ if e.errno == win32.ERROR_BROKEN_PIPE:
+ raise EOFError
+ raise
+ buf.write(firstchunk)
+ if complete:
+ return buf
navail, nleft = win32.PeekNamedPipe(self._handle)
if maxsize is not None and lenfirstchunk + nleft > maxsize:
return None
- lastchunk, complete = win32.ReadFile(self._handle, nleft)
- assert complete
- buf.write(lastchunk)
+ if nleft > 0:
+ overlapped = win32.ReadFile(self._handle, nleft, overlapped=True)
+ res, complete = overlapped.GetOverlappedResult(True)
+ assert res == nleft
+ assert complete
+ buf.write(overlapped.getbuffer())
return buf
- def _poll(self, timeout):
+ def _poll(self, timeout, sentinels=()):
+ # Fast non-blocking path
navail, nleft = win32.PeekNamedPipe(self._handle)
if navail > 0:
return True
elif timeout == 0.0:
return False
- # Setup a polling loop (translated straight from old
- # pipe_connection.c)
+ # Blocking: use overlapped I/O
if timeout < 0.0:
- deadline = None
+ timeout = INFINITE
else:
- deadline = time.time() + timeout
- delay = 0.001
- max_delay = 0.02
- while True:
- time.sleep(delay)
- navail, nleft = win32.PeekNamedPipe(self._handle)
- if navail > 0:
- return True
- if deadline and time.time() > deadline:
- return False
- if delay < max_delay:
- delay += 0.001
+ timeout = int(timeout * 1000 + 0.5)
+ overlapped = win32.ReadFile(self._handle, 1, overlapped=True)
+ try:
+ handles = [overlapped.event]
+ handles += sentinels
+ res = win32.WaitForMultipleObjects(handles, False, timeout)
+ finally:
+ # Always cancel overlapped I/O in the same thread
+ # (because CancelIoEx() appears only in Vista)
+ overlapped.cancel()
+ if res == WAIT_TIMEOUT:
+ return False
+ idx = res - WAIT_OBJECT_0
+ if idx == 0:
+ # I/O was successful, store received data
+ overlapped.GetOverlappedResult(True)
+ self._buffered += overlapped.getbuffer()
+ return True
+ assert 0 < idx < len(handles)
+ raise SentinelReady([handles[idx]])
class Connection(_ConnectionBase):
@@ -357,11 +395,18 @@ class Connection(_ConnectionBase):
break
buf = buf[n:]
- def _recv(self, size, read=_read):
+ def _recv(self, size, sentinels=(), read=_read):
buf = io.BytesIO()
+ handle = self._handle
+ if sentinels:
+ handles = [handle] + sentinels
remaining = size
while remaining > 0:
- chunk = read(self._handle, remaining)
+ if sentinels:
+ r = _select(handles, [], [])[0]
+ if handle not in r:
+ raise SentinelReady(r)
+ chunk = read(handle, remaining)
n = len(chunk)
if n == 0:
if remaining == size:
@@ -381,15 +426,17 @@ class Connection(_ConnectionBase):
if n > 0:
self._send(buf)
- def _recv_bytes(self, maxsize=None):
- buf = self._recv(4)
+ def _recv_bytes(self, maxsize=None, sentinels=()):
+ buf = self._recv(4, sentinels)
size, = struct.unpack("=i", buf.getvalue())
if maxsize is not None and size > maxsize:
return None
- return self._recv(size)
+ return self._recv(size, sentinels)
def _poll(self, timeout):
- r = select.select([self._handle], [], [], timeout)[0]
+ if timeout < 0.0:
+ timeout = None
+ r = _select([self._handle], [], [], timeout)[0]
return bool(r)
@@ -495,23 +542,21 @@ else:
obsize, ibsize = 0, BUFSIZE
h1 = win32.CreateNamedPipe(
- address, openmode,
+ address, openmode | win32.FILE_FLAG_OVERLAPPED,
win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE |
win32.PIPE_WAIT,
1, obsize, ibsize, win32.NMPWAIT_WAIT_FOREVER, win32.NULL
)
h2 = win32.CreateFile(
- address, access, 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL
+ address, access, 0, win32.NULL, win32.OPEN_EXISTING,
+ win32.FILE_FLAG_OVERLAPPED, win32.NULL
)
win32.SetNamedPipeHandleState(
h2, win32.PIPE_READMODE_MESSAGE, None, None
)
- try:
- win32.ConnectNamedPipe(h1, win32.NULL)
- except WindowsError as e:
- if e.args[0] != win32.ERROR_PIPE_CONNECTED:
- raise
+ overlapped = win32.ConnectNamedPipe(h1, overlapped=True)
+ overlapped.GetOverlappedResult(True)
c1 = PipeConnection(h1, writable=duplex)
c2 = PipeConnection(h2, readable=duplex)
diff --git a/Lib/multiprocessing/forking.py b/Lib/multiprocessing/forking.py
index 3d95557..a2c61ef 100644
--- a/Lib/multiprocessing/forking.py
+++ b/Lib/multiprocessing/forking.py
@@ -35,6 +35,7 @@
import os
import sys
import signal
+import select
from multiprocessing import util, process
@@ -101,10 +102,12 @@ else:
if sys.platform != 'win32':
import time
+ import select
exit = os._exit
duplicate = os.dup
close = os.close
+ _select = util._eintr_retry(select.select)
#
# We define a Popen class similar to the one from subprocess, but
@@ -118,8 +121,12 @@ if sys.platform != 'win32':
sys.stderr.flush()
self.returncode = None
+ r, w = os.pipe()
+ self.sentinel = r
+
self.pid = os.fork()
if self.pid == 0:
+ os.close(r)
if 'random' in sys.modules:
import random
random.seed()
@@ -128,6 +135,11 @@ if sys.platform != 'win32':
sys.stderr.flush()
os._exit(code)
+ # `w` will be closed when the child exits, at which point `r`
+ # will become ready for reading (using e.g. select()).
+ os.close(w)
+ util.Finalize(self, os.close, (r,))
+
def poll(self, flag=os.WNOHANG):
if self.returncode is None:
try:
@@ -145,20 +157,14 @@ if sys.platform != 'win32':
return self.returncode
def wait(self, timeout=None):
- if timeout is None:
- return self.poll(0)
- deadline = time.time() + timeout
- delay = 0.0005
- while 1:
- res = self.poll()
- if res is not None:
- break
- remaining = deadline - time.time()
- if remaining <= 0:
- break
- delay = min(delay * 2, remaining, 0.05)
- time.sleep(delay)
- return res
+ if self.returncode is None:
+ if timeout is not None:
+ r = _select([self.sentinel], [], [], timeout)[0]
+ if not r:
+ return None
+ # This shouldn't block if select() returned successfully.
+ return self.poll(os.WNOHANG if timeout == 0.0 else 0)
+ return self.returncode
def terminate(self):
if self.returncode is None:
@@ -258,6 +264,7 @@ else:
self.pid = pid
self.returncode = None
self._handle = hp
+ self.sentinel = int(hp)
# send information to child
prep_data = get_preparation_data(process_obj._name)
diff --git a/Lib/multiprocessing/process.py b/Lib/multiprocessing/process.py
index 3fb9ff6..99ee532 100644
--- a/Lib/multiprocessing/process.py
+++ b/Lib/multiprocessing/process.py
@@ -132,6 +132,7 @@ class Process(object):
else:
from .forking import Popen
self._popen = Popen(self)
+ self._sentinel = self._popen.sentinel
_current_process._children.add(self)
def terminate(self):
@@ -218,6 +219,17 @@ class Process(object):
pid = ident
+ @property
+ def sentinel(self):
+ '''
+ Return a file descriptor (Unix) or handle (Windows) suitable for
+ waiting for process termination.
+ '''
+ try:
+ return self._sentinel
+ except AttributeError:
+ raise ValueError("process not started")
+
def __repr__(self):
if self is _current_process:
status = 'started'
diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py
index 3280a25..3324363 100644
--- a/Lib/multiprocessing/queues.py
+++ b/Lib/multiprocessing/queues.py
@@ -44,7 +44,7 @@ import weakref
from queue import Empty, Full
import _multiprocessing
-from multiprocessing import Pipe
+from multiprocessing.connection import Pipe, SentinelReady
from multiprocessing.synchronize import Lock, BoundedSemaphore, Semaphore, Condition
from multiprocessing.util import debug, info, Finalize, register_after_fork
from multiprocessing.forking import assert_spawning
@@ -372,10 +372,10 @@ class SimpleQueue(object):
def _make_methods(self):
recv = self._reader.recv
racquire, rrelease = self._rlock.acquire, self._rlock.release
- def get():
+ def get(*, sentinels=None):
racquire()
try:
- return recv()
+ return recv(sentinels)
finally:
rrelease()
self.get = get
diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py
index 30b7a85..b59ac9f 100644
--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -32,9 +32,11 @@
# SUCH DAMAGE.
#
+import functools
import itertools
import weakref
import atexit
+import select
import threading # we want threading to install it's
# cleanup function before multiprocessing does
@@ -315,3 +317,21 @@ class ForkAwareLocal(threading.local):
register_after_fork(self, lambda obj : obj.__dict__.clear())
def __reduce__(self):
return type(self), ()
+
+
+#
+# Automatic retry after EINTR
+#
+
+def _eintr_retry(func, _errors=(EnvironmentError, select.error)):
+ @functools.wraps(func)
+ def wrapped(*args, **kwargs):
+ while True:
+ try:
+ return func(*args, **kwargs)
+ except _errors as e:
+ # select.error has no `errno` attribute
+ if e.args[0] == errno.EINTR:
+ continue
+ raise
+ return wrapped
diff --git a/Lib/netrc.py b/Lib/netrc.py
index a60b8b7..c96db6f 100644
--- a/Lib/netrc.py
+++ b/Lib/netrc.py
@@ -2,7 +2,7 @@
# Module and documentation by Eric S. Raymond, 21 Dec 1998
-import os, shlex
+import io, os, shlex
__all__ = ["netrc", "NetrcParseError"]
@@ -37,12 +37,14 @@ class netrc:
lexer.commenters = lexer.commenters.replace('#', '')
while 1:
# Look for a machine, default, or macdef top-level keyword
+ saved_lineno = lexer.lineno
toplevel = tt = lexer.get_token()
if not tt:
break
elif tt[0] == '#':
- fp.readline();
- continue;
+ if lexer.lineno == saved_lineno and len(tt) == 1:
+ lexer.instream.readline()
+ continue
elif tt == 'machine':
entryname = lexer.get_token()
elif tt == 'default':
@@ -68,8 +70,8 @@ class netrc:
self.hosts[entryname] = {}
while 1:
tt = lexer.get_token()
- if (tt=='' or tt == 'machine' or
- tt == 'default' or tt =='macdef'):
+ if (tt.startswith('#') or
+ tt in {'', 'machine', 'default', 'macdef'}):
if password:
self.hosts[entryname] = (login, account, password)
lexer.push_token(tt)
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
index ec8a7ab..826be87 100644
--- a/Lib/ntpath.py
+++ b/Lib/ntpath.py
@@ -672,3 +672,14 @@ except ImportError:
def sameopenfile(f1, f2):
"""Test whether two file objects reference the same file"""
return _getfileinformation(f1) == _getfileinformation(f2)
+
+
+try:
+ # The genericpath.isdir implementation uses os.stat and checks the mode
+ # attribute to tell whether or not the path is a directory.
+ # This is overkill on Windows - just pass the path to GetFileAttributes
+ # and check the attribute from there.
+ from nt import _isdir as isdir
+except ImportError:
+ # Use genericpath.isdir as imported above.
+ pass
diff --git a/Lib/packaging/command/sdist.py b/Lib/packaging/command/sdist.py
index a19203f..09b26db 100644
--- a/Lib/packaging/command/sdist.py
+++ b/Lib/packaging/command/sdist.py
@@ -201,15 +201,20 @@ class sdist(Command):
self.filelist.write(self.manifest)
def add_defaults(self):
- """Add all the default files to self.filelist:
- - all pure Python modules mentioned in setup script
- - all files pointed by package_data (build_py)
- - all files defined in data_files.
- - all files defined as scripts.
- - all C sources listed as part of extensions or C libraries
- in the setup script (doesn't catch C headers!)
- Everything is optional.
+ """Add all default files to self.filelist.
+
+ In addition to the setup.cfg file, this will include all files returned
+ by the get_source_files of every registered command. This will find
+ Python modules and packages, data files listed in package_data_,
+ data_files and extra_files, scripts, C sources of extension modules or
+ C libraries (headers are missing).
"""
+ if os.path.exists('setup.cfg'):
+ self.filelist.append('setup.cfg')
+ else:
+ logger.warning("%s: standard 'setup.cfg' file not found",
+ self.get_command_name())
+
for cmd_name in get_command_names():
try:
cmd_obj = self.get_finalized_command(cmd_name)
diff --git a/Lib/packaging/config.py b/Lib/packaging/config.py
index 6df2bab..21bbcf8 100644
--- a/Lib/packaging/config.py
+++ b/Lib/packaging/config.py
@@ -9,7 +9,8 @@ from configparser import RawConfigParser
from packaging import logger
from packaging.errors import PackagingOptionError
from packaging.compiler.extension import Extension
-from packaging.util import check_environ, iglob, resolve_name, strtobool
+from packaging.util import (check_environ, iglob, resolve_name, strtobool,
+ split_multiline)
from packaging.compiler import set_compiler
from packaging.command import set_command
from packaging.markers import interpret
@@ -60,17 +61,15 @@ def get_resources_dests(resources_root, rules):
class Config:
- """Reads configuration files and work with the Distribution instance
- """
+ """Class used to work with configuration files"""
def __init__(self, dist):
self.dist = dist
- self.setup_hook = None
+ self.setup_hooks = []
- def run_hook(self, config):
- if self.setup_hook is None:
- return
- # the hook gets only the config
- self.setup_hook(config)
+ def run_hooks(self, config):
+ """Run setup hooks in the order defined in the spec."""
+ for hook in self.setup_hooks:
+ hook(config)
def find_config_files(self):
"""Find as many configuration files as should be processed for this
@@ -124,29 +123,26 @@ class Config:
# XXX
return value
- def _multiline(self, value):
- value = [v for v in
- [v.strip() for v in value.split('\n')]
- if v != '']
- return value
-
def _read_setup_cfg(self, parser, cfg_filename):
cfg_directory = os.path.dirname(os.path.abspath(cfg_filename))
content = {}
for section in parser.sections():
content[section] = dict(parser.items(section))
- # global:setup_hook is called *first*
+ # global setup hooks are called first
if 'global' in content:
- if 'setup_hook' in content['global']:
- setup_hook = content['global']['setup_hook']
- try:
- self.setup_hook = resolve_name(setup_hook)
- except ImportError as e:
- logger.warning('could not import setup_hook: %s',
- e.args[0])
- else:
- self.run_hook(content)
+ if 'setup_hooks' in content['global']:
+ setup_hooks = split_multiline(content['global']['setup_hooks'])
+
+ for line in setup_hooks:
+ try:
+ hook = resolve_name(line)
+ except ImportError as e:
+ logger.warning('cannot find setup hook: %s', e.args[0])
+ else:
+ self.setup_hooks.append(hook)
+
+ self.run_hooks(content)
metadata = self.dist.metadata
@@ -155,7 +151,7 @@ class Config:
for key, value in content['metadata'].items():
key = key.replace('_', '-')
if metadata.is_multi_field(key):
- value = self._multiline(value)
+ value = split_multiline(value)
if key == 'project-url':
value = [(label.strip(), url.strip())
@@ -168,21 +164,18 @@ class Config:
"mutually exclusive")
raise PackagingOptionError(msg)
- if isinstance(value, list):
- filenames = value
- else:
- filenames = value.split()
+ filenames = value.split()
- # concatenate each files
- value = ''
+ # concatenate all files
+ value = []
for filename in filenames:
# will raise if file not found
with open(filename) as description_file:
- value += description_file.read().strip() + '\n'
+ value.append(description_file.read().strip())
# add filename as a required file
if filename not in metadata.requires_files:
metadata.requires_files.append(filename)
- value = value.strip()
+ value = '\n'.join(value).strip()
key = 'description'
if metadata.is_metadata_field(key):
@@ -192,7 +185,7 @@ class Config:
files = content['files']
self.dist.package_dir = files.pop('packages_root', None)
- files = dict((key, self._multiline(value)) for key, value in
+ files = dict((key, split_multiline(value)) for key, value in
files.items())
self.dist.packages = []
@@ -310,7 +303,7 @@ class Config:
opt = opt.replace('-', '_')
if opt == 'sub_commands':
- val = self._multiline(val)
+ val = split_multiline(val)
if isinstance(val, str):
val = [val]
@@ -348,14 +341,14 @@ class Config:
raise PackagingOptionError(msg)
def _load_compilers(self, compilers):
- compilers = self._multiline(compilers)
+ compilers = split_multiline(compilers)
if isinstance(compilers, str):
compilers = [compilers]
for compiler in compilers:
set_compiler(compiler.strip())
def _load_commands(self, commands):
- commands = self._multiline(commands)
+ commands = split_multiline(commands)
if isinstance(commands, str):
commands = [commands]
for command in commands:
diff --git a/Lib/packaging/create.py b/Lib/packaging/create.py
index c18d42f..917b6cf 100644
--- a/Lib/packaging/create.py
+++ b/Lib/packaging/create.py
@@ -175,11 +175,11 @@ def convert_yn_to_bool(yn, yes=True, no=False):
def _build_classifiers_dict(classifiers):
d = {}
for key in classifiers:
- subDict = d
+ subdict = d
for subkey in key.split(' :: '):
- if not subkey in subDict:
- subDict[subkey] = {}
- subDict = subDict[subkey]
+ if subkey not in subdict:
+ subdict[subkey] = {}
+ subdict = subdict[subkey]
return d
CLASSIFIERS = _build_classifiers_dict(_CLASSIFIERS_LIST)
diff --git a/Lib/packaging/database.py b/Lib/packaging/database.py
index 22d4b13..e3c57ba 100644
--- a/Lib/packaging/database.py
+++ b/Lib/packaging/database.py
@@ -104,12 +104,12 @@ def _generate_cache(use_egg_info=False, paths=sys.path):
for dist in _yield_distributions(gen_dist, gen_egg, paths):
if isinstance(dist, Distribution):
_cache_path[dist.path] = dist
- if not dist.name in _cache_name:
+ if dist.name not in _cache_name:
_cache_name[dist.name] = []
_cache_name[dist.name].append(dist)
else:
_cache_path_egg[dist.path] = dist
- if not dist.name in _cache_name_egg:
+ if dist.name not in _cache_name_egg:
_cache_name_egg[dist.name] = []
_cache_name_egg[dist.name].append(dist)
@@ -150,7 +150,7 @@ class Distribution:
self.version = self.metadata['Version']
self.path = path
- if _cache_enabled and not path in _cache_path:
+ if _cache_enabled and path not in _cache_path:
_cache_path[path] = self
def __repr__(self):
diff --git a/Lib/packaging/depgraph.py b/Lib/packaging/depgraph.py
index 48ea3d9..b3c555a 100644
--- a/Lib/packaging/depgraph.py
+++ b/Lib/packaging/depgraph.py
@@ -58,7 +58,7 @@ class DependencyGraph:
"""
self.adjacency_list[x].append((y, label))
# multiple edges are allowed, so be careful
- if not x in self.reverse_list[y]:
+ if x not in self.reverse_list[y]:
self.reverse_list[y].append(x)
def add_missing(self, distribution, requirement):
@@ -72,7 +72,7 @@ class DependencyGraph:
self.missing[distribution].append(requirement)
def _repr_dist(self, dist):
- return '%s %s' % (dist.name, dist.metadata['Version'])
+ return '%r %s' % (dist.name, dist.metadata['Version'])
def repr_node(self, dist, level=1):
"""Prints only a subgraph"""
@@ -154,10 +154,10 @@ def generate_graph(dists):
if len(comps) == 2:
version = comps[1]
if len(version) < 3 or version[0] != '(' or version[-1] != ')':
- raise PackagingError('Distribution %s has ill formed' \
- 'provides field: %s' % (dist.name, p))
+ raise PackagingError('distribution %r has ill-formed'
+ 'provides field: %r' % (dist.name, p))
version = version[1:-1] # trim off parenthesis
- if not name in provided:
+ if name not in provided:
provided[name] = []
provided[name].append((version, dist))
@@ -174,7 +174,7 @@ def generate_graph(dists):
name = predicate.name
- if not name in provided:
+ if name not in provided:
graph.add_missing(dist, req)
else:
matched = False
@@ -204,8 +204,9 @@ def dependent_dists(dists, dist):
:param dists: a list of distributions
:param dist: a distribution, member of *dists* for which we are interested
"""
- if not dist in dists:
- raise ValueError('The given distribution is not a member of the list')
+ if dist not in dists:
+ raise ValueError('given distribution %r is not a member of the list' %
+ dist.name)
graph = generate_graph(dists)
dep = [dist] # dependent distributions
@@ -215,7 +216,7 @@ def dependent_dists(dists, dist):
node = fringe.pop()
dep.append(node)
for prev in graph.reverse_list[node]:
- if not prev in dep:
+ if prev not in dep:
fringe.append(prev)
dep.pop(0) # remove dist from dep, was there to prevent infinite loops
@@ -236,17 +237,19 @@ def main():
except Exception as e:
tempout.seek(0)
tempout = tempout.read()
- print('Could not generate the graph\n%s\n%s\n' % (tempout, e))
+ print('Could not generate the graph')
+ print(tempout)
+ print(e)
sys.exit(1)
for dist, reqs in graph.missing.items():
if len(reqs) > 0:
- print("Warning: Missing dependencies for %s:" % dist.name,
+ print("Warning: Missing dependencies for %r:" % dist.name,
", ".join(reqs))
# XXX replace with argparse
if len(sys.argv) == 1:
print('Dependency graph:')
- print(' ' + repr(graph).replace('\n', '\n '))
+ print(' ', repr(graph).replace('\n', '\n '))
sys.exit(0)
elif len(sys.argv) > 1 and sys.argv[1] in ('-d', '--dot'):
if len(sys.argv) > 2:
@@ -259,7 +262,7 @@ def main():
tempout.seek(0)
tempout = tempout.read()
print(tempout)
- print('Dot file written at "%s"' % filename)
+ print('Dot file written at %r' % filename)
sys.exit(0)
else:
print('Supported option: -d [filename]')
diff --git a/Lib/packaging/dist.py b/Lib/packaging/dist.py
index 6065e78..5c390ce 100644
--- a/Lib/packaging/dist.py
+++ b/Lib/packaging/dist.py
@@ -509,14 +509,14 @@ Common commands: (see '--help-commands' for more)
options = self.global_options
parser.set_option_table(options)
parser.print_help(self.common_usage + "\nGlobal options:")
- print('')
+ print()
if display_options:
parser.set_option_table(self.display_options)
parser.print_help(
"Information display options (just display " +
"information, ignore any commands)")
- print('')
+ print()
for command in self.commands:
if isinstance(command, type) and issubclass(command, Command):
@@ -529,7 +529,7 @@ Common commands: (see '--help-commands' for more)
else:
parser.set_option_table(cls.user_options)
parser.print_help("Options for %r command:" % cls.__name__)
- print('')
+ print()
print(gen_usage(self.script_name))
@@ -544,7 +544,7 @@ Common commands: (see '--help-commands' for more)
# we ignore "foo bar").
if self.help_commands:
self.print_commands()
- print('')
+ print()
print(gen_usage(self.script_name))
return 1
diff --git a/Lib/packaging/install.py b/Lib/packaging/install.py
index 4b82088..c5bda45 100644
--- a/Lib/packaging/install.py
+++ b/Lib/packaging/install.py
@@ -13,7 +13,7 @@ import errno
import shutil
import logging
import tempfile
-from sysconfig import get_config_var, get_path
+from sysconfig import get_config_var, get_path, is_python_build
from packaging import logger
from packaging.dist import Distribution
@@ -488,20 +488,31 @@ def install(project):
Returns True on success, False on failure
"""
+ if is_python_build():
+ # Python would try to install into the site-packages directory under
+ # $PREFIX, but when running from an uninstalled code checkout we don't
+ # want to create directories under the installation root
+ message = ('installing third-party projects from an uninstalled '
+ 'Python is not supported')
+ logger.error(message)
+ return False
+
logger.info('Checking the installation location...')
purelib_path = get_path('purelib')
+
# trying to write a file there
try:
with tempfile.NamedTemporaryFile(suffix=project,
dir=purelib_path) as testfile:
testfile.write(b'test')
except OSError:
- # was unable to write a file
+ # FIXME this should check the errno, or be removed altogether (race
+ # condition: the directory permissions could be changed between here
+ # and the actual install)
logger.info('Unable to write in "%s". Do you have the permissions ?'
% purelib_path)
return False
-
logger.info('Getting information about %r...', project)
try:
info = get_infos(project)
@@ -520,7 +531,7 @@ def install(project):
except InstallationConflict as e:
if logger.isEnabledFor(logging.INFO):
- projects = ['%s %s' % (p.name, p.version) for p in e.args[0]]
+ projects = ['%r %s' % (p.name, p.version) for p in e.args[0]]
logger.info('%r conflicts with %s', project, ','.join(projects))
return True
diff --git a/Lib/packaging/pypi/dist.py b/Lib/packaging/pypi/dist.py
index db04cda..d3824c2 100644
--- a/Lib/packaging/pypi/dist.py
+++ b/Lib/packaging/pypi/dist.py
@@ -256,7 +256,7 @@ class DistInfo(IndexReference):
hashlib.new(hashname)
except ValueError:
raise UnsupportedHashName(hashname)
- if not url in [u['url'] for u in self.urls]:
+ if url not in [u['url'] for u in self.urls]:
self.urls.append({
'url': url,
'hashname': hashname,
@@ -329,7 +329,7 @@ class DistInfo(IndexReference):
url param"""
hashname = self.url['hashname']
expected_hashval = self.url['hashval']
- if not None in (expected_hashval, hashname):
+ if None not in (expected_hashval, hashname):
with open(filename, 'rb') as f:
hashval = hashlib.new(hashname)
hashval.update(f.read())
@@ -409,7 +409,7 @@ class ReleasesList(IndexReference):
(release.name, self.name))
version = str(release.version)
- if not version in self.get_versions():
+ if version not in self.get_versions():
# append only if not already exists
self.releases.append(release)
for dist in release.dists.values():
diff --git a/Lib/packaging/pypi/simple.py b/Lib/packaging/pypi/simple.py
index c372c6f..1dcb8ce 100644
--- a/Lib/packaging/pypi/simple.py
+++ b/Lib/packaging/pypi/simple.py
@@ -231,7 +231,8 @@ class Crawler(BaseClient):
"""
self._mirrors_used.add(self.index_url)
index_url = self._mirrors.pop()
- if not ("http://" or "https://" or "file://") in index_url:
+ # XXX use urllib.parse for a real check of missing scheme part
+ if not index_url.startswith(("http://", "https://", "file://")):
index_url = "http://%s" % index_url
if not index_url.endswith("/simple"):
@@ -282,7 +283,7 @@ class Crawler(BaseClient):
name = release.name
else:
name = release_info['name']
- if not name.lower() in self._projects:
+ if name.lower() not in self._projects:
self._projects[name.lower()] = ReleasesList(name, index=self._index)
if release:
@@ -320,7 +321,7 @@ class Crawler(BaseClient):
# it's a distribution, so create a dist object
try:
infos = get_infos_from_url(link, project_name,
- is_external=not self.index_url in url)
+ is_external=self.index_url not in url)
except CantParseArchiveName as e:
if self.verbose:
logger.warning(
diff --git a/Lib/packaging/run.py b/Lib/packaging/run.py
index c17ccfd..3e720cf 100644
--- a/Lib/packaging/run.py
+++ b/Lib/packaging/run.py
@@ -286,9 +286,9 @@ def _metadata(dispatcher, args, **kw):
value = metadata[key]
if isinstance(value, list):
for v in value:
- print(' ' + v)
+ print(' ', v)
else:
- print(' ' + value.replace('\n', '\n '))
+ print(' ', value.replace('\n', '\n '))
@action_help(remove_usage)
@@ -366,7 +366,7 @@ def _list(dispatcher, args, **kw):
print('%s %s at %s' % (dist.name, dist.metadata['version'], dist.path))
number += 1
- print('')
+ print()
if number == 0:
print('Nothing seems to be installed.')
else:
@@ -405,7 +405,6 @@ class Dispatcher:
self.verbose = 1
self.dry_run = False
self.help = False
- self.script_name = 'pysetup'
self.cmdclass = {}
self.commands = []
self.command_options = {}
@@ -574,17 +573,17 @@ class Dispatcher:
from packaging.command.cmd import Command
print('Usage: pysetup [options] action [action_options]')
- print('')
+ print()
if global_options_:
self.print_usage(self.parser)
- print('')
+ print()
if display_options_:
parser.set_option_table(display_options)
parser.print_help(
"Information display options (just display " +
"information, ignore any commands)")
- print('')
+ print()
for command in commands:
if isinstance(command, type) and issubclass(command, Command):
@@ -598,15 +597,15 @@ class Dispatcher:
parser.set_option_table(cls.user_options)
parser.print_help("Options for %r command:" % cls.__name__)
- print('')
+ print()
def _show_command_help(self, command):
if isinstance(command, str):
command = get_command_class(command)
desc = getattr(command, 'description', '(no description available)')
- print('Description: %s' % desc)
- print('')
+ print('Description:', desc)
+ print()
if (hasattr(command, 'help_options') and
isinstance(command.help_options, list)):
@@ -616,7 +615,7 @@ class Dispatcher:
self.parser.set_option_table(command.user_options)
self.parser.print_help("Options:")
- print('')
+ print()
def _get_command_groups(self):
"""Helper function to retrieve all the command class names divided
diff --git a/Lib/packaging/tests/test_command_bdist_dumb.py b/Lib/packaging/tests/test_command_bdist_dumb.py
index 41b0dd0..b235795 100644
--- a/Lib/packaging/tests/test_command_bdist_dumb.py
+++ b/Lib/packaging/tests/test_command_bdist_dumb.py
@@ -49,7 +49,6 @@ class BuildDumbTestCase(support.TempdirManager,
'py_modules': ['foo'],
'url': 'xxx', 'author': 'xxx',
'author_email': 'xxx'})
- dist.script_name = 'setup.py'
os.chdir(pkg_dir)
sys.argv[:] = ['setup.py']
diff --git a/Lib/packaging/tests/test_command_build_py.py b/Lib/packaging/tests/test_command_build_py.py
index 49069f5..243a863 100644
--- a/Lib/packaging/tests/test_command_build_py.py
+++ b/Lib/packaging/tests/test_command_build_py.py
@@ -33,9 +33,7 @@ class BuildPyTestCase(support.TempdirManager,
dist = Distribution({"packages": ["pkg"],
"package_dir": sources})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
dist.command_obj["build"] = support.DummyCommand(
force=False,
build_lib=destination,
@@ -89,8 +87,6 @@ class BuildPyTestCase(support.TempdirManager,
dist = Distribution({"packages": ["pkg"],
"package_dir": sources,
"package_data": {"pkg": ["doc/*"]}})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
dist.script_args = ["build"]
dist.parse_command_line()
diff --git a/Lib/packaging/tests/test_command_install_dist.py b/Lib/packaging/tests/test_command_install_dist.py
index 1974a2f..7821a3a 100644
--- a/Lib/packaging/tests/test_command_install_dist.py
+++ b/Lib/packaging/tests/test_command_install_dist.py
@@ -30,8 +30,6 @@ class InstallTestCase(support.TempdirManager,
destination = os.path.join(builddir, "installation")
dist = Distribution({"name": "foopkg"})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(builddir, "setup.py")
dist.command_obj["build"] = support.DummyCommand(
build_base=builddir,
build_lib=os.path.join(builddir, "lib"),
diff --git a/Lib/packaging/tests/test_command_install_distinfo.py b/Lib/packaging/tests/test_command_install_distinfo.py
index 6d40f66..ade191c 100644
--- a/Lib/packaging/tests/test_command_install_distinfo.py
+++ b/Lib/packaging/tests/test_command_install_distinfo.py
@@ -162,7 +162,7 @@ class InstallDistinfoTestCase(support.TempdirManager,
expected = []
for f in install.get_outputs():
- if (f.endswith('.pyc') or f == os.path.join(
+ if (f.endswith(('.pyc', '.pyo')) or f == os.path.join(
install_dir, 'foo-1.0.dist-info', 'RECORD')):
expected.append([f, '', ''])
else:
diff --git a/Lib/packaging/tests/test_command_install_lib.py b/Lib/packaging/tests/test_command_install_lib.py
index 96749e3..b46f3bd 100644
--- a/Lib/packaging/tests/test_command_install_lib.py
+++ b/Lib/packaging/tests/test_command_install_lib.py
@@ -65,7 +65,6 @@ class InstallLibTestCase(support.TempdirManager,
self.write_file(f, '# python package')
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
cmd.distribution.packages = [pkg_dir]
- cmd.distribution.script_name = 'setup.py'
# make sure the build_lib is set the temp dir
build_dir = os.path.split(pkg_dir)[0]
@@ -86,7 +85,6 @@ class InstallLibTestCase(support.TempdirManager,
self.write_file(f, '# python package')
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
cmd.distribution.packages = [pkg_dir]
- cmd.distribution.script_name = 'setup.py'
# get_input should return 2 elements
self.assertEqual(len(cmd.get_inputs()), 2)
diff --git a/Lib/packaging/tests/test_command_sdist.py b/Lib/packaging/tests/test_command_sdist.py
index 41b2a24..bcaa630 100644
--- a/Lib/packaging/tests/test_command_sdist.py
+++ b/Lib/packaging/tests/test_command_sdist.py
@@ -24,16 +24,11 @@ from packaging.util import find_executable
from packaging.tests import support
from shutil import get_archive_formats
-SETUP_PY = """
-from packaging.core import setup
-import somecode
-
-setup(name='fake')
-"""
MANIFEST = """\
# file GENERATED by packaging, do NOT edit
inroot.txt
+setup.cfg
data%(sep)sdata.dt
scripts%(sep)sscript.py
some%(sep)sfile.txt
@@ -56,8 +51,6 @@ class SDistTestCase(support.TempdirManager,
restore_environ = ['HOME']
def setUp(self):
- # PyPIRCCommandTestCase creates a temp dir already
- # and put it in self.tmp_dir
super(SDistTestCase, self).setUp()
self.tmp_dir = self.mkdtemp()
os.environ['HOME'] = self.tmp_dir
@@ -68,7 +61,6 @@ class SDistTestCase(support.TempdirManager,
# a package, and a README
self.write_file((self.tmp_dir, 'README'), 'xxx')
self.write_file((self.tmp_dir, 'somecode', '__init__.py'), '#')
- self.write_file((self.tmp_dir, 'setup.py'), SETUP_PY)
os.chdir(self.tmp_dir)
def tearDown(self):
@@ -83,7 +75,6 @@ class SDistTestCase(support.TempdirManager,
'url': 'xxx', 'author': 'xxx',
'author_email': 'xxx'}
dist = Distribution(metadata)
- dist.script_name = 'setup.py'
dist.packages = ['somecode']
dist.include_package_data = True
cmd = sdist(dist)
@@ -173,6 +164,7 @@ class SDistTestCase(support.TempdirManager,
# in package_data
dist.package_data = {'': ['*.cfg', '*.dat'],
'somecode': ['*.txt']}
+ self.write_file((self.tmp_dir, 'setup.cfg'), '#')
self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#')
self.write_file((self.tmp_dir, 'somecode', 'doc.dat'), '#')
@@ -211,9 +203,9 @@ class SDistTestCase(support.TempdirManager,
with zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip')) as zip_file:
content = zip_file.namelist()
- # Making sure everything was added. This includes 9 code and data
- # files in addition to PKG-INFO.
- self.assertEqual(len(content), 9)
+ # Making sure everything was added. This includes 8 code and data
+ # files in addition to PKG-INFO and setup.cfg
+ self.assertEqual(len(content), 10)
# Checking the MANIFEST
with open(join(self.tmp_dir, 'MANIFEST')) as fp:
@@ -230,7 +222,7 @@ class SDistTestCase(support.TempdirManager,
cmd.ensure_finalized()
cmd.run()
warnings = self.get_logs(logging.WARN)
- self.assertEqual(len(warnings), 3)
+ self.assertEqual(len(warnings), 4)
# trying with a complete set of metadata
self.loghandler.flush()
@@ -242,8 +234,9 @@ class SDistTestCase(support.TempdirManager,
# removing manifest generated warnings
warnings = [warn for warn in warnings if
not warn.endswith('-- skipping')]
- # the remaining warning is about the use of the default file list
- self.assertEqual(len(warnings), 1)
+ # the remaining warnings are about the use of the default file list and
+ # the absence of setup.cfg
+ self.assertEqual(len(warnings), 2)
def test_show_formats(self):
__, stdout = captured_stdout(show_formats)
diff --git a/Lib/packaging/tests/test_command_upload.py b/Lib/packaging/tests/test_command_upload.py
index d7609a2..dbb4db7 100644
--- a/Lib/packaging/tests/test_command_upload.py
+++ b/Lib/packaging/tests/test_command_upload.py
@@ -140,8 +140,8 @@ class UploadTestCase(support.TempdirManager, support.EnvironRestorer,
cmd.upload_docs = True
cmd.ensure_finalized()
cmd.repository = self.pypi.full_address
+ prev_dir = os.getcwd()
try:
- prev_dir = os.getcwd()
os.chdir(self.tmp_dir)
cmd.run()
finally:
diff --git a/Lib/packaging/tests/test_config.py b/Lib/packaging/tests/test_config.py
index a276730..6be63eb 100644
--- a/Lib/packaging/tests/test_config.py
+++ b/Lib/packaging/tests/test_config.py
@@ -90,7 +90,7 @@ commands =
compilers =
packaging.tests.test_config.DCompiler
-setup_hook = %(setup-hook)s
+setup_hooks = %(setup-hooks)s
@@ -114,7 +114,7 @@ libraries = gecodeint gecodekernel -- sys.platform != 'win32'
GecodeInt GecodeKernel -- sys.platform == 'win32'
[extension=fast_taunt]
-name = three.fast_taunt
+name = two.fast_taunt
sources = cxx_src/utils_taunt.cxx
cxx_src/python_module.cxx
include_dirs = /usr/include/gecode
@@ -135,8 +135,16 @@ class DCompiler:
pass
-def hook(content):
- content['metadata']['version'] += '.dev1'
+def version_hook(config):
+ config['metadata']['version'] += '.dev1'
+
+
+def first_hook(config):
+ config['files']['modules'] += '\n first'
+
+
+def third_hook(config):
+ config['files']['modules'] += '\n third'
class FooBarBazTest:
@@ -186,7 +194,7 @@ class ConfigTestCase(support.TempdirManager,
def write_setup(self, kwargs=None):
opts = {'description-file': 'README', 'extra-files': '',
- 'setup-hook': 'packaging.tests.test_config.hook'}
+ 'setup-hooks': 'packaging.tests.test_config.version_hook'}
if kwargs:
opts.update(kwargs)
self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
@@ -305,7 +313,7 @@ class ConfigTestCase(support.TempdirManager,
self.assertEqual(ext.extra_link_args,
['`gcc -print-file-name=libgcc.a`', '-shared'])
- ext = ext_modules.get('three.fast_taunt')
+ ext = ext_modules.get('two.fast_taunt')
self.assertEqual(ext.sources,
['cxx_src/utils_taunt.cxx', 'cxx_src/python_module.cxx'])
self.assertEqual(ext.include_dirs,
@@ -318,16 +326,30 @@ class ConfigTestCase(support.TempdirManager,
self.assertEqual(ext.extra_compile_args, cargs)
self.assertEqual(ext.language, 'cxx')
- def test_missing_setuphook_warns(self):
- self.write_setup({'setup-hook': 'this.does._not.exist'})
+ def test_missing_setup_hook_warns(self):
+ self.write_setup({'setup-hooks': 'this.does._not.exist'})
self.write_file('README', 'yeah')
dist = self.get_dist()
logs = self.get_logs(logging.WARNING)
self.assertEqual(1, len(logs))
- self.assertIn('could not import setup_hook', logs[0])
+ self.assertIn('cannot find setup hook', logs[0])
+
+ def test_multiple_setup_hooks(self):
+ self.write_setup({
+ 'setup-hooks': '\n packaging.tests.test_config.first_hook'
+ '\n packaging.tests.test_config.missing_hook'
+ '\n packaging.tests.test_config.third_hook'
+ })
+ self.write_file('README', 'yeah')
+ dist = self.get_dist()
+
+ self.assertEqual(['haven', 'first', 'third'], dist.py_modules)
+ logs = self.get_logs(logging.WARNING)
+ self.assertEqual(1, len(logs))
+ self.assertIn('cannot find setup hook', logs[0])
def test_metadata_requires_description_files_missing(self):
- self.write_setup({'description-file': 'README\n README2'})
+ self.write_setup({'description-file': 'README README2'})
self.write_file('README', 'yeah')
self.write_file('README2', 'yeah')
os.mkdir('src')
diff --git a/Lib/packaging/tests/test_create.py b/Lib/packaging/tests/test_create.py
index 906ca8f..a82ab43 100644
--- a/Lib/packaging/tests/test_create.py
+++ b/Lib/packaging/tests/test_create.py
@@ -13,6 +13,7 @@ class CreateTestCase(support.TempdirManager,
support.EnvironRestorer,
unittest.TestCase):
+ maxDiff = None
restore_environ = ['PLAT']
def setUp(self):
@@ -65,10 +66,15 @@ class CreateTestCase(support.TempdirManager,
# building the structure
tempdir = self.wdir
dirs = ['pkg1', 'data', 'pkg2', 'pkg2/sub']
- files = ['README', 'setup.cfg', 'foo.py',
- 'pkg1/__init__.py', 'pkg1/bar.py',
- 'data/data1', 'pkg2/__init__.py',
- 'pkg2/sub/__init__.py']
+ files = [
+ 'README',
+ 'data/data1',
+ 'foo.py',
+ 'pkg1/__init__.py',
+ 'pkg1/bar.py',
+ 'pkg2/__init__.py',
+ 'pkg2/sub/__init__.py',
+ ]
for dir_ in dirs:
os.mkdir(os.path.join(tempdir, dir_))
@@ -85,8 +91,8 @@ class CreateTestCase(support.TempdirManager,
['pkg1', 'pkg2', 'pkg2.sub'])
self.assertEqual(mainprogram.data['modules'], ['foo'])
data_fn = os.path.join('data', 'data1')
- self.assertEqual(set(mainprogram.data['extra_files']),
- set(['setup.cfg', 'README', data_fn]))
+ self.assertEqual(mainprogram.data['extra_files'],
+ ['README', data_fn])
def test_convert_setup_py_to_cfg(self):
self.write_file((self.wdir, 'setup.py'),
@@ -130,43 +136,45 @@ class CreateTestCase(support.TempdirManager,
main()
with open(os.path.join(self.wdir, 'setup.cfg'), encoding='utf-8') as fp:
- lines = set(line.rstrip() for line in fp)
-
- # FIXME don't use sets
- self.assertEqual(lines, set(['',
- '[metadata]',
- 'version = 0.2',
- 'name = pyxfoil',
- 'maintainer = André Espaze',
- 'description = My super Death-scription',
- ' |barbar is now on the public domain,',
- ' |ho, baby !',
- 'maintainer_email = andre.espaze@logilab.fr',
- 'home_page = http://www.python-science.org/project/pyxfoil',
- 'download_url = UNKNOWN',
- 'summary = Python bindings for the Xfoil engine',
- '[files]',
- 'modules = my_lib',
- ' mymodule',
- 'packages = pyxfoil',
- ' babar',
- ' me',
- 'extra_files = Martinique/Lamentin/dady',
- ' Martinique/Lamentin/mumy',
- ' Martinique/Lamentin/sys',
- ' Martinique/Lamentin/bro',
- ' Pom',
- ' Flora',
- ' Alexander',
- ' setup.py',
- ' README',
- ' pyxfoil/fengine.so',
- 'scripts = my_script',
- ' bin/run',
- 'resources =',
- ' README.rst = {doc}',
- ' pyxfoil.1 = {man}',
- ]))
+ contents = fp.read()
+
+ self.assertEqual(contents, dedent("""\
+ [metadata]
+ name = pyxfoil
+ version = 0.2
+ summary = Python bindings for the Xfoil engine
+ download_url = UNKNOWN
+ home_page = http://www.python-science.org/project/pyxfoil
+ maintainer = André Espaze
+ maintainer_email = andre.espaze@logilab.fr
+ description = My super Death-scription
+ |barbar is now on the public domain,
+ |ho, baby !
+
+ [files]
+ packages = pyxfoil
+ babar
+ me
+ modules = my_lib
+ mymodule
+ scripts = my_script
+ bin/run
+ extra_files = Martinique/Lamentin/dady
+ Martinique/Lamentin/mumy
+ Martinique/Lamentin/sys
+ Martinique/Lamentin/bro
+ setup.py
+ README
+ Pom
+ Flora
+ Alexander
+ pyxfoil/fengine.so
+
+ resources =
+ README.rst = {doc}
+ pyxfoil.1 = {man}
+
+ """))
def test_convert_setup_py_to_cfg_with_description_in_readme(self):
self.write_file((self.wdir, 'setup.py'),
@@ -203,26 +211,29 @@ ho, baby!
# FIXME Out of memory error.
main()
with open(os.path.join(self.wdir, 'setup.cfg'), encoding='utf-8') as fp:
- lines = set(line.rstrip() for line in fp)
-
- self.assertEqual(lines, set(['',
- '[metadata]',
- 'version = 0.2',
- 'name = pyxfoil',
- 'maintainer = André Espaze',
- 'maintainer_email = andre.espaze@logilab.fr',
- 'home_page = http://www.python-science.org/project/pyxfoil',
- 'download_url = UNKNOWN',
- 'summary = Python bindings for the Xfoil engine',
- 'description-file = README.txt',
- '[files]',
- 'packages = pyxfoil',
- 'extra_files = pyxfoil/fengine.so',
- ' pyxfoil/babar.so',
- 'resources =',
- ' README.rst = {doc}',
- ' pyxfoil.1 = {man}',
- ]))
+ contents = fp.read()
+
+ self.assertEqual(contents, dedent("""\
+ [metadata]
+ name = pyxfoil
+ version = 0.2
+ summary = Python bindings for the Xfoil engine
+ download_url = UNKNOWN
+ home_page = http://www.python-science.org/project/pyxfoil
+ maintainer = André Espaze
+ maintainer_email = andre.espaze@logilab.fr
+ description-file = README.txt
+
+ [files]
+ packages = pyxfoil
+ extra_files = pyxfoil/fengine.so
+ pyxfoil/babar.so
+
+ resources =
+ README.rst = {doc}
+ pyxfoil.1 = {man}
+
+ """))
def test_suite():
diff --git a/Lib/packaging/tests/test_dist.py b/Lib/packaging/tests/test_dist.py
index fb6d524..e1c5ff0 100644
--- a/Lib/packaging/tests/test_dist.py
+++ b/Lib/packaging/tests/test_dist.py
@@ -35,7 +35,7 @@ class DistributionTestCase(support.TempdirManager,
support.EnvironRestorer,
unittest.TestCase):
- restore_environ = ['HOME']
+ restore_environ = ['HOME', 'PLAT']
def setUp(self):
super(DistributionTestCase, self).setUp()
diff --git a/Lib/packaging/tests/test_install.py b/Lib/packaging/tests/test_install.py
index c50a45e..35733c8 100644
--- a/Lib/packaging/tests/test_install.py
+++ b/Lib/packaging/tests/test_install.py
@@ -1,5 +1,7 @@
"""Tests for the packaging.install module."""
import os
+import logging
+from sysconfig import is_python_build
from tempfile import mkstemp
from packaging import install
@@ -357,9 +359,17 @@ class TestInstall(LoggingCatcher, TempdirManager, unittest.TestCase):
install._install_dist = old_install_dist
def test_install_permission_denied(self):
- # if we don't have the access to the installation
- # path, we should abort immediatly
+ # if we don't have access to the installation path, we should abort
+ # immediately
project = os.path.join(os.path.dirname(__file__), 'package.tgz')
+
+ # when running from an uninstalled build, a warning is emitted and the
+ # installation is not attempted
+ if is_python_build():
+ self.assertFalse(install.install(project))
+ self.assertEqual(1, len(self.get_logs(logging.ERROR)))
+ return
+
install_path = self.mkdtemp()
old_get_path = install.get_path
install.get_path = lambda path: install_path
diff --git a/Lib/packaging/tests/test_util.py b/Lib/packaging/tests/test_util.py
index 5a94a73..9b6498b 100644
--- a/Lib/packaging/tests/test_util.py
+++ b/Lib/packaging/tests/test_util.py
@@ -8,16 +8,18 @@ import subprocess
from io import StringIO
from packaging.tests import support, unittest
+from packaging.tests.test_config import SETUP_CFG
from packaging.errors import (
PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
PackagingExecError, InstallationException)
from packaging import util
+from packaging.dist import Distribution
from packaging.util import (
convert_path, change_root, split_quoted, strtobool, rfc822_escape,
get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
- get_install_method)
+ get_install_method, cfg_to_args)
PYPIRC = """\
@@ -88,13 +90,15 @@ class UtilTestCase(support.EnvironRestorer,
support.LoggingCatcher,
unittest.TestCase):
- restore_environ = ['HOME']
+ restore_environ = ['HOME', 'PLAT']
def setUp(self):
super(UtilTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- self.rc = os.path.join(self.tmp_dir, '.pypirc')
- os.environ['HOME'] = self.tmp_dir
+ self.addCleanup(os.chdir, os.getcwd())
+ tempdir = self.mkdtemp()
+ self.rc = os.path.join(tempdir, '.pypirc')
+ os.environ['HOME'] = tempdir
+ os.chdir(tempdir)
# saving the environment
self.name = os.name
self.platform = sys.platform
@@ -103,7 +107,6 @@ class UtilTestCase(support.EnvironRestorer,
self.join = os.path.join
self.isabs = os.path.isabs
self.splitdrive = os.path.splitdrive
- #self._config_vars = copy(sysconfig._config_vars)
# patching os.uname
if hasattr(os, 'uname'):
@@ -137,7 +140,6 @@ class UtilTestCase(support.EnvironRestorer,
os.uname = self.uname
else:
del os.uname
- #sysconfig._config_vars = copy(self._config_vars)
util.find_executable = self.old_find_executable
subprocess.Popen = self.old_popen
sys.old_stdout = self.old_stdout
@@ -491,6 +493,38 @@ class UtilTestCase(support.EnvironRestorer,
content = f.read()
self.assertEqual(content, WANTED)
+ def test_cfg_to_args(self):
+ opts = {'description-file': 'README', 'extra-files': '',
+ 'setup-hooks': 'packaging.tests.test_config.version_hook'}
+ self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
+ self.write_file('README', 'loooong description')
+
+ args = cfg_to_args()
+ # use Distribution to get the contents of the setup.cfg file
+ dist = Distribution()
+ dist.parse_config_files()
+ metadata = dist.metadata
+
+ self.assertEqual(args['name'], metadata['Name'])
+ # + .dev1 because the test SETUP_CFG also tests a hook function in
+ # test_config.py for appending to the version string
+ self.assertEqual(args['version'] + '.dev1', metadata['Version'])
+ self.assertEqual(args['author'], metadata['Author'])
+ self.assertEqual(args['author_email'], metadata['Author-Email'])
+ self.assertEqual(args['maintainer'], metadata['Maintainer'])
+ self.assertEqual(args['maintainer_email'],
+ metadata['Maintainer-Email'])
+ self.assertEqual(args['description'], metadata['Summary'])
+ self.assertEqual(args['long_description'], metadata['Description'])
+ self.assertEqual(args['classifiers'], metadata['Classifier'])
+ self.assertEqual(args['requires'], metadata['Requires-Dist'])
+ self.assertEqual(args['provides'], metadata['Provides-Dist'])
+
+ self.assertEqual(args['package_dir'].get(''), dist.package_dir)
+ self.assertEqual(args['packages'], dist.packages)
+ self.assertEqual(args['scripts'], dist.scripts)
+ self.assertEqual(args['py_modules'], dist.py_modules)
+
class GlobTestCaseBase(support.TempdirManager,
support.LoggingCatcher,
diff --git a/Lib/packaging/util.py b/Lib/packaging/util.py
index d4aae41..4dff547 100644
--- a/Lib/packaging/util.py
+++ b/Lib/packaging/util.py
@@ -250,6 +250,14 @@ def split_quoted(s):
return words
+def split_multiline(value):
+ """Split a multiline string into a list, excluding blank lines."""
+
+ return [element for element in
+ (line.strip() for line in value.split('\n'))
+ if element]
+
+
def execute(func, args, msg=None, verbose=0, dry_run=False):
"""Perform some action that affects the outside world.
@@ -542,18 +550,15 @@ def write_file(filename, contents):
def _is_package(path):
- if not os.path.isdir(path):
- return False
- return os.path.isfile(os.path.join(path, '__init__.py'))
+ return os.path.isdir(path) and os.path.isfile(
+ os.path.join(path, '__init__.py'))
# Code taken from the pip project
def _is_archive_file(name):
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar')
ext = splitext(name)[1].lower()
- if ext in archives:
- return True
- return False
+ return ext in archives
def _under(path, root):
@@ -772,12 +777,13 @@ def spawn(cmd, search_path=True, verbose=0, dry_run=False, env=None):
Raise PackagingExecError if running the program fails in any way; just
return on success.
"""
- logger.info(' '.join(cmd))
+ logger.debug('spawn: running %r', cmd)
if dry_run:
+ logging.debug('dry run, no process actually spawned')
return
exit_status = subprocess.call(cmd, env=env)
if exit_status != 0:
- msg = "command '%s' failed with exit status %d"
+ msg = "command %r failed with exit status %d"
raise PackagingExecError(msg % (cmd, exit_status))
@@ -1010,16 +1016,20 @@ def cfg_to_args(path='setup.cfg'):
"requires": ("metadata", "requires_dist"),
"provides": ("metadata", "provides_dist"), # **
"obsoletes": ("metadata", "obsoletes_dist"), # **
+ "package_dir": ("files", 'packages_root'),
"packages": ("files",),
"scripts": ("files",),
"py_modules": ("files", "modules"), # **
}
MULTI_FIELDS = ("classifiers",
- "requires",
"platforms",
+ "requires",
+ "provides",
+ "obsoletes",
"packages",
- "scripts")
+ "scripts",
+ "py_modules")
def has_get_option(config, section, option):
if config.has_option(section, option):
@@ -1031,10 +1041,10 @@ def cfg_to_args(path='setup.cfg'):
# The real code starts here
config = RawConfigParser()
- if not os.path.exists(file):
+ if not os.path.exists(path):
raise PackagingFileError("file '%s' does not exist" %
- os.path.abspath(file))
- config.read(path)
+ os.path.abspath(path))
+ config.read(path, encoding='utf-8')
kwargs = {}
for arg in D1_D2_SETUP_ARGS:
@@ -1050,17 +1060,24 @@ def cfg_to_args(path='setup.cfg'):
in_cfg_value = has_get_option(config, section, option)
if not in_cfg_value:
# There is no such option in the setup.cfg
- if arg == "long_description":
- filename = has_get_option(config, section, "description_file")
- if filename:
- with open(filename) as fp:
- in_cfg_value = fp.read()
+ if arg == 'long_description':
+ filenames = has_get_option(config, section, 'description-file')
+ if filenames:
+ filenames = split_multiline(filenames)
+ in_cfg_value = []
+ for filename in filenames:
+ with open(filename) as fp:
+ in_cfg_value.append(fp.read())
+ in_cfg_value = '\n\n'.join(in_cfg_value)
else:
continue
+ if arg == 'package_dir' and in_cfg_value:
+ in_cfg_value = {'': in_cfg_value}
+
if arg in MULTI_FIELDS:
# support multiline options
- in_cfg_value = in_cfg_value.strip().split('\n')
+ in_cfg_value = split_multiline(in_cfg_value)
kwargs[arg] = in_cfg_value
@@ -1099,7 +1116,7 @@ def ask(message, options):
response = input(message)
response = response.strip().lower()
if response not in options:
- print('invalid response: %r' % response)
+ print('invalid response:', repr(response))
print('choose one of', ', '.join(repr(o) for o in options))
else:
return response
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index f724b9f..f9d1c99 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -162,7 +162,7 @@ def quotedata(data):
re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
def _quote_periods(bindata):
- return re.sub(br'(?m)^\.', '..', bindata)
+ return re.sub(br'(?m)^\.', b'..', bindata)
def _fix_eols(data):
return re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data)
@@ -172,27 +172,6 @@ try:
except ImportError:
_have_ssl = False
else:
- class SSLFakeFile:
- """A fake file like object that really wraps a SSLObject.
-
- It only supports what is needed in smtplib.
- """
- def __init__(self, sslobj):
- self.sslobj = sslobj
-
- def readline(self):
- str = b""
- chr = None
- while chr != b"\n":
- chr = self.sslobj.read(1)
- if not chr:
- break
- str += chr
- return str
-
- def close(self):
- pass
-
_have_ssl = True
@@ -322,6 +301,7 @@ class SMTP:
if self.debuglevel > 0:
print('connect:', (host, port), file=stderr)
self.sock = self._get_socket(host, port, self.timeout)
+ self.file = None
(code, msg) = self.getreply()
if self.debuglevel > 0:
print("connect:", msg, file=stderr)
@@ -669,7 +649,7 @@ class SMTP:
self.sock = context.wrap_socket(self.sock)
else:
self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
- self.file = SSLFakeFile(self.sock)
+ self.file = None
# RFC 3207:
# The client MUST discard any knowledge obtained from
# the server, such as the list of SMTP service extensions,
@@ -853,7 +833,6 @@ if _have_ssl:
new_socket = self.context.wrap_socket(new_socket)
else:
new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
- self.file = SSLFakeFile(new_socket)
return new_socket
__all__.append("SMTP_SSL")
@@ -890,6 +869,7 @@ class LMTP(SMTP):
# Handle Unix-domain sockets.
try:
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.file = None
self.sock.connect(host)
except socket.error as msg:
if self.debuglevel > 0:
diff --git a/Lib/sysconfig.cfg b/Lib/sysconfig.cfg
index 1f6b8bc..573b12e 100644
--- a/Lib/sysconfig.cfg
+++ b/Lib/sysconfig.cfg
@@ -1,24 +1,24 @@
[globals]
-# These are the useful categories that are sometimes referenced at runtime,
-# using packaging.resources.get_file:
+# These are useful categories that can be referenced at run time,
+# using packaging.database.get_file.
# Configuration files
config = {confdir}/{distribution.name}
# Non-writable data that is independent of architecture (images, many xml/text files)
appdata = {datadir}/{distribution.name}
# Non-writable data that is architecture-dependent (some binary data formats)
appdata.arch = {libdir}/{distribution.name}
-# Data, written by the package, that must be preserved (databases)
+# Data, written by the app/lib, that must be preserved (databases)
appdata.persistent = {statedir}/lib/{distribution.name}
-# Data, written by the package, that can be safely discarded (cache)
+# Data, written by the app/lib, that can be safely discarded (cache)
appdata.disposable = {statedir}/cache/{distribution.name}
-# Help or documentation files referenced at runtime
+# Help or documentation files
help = {datadir}/{distribution.name}
icon = {datadir}/pixmaps
scripts = {base}/bin
# Non-runtime files. These are valid categories for marking files for
-# install, but they should not be referenced by the app at runtime:
-# Help or documentation files not referenced by the package at runtime
+# install, but they should not be referenced by the app/lib at run time.
+# Help or documentation files
doc = {datadir}/doc/{distribution.name}
# GNU info documentation files
info = {datadir}/info
diff --git a/Lib/test/support.py b/Lib/test/support.py
index 739cb7b..a51d943 100644
--- a/Lib/test/support.py
+++ b/Lib/test/support.py
@@ -1561,9 +1561,10 @@ def can_symlink():
try:
os.symlink(TESTFN, symlink_path)
can = True
- os.remove(symlink_path)
except (OSError, NotImplementedError, AttributeError):
can = False
+ else:
+ os.remove(symlink_path)
_can_symlink = can
return can
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 2836e7e..b0e9a03 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -4480,6 +4480,67 @@ class TestArgumentTypeError(TestCase):
else:
self.fail()
+# =========================
+# MessageContentError tests
+# =========================
+
+class TestMessageContentError(TestCase):
+
+ def test_missing_argument_name_in_message(self):
+ parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
+ parser.add_argument('req_pos', type=str)
+ parser.add_argument('-req_opt', type=int, required=True)
+ parser.add_argument('need_one', type=str, nargs='+')
+
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args([])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertRegex(msg, 'req_opt')
+ self.assertRegex(msg, 'need_one')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args(['myXargument'])
+ msg = str(cm.exception)
+ self.assertNotIn(msg, 'req_pos')
+ self.assertRegex(msg, 'req_opt')
+ self.assertRegex(msg, 'need_one')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args(['myXargument', '-req_opt=1'])
+ msg = str(cm.exception)
+ self.assertNotIn(msg, 'req_pos')
+ self.assertNotIn(msg, 'req_opt')
+ self.assertRegex(msg, 'need_one')
+
+ def test_optional_optional_not_in_message(self):
+ parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
+ parser.add_argument('req_pos', type=str)
+ parser.add_argument('--req_opt', type=int, required=True)
+ parser.add_argument('--opt_opt', type=bool, nargs='?',
+ default=True)
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args([])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertRegex(msg, 'req_opt')
+ self.assertNotIn(msg, 'opt_opt')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args(['--req_opt=1'])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertNotIn(msg, 'req_opt')
+ self.assertNotIn(msg, 'opt_opt')
+
+ def test_optional_positional_not_in_message(self):
+ parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
+ parser.add_argument('req_pos')
+ parser.add_argument('optional_positional', nargs='?', default='eggs')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args([])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertNotIn(msg, 'optional_positional')
+
+
# ======================
# parse_known_args tests
# ======================
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 97619cf..ce1586f 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -372,7 +372,15 @@ class BuiltinTest(unittest.TestCase):
f = Foo()
self.assertTrue(dir(f) == ["ga", "kan", "roo"])
- # dir(obj__dir__not_list)
+ # dir(obj__dir__tuple)
+ class Foo(object):
+ def __dir__(self):
+ return ("b", "c", "a")
+ res = dir(Foo())
+ self.assertIsInstance(res, list)
+ self.assertTrue(res == ["a", "b", "c"])
+
+ # dir(obj__dir__not_sequence)
class Foo(object):
def __dir__(self):
return 7
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py
index 7457f39..5968980 100644
--- a/Lib/test/test_concurrent_futures.py
+++ b/Lib/test/test_concurrent_futures.py
@@ -19,7 +19,7 @@ import unittest
from concurrent import futures
from concurrent.futures._base import (
PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future)
-import concurrent.futures.process
+from concurrent.futures.process import BrokenProcessPool
def create_future(state=PENDING, exception=None, result=None):
@@ -154,7 +154,7 @@ class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest):
processes = self.executor._processes
self.executor.shutdown()
- for p in processes:
+ for p in processes.values():
p.join()
def test_context_manager_shutdown(self):
@@ -163,7 +163,7 @@ class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest):
self.assertEqual(list(e.map(abs, range(-5, 5))),
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4])
- for p in processes:
+ for p in processes.values():
p.join()
def test_del_shutdown(self):
@@ -174,7 +174,7 @@ class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest):
del executor
queue_management_thread.join()
- for p in processes:
+ for p in processes.values():
p.join()
class WaitTests(unittest.TestCase):
@@ -381,7 +381,17 @@ class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest):
class ProcessPoolExecutorTest(ProcessPoolMixin, ExecutorTest):
- pass
+ def test_killed_child(self):
+ # When a child process is abruptly terminated, the whole pool gets
+ # "broken".
+ futures = [self.executor.submit(time.sleep, 3)]
+ # Get one of the processes, and terminate (kill) it
+ p = next(iter(self.executor._processes.values()))
+ p.terminate()
+ for fut in futures:
+ self.assertRaises(BrokenProcessPool, fut.result)
+ # Submitting other jobs fails as well.
+ self.assertRaises(BrokenProcessPool, self.executor.submit, pow, 2, 8)
class FutureTests(unittest.TestCase):
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index f5dff1e..7666fe4 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -298,6 +298,23 @@ class TestRetrievingSourceCode(GetSourceBase):
del sys.modules[name]
inspect.getmodule(compile('a=10','','single'))
+ def test_proceed_with_fake_filename(self):
+ '''doctest monkeypatches linecache to enable inspection'''
+ fn, source = '<test>', 'def x(): pass\n'
+ getlines = linecache.getlines
+ def monkey(filename, module_globals=None):
+ if filename == fn:
+ return source.splitlines(True)
+ else:
+ return getlines(filename, module_globals)
+ linecache.getlines = monkey
+ try:
+ ns = {}
+ exec(compile(source, fn, 'single'), ns)
+ inspect.getsource(ns["x"])
+ finally:
+ linecache.getlines = getlines
+
class TestDecorators(GetSourceBase):
fodderModule = mod2
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index ceefd95..b0b8e19 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -1399,8 +1399,7 @@ class DatagramHandlerTest(BaseTest):
pointing to that server's address and port."""
BaseTest.setUp(self)
addr = ('localhost', 0)
- self.server = server = TestUDPServer(addr, self.handle_datagram,
- 0.01)
+ self.server = server = TestUDPServer(addr, self.handle_datagram, 0.01)
server.start()
server.ready.wait()
self.sock_hdlr = logging.handlers.DatagramHandler('localhost',
@@ -1478,6 +1477,11 @@ class SysLogHandlerTest(BaseTest):
logger.error("sp\xe4m")
self.handled.wait()
self.assertEqual(self.log_output, b'<11>\xef\xbb\xbfsp\xc3\xa4m\x00')
+ self.handled.clear()
+ self.sl_hdlr.append_nul = False
+ logger.error("sp\xe4m")
+ self.handled.wait()
+ self.assertEqual(self.log_output, b'<11>\xef\xbb\xbfsp\xc3\xa4m')
@unittest.skipUnless(threading, 'Threading required for this test.')
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index 712378b..4bbb19b 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -417,6 +417,35 @@ class MmapTests(unittest.TestCase):
m[x] = b
self.assertEqual(m[x], b)
+ def test_read_all(self):
+ m = mmap.mmap(-1, 16)
+ self.addCleanup(m.close)
+
+ # With no parameters, or None or a negative argument, reads all
+ m.write(bytes(range(16)))
+ m.seek(0)
+ self.assertEqual(m.read(), bytes(range(16)))
+ m.seek(8)
+ self.assertEqual(m.read(), bytes(range(8, 16)))
+ m.seek(16)
+ self.assertEqual(m.read(), b'')
+ m.seek(3)
+ self.assertEqual(m.read(None), bytes(range(3, 16)))
+ m.seek(4)
+ self.assertEqual(m.read(-1), bytes(range(4, 16)))
+ m.seek(5)
+ self.assertEqual(m.read(-2), bytes(range(5, 16)))
+ m.seek(9)
+ self.assertEqual(m.read(-42), bytes(range(9, 16)))
+
+ def test_read_invalid_arg(self):
+ m = mmap.mmap(-1, 16)
+ self.addCleanup(m.close)
+
+ self.assertRaises(TypeError, m.read, 'foo')
+ self.assertRaises(TypeError, m.read, 5.5)
+ self.assertRaises(TypeError, m.read, [1, 2, 3])
+
def test_extended_getslice(self):
# Test extended slicing by comparing with list slicing.
s = bytes(reversed(range(256)))
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py
index 0c05ff6..85094cc 100644
--- a/Lib/test/test_multiprocessing.py
+++ b/Lib/test/test_multiprocessing.py
@@ -71,6 +71,23 @@ HAVE_GETVALUE = not getattr(_multiprocessing,
'HAVE_BROKEN_SEM_GETVALUE', False)
WIN32 = (sys.platform == "win32")
+if WIN32:
+ from _subprocess import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
+
+ def wait_for_handle(handle, timeout):
+ if timeout is None or timeout < 0.0:
+ timeout = INFINITE
+ else:
+ timeout = int(1000 * timeout)
+ return WaitForSingleObject(handle, timeout) == WAIT_OBJECT_0
+else:
+ from select import select
+ _select = util._eintr_retry(select)
+
+ def wait_for_handle(handle, timeout):
+ if timeout is not None and timeout < 0.0:
+ timeout = None
+ return handle in _select([handle], [], [], timeout)[0]
#
# Some tests require ctypes
@@ -307,6 +324,26 @@ class _TestProcess(BaseTestCase):
]
self.assertEqual(result, expected)
+ @classmethod
+ def _test_sentinel(cls, event):
+ event.wait(10.0)
+
+ def test_sentinel(self):
+ if self.TYPE == "threads":
+ return
+ event = self.Event()
+ p = self.Process(target=self._test_sentinel, args=(event,))
+ with self.assertRaises(ValueError):
+ p.sentinel
+ p.start()
+ self.addCleanup(p.join)
+ sentinel = p.sentinel
+ self.assertIsInstance(sentinel, int)
+ self.assertFalse(wait_for_handle(sentinel, timeout=0.0))
+ event.set()
+ p.join()
+ self.assertTrue(wait_for_handle(sentinel, timeout=DELTA))
+
#
#
#
diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py
index da7ec05..ef70e37 100644
--- a/Lib/test/test_netrc.py
+++ b/Lib/test/test_netrc.py
@@ -1,54 +1,107 @@
-
-import netrc, os, unittest, sys
+import netrc, os, unittest, sys, textwrap
from test import support
-TEST_NETRC = """
-
- #this is a comment
-#this is a comment
-# this is a comment
-
-machine foo login log1 password pass1 account acct1
-machine bar login log1 password pass# account acct1
-
-macdef macro1
-line1
-line2
-
-macdef macro2
-line3
-line4
-
-default login log2 password pass2
-
-"""
-
temp_filename = support.TESTFN
class NetrcTestCase(unittest.TestCase):
- def setUp(self):
- mode = 'w'
- if sys.platform not in ['cygwin']:
- mode += 't'
- fp = open(temp_filename, mode)
- fp.write(TEST_NETRC)
- fp.close()
- self.nrc = netrc.netrc(temp_filename)
-
def tearDown(self):
os.unlink(temp_filename)
- def test_case_1(self):
- self.assertEqual(self.nrc.hosts['foo'], ('log1', 'acct1', 'pass1'))
- self.assertEqual(self.nrc.hosts['default'], ('log2', None, 'pass2'))
+ def make_nrc(self, test_data):
+ test_data = textwrap.dedent(test_data)
+ mode = 'w'
+ if sys.platform != 'cygwin':
+ mode += 't'
+ with open(temp_filename, mode) as fp:
+ fp.write(test_data)
+ return netrc.netrc(temp_filename)
+
+ def test_default(self):
+ nrc = self.make_nrc("""\
+ machine host1.domain.com login log1 password pass1 account acct1
+ default login log2 password pass2
+ """)
+ self.assertEqual(nrc.hosts['host1.domain.com'],
+ ('log1', 'acct1', 'pass1'))
+ self.assertEqual(nrc.hosts['default'], ('log2', None, 'pass2'))
def test_macros(self):
- self.assertEqual(self.nrc.macros, {'macro1':['line1\n', 'line2\n'],
- 'macro2':['line3\n', 'line4\n']})
+ nrc = self.make_nrc("""\
+ macdef macro1
+ line1
+ line2
+
+ macdef macro2
+ line3
+ line4
+ """)
+ self.assertEqual(nrc.macros, {'macro1': ['line1\n', 'line2\n'],
+ 'macro2': ['line3\n', 'line4\n']})
+
+ def _test_passwords(self, nrc, passwd):
+ nrc = self.make_nrc(nrc)
+ self.assertEqual(nrc.hosts['host.domain.com'], ('log', 'acct', passwd))
+
+ def test_password_with_leading_hash(self):
+ self._test_passwords("""\
+ machine host.domain.com login log password #pass account acct
+ """, '#pass')
+
+ def test_password_with_trailing_hash(self):
+ self._test_passwords("""\
+ machine host.domain.com login log password pass# account acct
+ """, 'pass#')
+
+ def test_password_with_internal_hash(self):
+ self._test_passwords("""\
+ machine host.domain.com login log password pa#ss account acct
+ """, 'pa#ss')
+
+ def _test_comment(self, nrc, passwd='pass'):
+ nrc = self.make_nrc(nrc)
+ self.assertEqual(nrc.hosts['foo.domain.com'], ('bar', None, passwd))
+ self.assertEqual(nrc.hosts['bar.domain.com'], ('foo', None, 'pass'))
+
+ def test_comment_before_machine_line(self):
+ self._test_comment("""\
+ # comment
+ machine foo.domain.com login bar password pass
+ machine bar.domain.com login foo password pass
+ """)
+
+ def test_comment_before_machine_line_no_space(self):
+ self._test_comment("""\
+ #comment
+ machine foo.domain.com login bar password pass
+ machine bar.domain.com login foo password pass
+ """)
+
+ def test_comment_before_machine_line_hash_only(self):
+ self._test_comment("""\
+ #
+ machine foo.domain.com login bar password pass
+ machine bar.domain.com login foo password pass
+ """)
+
+ def test_comment_at_end_of_machine_line(self):
+ self._test_comment("""\
+ machine foo.domain.com login bar password pass # comment
+ machine bar.domain.com login foo password pass
+ """)
+
+ def test_comment_at_end_of_machine_line_no_space(self):
+ self._test_comment("""\
+ machine foo.domain.com login bar password pass #comment
+ machine bar.domain.com login foo password pass
+ """)
+
+ def test_comment_at_end_of_machine_line_pass_has_hash(self):
+ self._test_comment("""\
+ machine foo.domain.com login bar password #pass #comment
+ machine bar.domain.com login foo password pass
+ """, '#pass')
- def test_parses_passwords_with_hash_character(self):
- self.assertEqual(self.nrc.hosts['bar'], ('log1', 'acct1', 'pass#'))
def test_main():
support.run_unittest(NetrcTestCase)
diff --git a/Lib/test/test_ossaudiodev.py b/Lib/test/test_ossaudiodev.py
index 9cb89d6..3908a05 100644
--- a/Lib/test/test_ossaudiodev.py
+++ b/Lib/test/test_ossaudiodev.py
@@ -170,6 +170,22 @@ class OSSAudioDevTests(unittest.TestCase):
pass
self.assertTrue(dsp.closed)
+ def test_on_closed(self):
+ dsp = ossaudiodev.open('w')
+ dsp.close()
+ self.assertRaises(ValueError, dsp.fileno)
+ self.assertRaises(ValueError, dsp.read, 1)
+ self.assertRaises(ValueError, dsp.write, b'x')
+ self.assertRaises(ValueError, dsp.writeall, b'x')
+ self.assertRaises(ValueError, dsp.bufsize)
+ self.assertRaises(ValueError, dsp.obufcount)
+ self.assertRaises(ValueError, dsp.obufcount)
+ self.assertRaises(ValueError, dsp.obuffree)
+ self.assertRaises(ValueError, dsp.getptr)
+
+ mixer = ossaudiodev.openmixer()
+ mixer.close()
+ self.assertRaises(ValueError, mixer.fileno)
def test_main():
try:
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
index b59f6e6..93f86d9 100644
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -1,8 +1,9 @@
-import sys
import os
-import unittest
import platform
import subprocess
+import sys
+import unittest
+import warnings
from test import support
@@ -250,10 +251,12 @@ class PlatformTest(unittest.TestCase):
command = '"{}" -c "print(\'Hello\')"'.format(sys.executable)
else:
command = "'{}' -c 'print(\"Hello\")'".format(sys.executable)
- with platform.popen(command) as stdout:
- hello = stdout.read().strip()
- stdout.close()
- self.assertEqual(hello, "Hello")
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ with platform.popen(command) as stdout:
+ hello = stdout.read().strip()
+ stdout.close()
+ self.assertEqual(hello, "Hello")
data = 'plop'
if mswindows:
@@ -261,15 +264,17 @@ class PlatformTest(unittest.TestCase):
else:
command = "'{}' -c 'import sys; data=sys.stdin.read(); exit(len(data))'"
command = command.format(sys.executable)
- with platform.popen(command, 'w') as stdin:
- stdout = stdin.write(data)
- ret = stdin.close()
- self.assertIsNotNone(ret)
- if os.name == 'nt':
- returncode = ret
- else:
- returncode = ret >> 8
- self.assertEqual(returncode, len(data))
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ with platform.popen(command, 'w') as stdin:
+ stdout = stdin.write(data)
+ ret = stdin.close()
+ self.assertIsNotNone(ret)
+ if os.name == 'nt':
+ returncode = ret
+ else:
+ returncode = ret >> 8
+ self.assertEqual(returncode, len(data))
def test_main():
diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
index 421ea68..438634e 100644
--- a/Lib/test/test_posix.py
+++ b/Lib/test/test_posix.py
@@ -481,8 +481,8 @@ class PosixTester(unittest.TestCase):
self.assertRaises(TypeError, os.pipe2, 'DEADBEEF')
self.assertRaises(TypeError, os.pipe2, 0, 0)
- # try calling without flag, like os.pipe()
- r, w = os.pipe2()
+ # try calling with flags = 0, like os.pipe()
+ r, w = os.pipe2(0)
os.close(r)
os.close(w)
@@ -569,6 +569,21 @@ class PosixTester(unittest.TestCase):
os.chdir(curdir)
support.rmtree(base_path)
+ @unittest.skipUnless(hasattr(posix, 'getgrouplist'), "test needs posix.getgrouplist()")
+ @unittest.skipUnless(hasattr(pwd, 'getpwuid'), "test needs pwd.getpwuid()")
+ @unittest.skipUnless(hasattr(os, 'getuid'), "test needs os.getuid()")
+ def test_getgrouplist(self):
+ with os.popen('id -G') as idg:
+ groups = idg.read().strip()
+
+ if not groups:
+ raise unittest.SkipTest("need working 'id -G'")
+
+ self.assertEqual(
+ set([int(x) for x in groups.split()]),
+ set(posix.getgrouplist(pwd.getpwuid(os.getuid())[0],
+ pwd.getpwuid(os.getuid())[3])))
+
@unittest.skipUnless(hasattr(os, 'getegid'), "test needs os.getegid()")
def test_getgroups(self):
with os.popen('id -G') as idg:
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index 0631390..effdbef 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -9,6 +9,7 @@ import struct
import subprocess
import traceback
import sys, os, time, errno
+from test.script_helper import assert_python_ok
try:
import threading
except ImportError:
@@ -600,12 +601,84 @@ class PendingSignalsTests(unittest.TestCase):
@unittest.skipUnless(hasattr(signal, 'sigwait'),
'need signal.sigwait()')
+ @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
+ 'need signal.pthread_sigmask()')
+ @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork()')
def test_sigwait(self):
- old_handler = signal.signal(signal.SIGALRM, self.handler)
- self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
+ def test(signum):
+ signal.alarm(1)
+ received = signal.sigwait([signum])
+ if received != signum:
+ print("sigwait() received %s, not %s"
+ % (received, signum),
+ file=sys.stderr)
+ os._exit(1)
+
+ signum = signal.SIGALRM
+
+ # sigwait must be called with the signal blocked: since the current
+ # process might have several threads running, we fork() a child process
+ # to have a single thread.
+ pid = os.fork()
+ if pid == 0:
+ # child: block and wait the signal
+ try:
+ signal.signal(signum, self.handler)
+ signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
- signal.alarm(1)
- self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)
+ # Do the tests
+ test(signum)
+
+ # The handler must not be called on unblock
+ try:
+ signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
+ except ZeroDivisionError:
+ print("the signal handler has been called",
+ file=sys.stderr)
+ os._exit(1)
+ except BaseException as err:
+ print("error: {}".format(err), file=sys.stderr)
+ os._exit(1)
+ else:
+ os._exit(0)
+ else:
+ # parent: check that the child correcty received the signal
+ self.assertEqual(os.waitpid(pid, 0), (pid, 0))
+
+ @unittest.skipUnless(hasattr(signal, 'sigwait'),
+ 'need signal.sigwait()')
+ @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
+ 'need signal.pthread_sigmask()')
+ @unittest.skipIf(threading is None, "test needs threading module")
+ def test_sigwait_thread(self):
+ # Check that calling sigwait() from a thread doesn't suspend the whole
+ # process. A new interpreter is spawned to avoid problems when mixing
+ # threads and fork(): only async-safe functions are allowed between
+ # fork() and exec().
+ assert_python_ok("-c", """if True:
+ import os, threading, sys, time, signal
+
+ # the default handler terminates the process
+ signum = signal.SIGUSR1
+
+ def kill_later():
+ # wait until the main thread is waiting in sigwait()
+ time.sleep(1)
+ os.kill(os.getpid(), signum)
+
+ # the signal must be blocked by all the threads
+ signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
+ killer = threading.Thread(target=kill_later)
+ killer.start()
+ received = signal.sigwait([signum])
+ if received != signum:
+ print("sigwait() received %s, not %s" % (received, signum),
+ file=sys.stderr)
+ sys.exit(1)
+ killer.join()
+ # unblock the signal, which should have been cleared by sigwait()
+ signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum])
+ """)
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
'need signal.pthread_sigmask()')
diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
index dfe08fa..1204707 100644
--- a/Lib/test/test_smtplib.py
+++ b/Lib/test/test_smtplib.py
@@ -278,6 +278,21 @@ class DebuggingServerTests(unittest.TestCase):
mexpect = '%s%s\n%s' % (MSG_BEGIN, m.decode('ascii'), MSG_END)
self.assertEqual(self.output.getvalue(), mexpect)
+ def testSendNeedingDotQuote(self):
+ # Issue 12283
+ m = '.A test\n.mes.sage.'
+ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3)
+ smtp.sendmail('John', 'Sally', m)
+ # XXX (see comment in testSend)
+ time.sleep(0.01)
+ smtp.quit()
+
+ self.client_evt.set()
+ self.serv_evt.wait()
+ self.output.flush()
+ mexpect = '%s%s\n%s' % (MSG_BEGIN, m, MSG_END)
+ self.assertEqual(self.output.getvalue(), mexpect)
+
def testSendMessage(self):
m = email.mime.text.MIMEText('A test message')
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3)
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index 7d4ca2c..b52d8e8 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -127,9 +127,10 @@ class ProcessTestCase(BaseTestCase):
with self.assertRaises(subprocess.TimeoutExpired) as c:
output = subprocess.check_output(
[sys.executable, "-c",
- "import sys; sys.stdout.write('BDFL')\n"
+ "import sys, time\n"
+ "sys.stdout.write('BDFL')\n"
"sys.stdout.flush()\n"
- "while True: pass"],
+ "time.sleep(3600)"],
# Some heavily loaded buildbots (sparc Debian 3.x) require
# this much time to start and print.
timeout=3)
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 9663715..4dcb690 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -345,6 +345,24 @@ class TestsWithSourceFile(unittest.TestCase):
with zipfile.ZipFile(f, "r") as zipfp:
self.assertEqual(zipfp.namelist(), [TESTFN])
+ def test_ignores_newline_at_end(self):
+ with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
+ zipfp.write(TESTFN, TESTFN)
+ with open(TESTFN2, 'a') as f:
+ f.write("\r\n\00\00\00")
+ with zipfile.ZipFile(TESTFN2, "r") as zipfp:
+ self.assertIsInstance(zipfp, zipfile.ZipFile)
+
+ def test_ignores_stuff_appended_past_comments(self):
+ with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
+ zipfp.comment = b"this is a comment"
+ zipfp.write(TESTFN, TESTFN)
+ with open(TESTFN2, 'a') as f:
+ f.write("abcdef\r\n")
+ with zipfile.ZipFile(TESTFN2, "r") as zipfp:
+ self.assertIsInstance(zipfp, zipfile.ZipFile)
+ self.assertEqual(zipfp.comment, b"this is a comment")
+
def test_write_default_name(self):
"""Check that calling ZipFile.write without arcname specified
produces the expected result."""
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 50f4848..5cc7816 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -246,16 +246,14 @@ def _EndRecData(fpin):
# found the magic number; attempt to unpack and interpret
recData = data[start:start+sizeEndCentDir]
endrec = list(struct.unpack(structEndArchive, recData))
- comment = data[start+sizeEndCentDir:]
- # check that comment length is correct
- if endrec[_ECD_COMMENT_SIZE] == len(comment):
- # Append the archive comment and start offset
- endrec.append(comment)
- endrec.append(maxCommentStart + start)
-
- # Try to read the "Zip64 end of central directory" structure
- return _EndRecData64(fpin, maxCommentStart + start - filesize,
- endrec)
+ commentSize = endrec[_ECD_COMMENT_SIZE] #as claimed by the zip file
+ comment = data[start+sizeEndCentDir:start+sizeEndCentDir+commentSize]
+ endrec.append(comment)
+ endrec.append(maxCommentStart + start)
+
+ # Try to read the "Zip64 end of central directory" structure
+ return _EndRecData64(fpin, maxCommentStart + start - filesize,
+ endrec)
# Unable to find a valid end of central directory structure
return
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 07486fd..2ca89cf 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -950,7 +950,7 @@ libinstall: build_all $(srcdir)/Lib/$(PLATDIR)
else true; \
fi; \
done
- @for i in $(srcdir)/Lib/*.py $(srcdir)/Lib/*.egg-info $(srcdir)/Lib/*.cfg ; \
+ @for i in $(srcdir)/Lib/*.py $(srcdir)/Lib/*.cfg ; \
do \
if test -x $$i; then \
$(INSTALL_SCRIPT) $$i $(DESTDIR)$(LIBDEST); \
diff --git a/Misc/ACKS b/Misc/ACKS
index 08fc572..163d9b8 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -116,6 +116,7 @@ Monty Brandenberg
Georg Brandl
Christopher Brannon
Terrence Brannon
+Erik Bray
Brian Brazil
Dave Brennan
Tom Bridgman
@@ -548,7 +549,9 @@ Vincent Legoll
Kip Lehman
Joerg Lehmann
Robert Lehmann
+Petri Lehtinen
Luke Kenneth Casson Leighton
+Tshepang Lekhonkhobe
Marc-Andre Lemburg
John Lenton
Christopher Tur Lesniewski-Laas
@@ -643,6 +646,7 @@ James A Morrison
Derek McTavish Mounce
Pablo Mouzo
Mher Movsisyan
+Ruslan Mstoi
Sjoerd Mullender
Sape Mullender
Michael Muller
diff --git a/Misc/NEWS b/Misc/NEWS
index fb7043f..38850c7 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,9 @@ Core and Builtins
- Issue #12084: os.stat on Windows now works properly with relative symbolic
links when called from any directory.
+- Loosen type restrictions on the __dir__ method. __dir__ can now return any
+ sequence, which will be converted to a list and sorted by dir().
+
- Issue #12265: Make error messages produced by passing an invalid set of
arguments to a function more informative.
@@ -190,6 +193,52 @@ Core and Builtins
Library
-------
+- Issue #12240: Allow multiple setup hooks in packaging's setup.cfg files.
+ Original patch by Erik Bray.
+
+- Issue #9284: Allow inspect.findsource() to find the source of doctest
+ functions.
+
+- Issue #11595: Fix assorted bugs in packaging.util.cfg_to_args, a
+ compatibility helper for the distutils-packaging transition. Original patch
+ by Erik Bray.
+
+- Issue #12287: In ossaudiodev, check that the device isn't closed in several
+ methods.
+
+- Issue #12009: Fixed regression in netrc file comment handling.
+
+- Issue #12246: Warn and fail when trying to install a third-party project from
+ an uninstalled Python (built in a source checkout). Original patch by
+ Tshepang Lekhonkhobe.
+
+- Issue #10694: zipfile now ignores garbage at the end of a zipfile.
+
+- Issue #12283: Fixed regression in smtplib quoting of leading dots in DATA.
+
+- Issue #10424: Argparse now includes the names of the missing required
+ arguments in the missing arguments error message.
+
+- Issue #12168: SysLogHandler now allows NUL termination to be controlled using
+ a new 'append_nul' attribute on the handler.
+
+- Issue #11583: Speed up os.path.isdir on Windows by using GetFileAttributes
+ instead of os.stat.
+
+- Issue #12021: Make mmap's read() method argument optional. Patch by Petri
+ Lehtinen.
+
+- Issue #9205: concurrent.futures.ProcessPoolExecutor now detects killed
+ children and raises BrokenProcessPool in such a situation. Previously it
+ would reliably freeze/deadlock.
+
+- Issue #12040: Expose a new attribute ``sentinel`` on instances of
+ :class:`multiprocessing.Process`. Also, fix Process.join() to not use
+ polling anymore, when given a timeout.
+
+- Issue #11893: Remove obsolete internal wrapper class ``SSLFakeFile`` in the
+ smtplib module. Patch by Catalin Iacob.
+
- Issue #12080: Fix a Decimal.power() case that took an unreasonably long time
to compute.
@@ -767,6 +816,12 @@ Library
Build
-----
+- Issue #10645: Installing Python does no longer create a
+ Python-X.Y.Z-pyX.Y.egg-info file in the lib-dynload directory.
+
+- Do not accidentally include the directory containing sqlite.h twice when
+ building sqlite3.
+
- Issue #11217: For 64-bit/32-bit Mac OS X universal framework builds,
ensure "make install" creates symlinks in --prefix bin for the "-32"
files in the framework bin directory like the installer does.
diff --git a/Modules/_multiprocessing/win32_functions.c b/Modules/_multiprocessing/win32_functions.c
index 12dc0cd..c017b2a 100644
--- a/Modules/_multiprocessing/win32_functions.c
+++ b/Modules/_multiprocessing/win32_functions.c
@@ -12,10 +12,223 @@
#define WIN32_FUNCTION(func) \
{#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_STATIC, ""}
+#define WIN32_KWARGS_FUNCTION(func) \
+ {#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_KEYWORDS | METH_STATIC, ""}
+
#define WIN32_CONSTANT(fmt, con) \
PyDict_SetItemString(Win32Type.tp_dict, #con, Py_BuildValue(fmt, con))
+/* Grab CancelIoEx dynamically from kernel32 */
+static int has_CancelIoEx = -1;
+static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
+
+static int
+check_CancelIoEx()
+{
+ if (has_CancelIoEx == -1)
+ {
+ HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
+ * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
+ "CancelIoEx");
+ has_CancelIoEx = (Py_CancelIoEx != NULL);
+ }
+ return has_CancelIoEx;
+}
+
+
+/*
+ * A Python object wrapping an OVERLAPPED structure and other useful data
+ * for overlapped I/O
+ */
+
+typedef struct {
+ PyObject_HEAD
+ OVERLAPPED overlapped;
+ /* For convenience, we store the file handle too */
+ HANDLE handle;
+ /* Whether there's I/O in flight */
+ int pending;
+ /* Whether I/O completed successfully */
+ int completed;
+ /* Buffer used for reading (optional) */
+ PyObject *read_buffer;
+ /* Buffer used for writing (optional) */
+ Py_buffer write_buffer;
+} OverlappedObject;
+
+static void
+overlapped_dealloc(OverlappedObject *self)
+{
+ int err = GetLastError();
+ if (self->pending) {
+ if (check_CancelIoEx())
+ Py_CancelIoEx(self->handle, &self->overlapped);
+ else {
+ PyErr_SetString(PyExc_RuntimeError,
+ "I/O operations still in flight while destroying "
+ "Overlapped object, the process may crash");
+ PyErr_WriteUnraisable(NULL);
+ }
+ }
+ CloseHandle(self->overlapped.hEvent);
+ SetLastError(err);
+ if (self->write_buffer.obj)
+ PyBuffer_Release(&self->write_buffer);
+ Py_CLEAR(self->read_buffer);
+ PyObject_Del(self);
+}
+
+static PyObject *
+overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj)
+{
+ int wait;
+ BOOL res;
+ DWORD transferred = 0;
+
+ wait = PyObject_IsTrue(waitobj);
+ if (wait < 0)
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
+ wait != 0);
+ Py_END_ALLOW_THREADS
+
+ if (!res) {
+ int err = GetLastError();
+ if (err == ERROR_IO_INCOMPLETE)
+ Py_RETURN_NONE;
+ if (err != ERROR_MORE_DATA) {
+ self->pending = 0;
+ return PyErr_SetExcFromWindowsErr(PyExc_IOError, err);
+ }
+ }
+ self->pending = 0;
+ self->completed = 1;
+ if (self->read_buffer) {
+ assert(PyBytes_CheckExact(self->read_buffer));
+ if (_PyBytes_Resize(&self->read_buffer, transferred))
+ return NULL;
+ }
+ return Py_BuildValue("lN", (long) transferred, PyBool_FromLong(res));
+}
+
+static PyObject *
+overlapped_getbuffer(OverlappedObject *self)
+{
+ PyObject *res;
+ if (!self->completed) {
+ PyErr_SetString(PyExc_ValueError,
+ "can't get read buffer before GetOverlappedResult() "
+ "signals the operation completed");
+ return NULL;
+ }
+ res = self->read_buffer ? self->read_buffer : Py_None;
+ Py_INCREF(res);
+ return res;
+}
+
+static PyObject *
+overlapped_cancel(OverlappedObject *self)
+{
+ BOOL res = TRUE;
+
+ if (self->pending) {
+ Py_BEGIN_ALLOW_THREADS
+ if (check_CancelIoEx())
+ res = Py_CancelIoEx(self->handle, &self->overlapped);
+ else
+ res = CancelIo(self->handle);
+ Py_END_ALLOW_THREADS
+ }
+
+ /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
+ if (!res && GetLastError() != ERROR_NOT_FOUND)
+ return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
+ self->pending = 0;
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef overlapped_methods[] = {
+ {"GetOverlappedResult", (PyCFunction) overlapped_GetOverlappedResult,
+ METH_O, NULL},
+ {"getbuffer", (PyCFunction) overlapped_getbuffer, METH_NOARGS, NULL},
+ {"cancel", (PyCFunction) overlapped_cancel, METH_NOARGS, NULL},
+ {NULL}
+};
+
+static PyMemberDef overlapped_members[] = {
+ {"event", T_HANDLE,
+ offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
+ READONLY, "overlapped event handle"},
+ {NULL}
+};
+
+PyTypeObject OverlappedType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ /* tp_name */ "_multiprocessing.win32.Overlapped",
+ /* tp_basicsize */ sizeof(OverlappedObject),
+ /* tp_itemsize */ 0,
+ /* tp_dealloc */ (destructor) overlapped_dealloc,
+ /* tp_print */ 0,
+ /* tp_getattr */ 0,
+ /* tp_setattr */ 0,
+ /* tp_reserved */ 0,
+ /* tp_repr */ 0,
+ /* tp_as_number */ 0,
+ /* tp_as_sequence */ 0,
+ /* tp_as_mapping */ 0,
+ /* tp_hash */ 0,
+ /* tp_call */ 0,
+ /* tp_str */ 0,
+ /* tp_getattro */ 0,
+ /* tp_setattro */ 0,
+ /* tp_as_buffer */ 0,
+ /* tp_flags */ Py_TPFLAGS_DEFAULT,
+ /* tp_doc */ "OVERLAPPED structure wrapper",
+ /* tp_traverse */ 0,
+ /* tp_clear */ 0,
+ /* tp_richcompare */ 0,
+ /* tp_weaklistoffset */ 0,
+ /* tp_iter */ 0,
+ /* tp_iternext */ 0,
+ /* tp_methods */ overlapped_methods,
+ /* tp_members */ overlapped_members,
+ /* tp_getset */ 0,
+ /* tp_base */ 0,
+ /* tp_dict */ 0,
+ /* tp_descr_get */ 0,
+ /* tp_descr_set */ 0,
+ /* tp_dictoffset */ 0,
+ /* tp_init */ 0,
+ /* tp_alloc */ 0,
+ /* tp_new */ 0,
+};
+
+static OverlappedObject *
+new_overlapped(HANDLE handle)
+{
+ OverlappedObject *self;
+
+ self = PyObject_New(OverlappedObject, &OverlappedType);
+ if (!self)
+ return NULL;
+ self->handle = handle;
+ self->read_buffer = NULL;
+ self->pending = 0;
+ self->completed = 0;
+ memset(&self->overlapped, 0, sizeof(OVERLAPPED));
+ memset(&self->write_buffer, 0, sizeof(Py_buffer));
+ /* Manual reset, initially non-signalled */
+ self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ return self;
+}
+
+
+/*
+ * Module functions
+ */
+
static PyObject *
win32_CloseHandle(PyObject *self, PyObject *args)
{
@@ -36,20 +249,44 @@ win32_CloseHandle(PyObject *self, PyObject *args)
}
static PyObject *
-win32_ConnectNamedPipe(PyObject *self, PyObject *args)
+win32_ConnectNamedPipe(PyObject *self, PyObject *args, PyObject *kwds)
{
HANDLE hNamedPipe;
- LPOVERLAPPED lpOverlapped;
+ int use_overlapped = 0;
BOOL success;
+ OverlappedObject *overlapped = NULL;
+ static char *kwlist[] = {"handle", "overlapped", NULL};
- if (!PyArg_ParseTuple(args, F_HANDLE F_POINTER,
- &hNamedPipe, &lpOverlapped))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ F_HANDLE "|i", kwlist,
+ &hNamedPipe, &use_overlapped))
return NULL;
+ if (use_overlapped) {
+ overlapped = new_overlapped(hNamedPipe);
+ if (!overlapped)
+ return NULL;
+ }
+
Py_BEGIN_ALLOW_THREADS
- success = ConnectNamedPipe(hNamedPipe, lpOverlapped);
+ success = ConnectNamedPipe(hNamedPipe,
+ overlapped ? &overlapped->overlapped : NULL);
Py_END_ALLOW_THREADS
+ if (overlapped) {
+ int err = GetLastError();
+ /* Overlapped ConnectNamedPipe never returns a success code */
+ assert(success == 0);
+ if (err == ERROR_IO_PENDING)
+ overlapped->pending = 1;
+ else if (err == ERROR_PIPE_CONNECTED)
+ SetEvent(overlapped->overlapped.hEvent);
+ else {
+ Py_DECREF(overlapped);
+ return PyErr_SetFromWindowsErr(err);
+ }
+ return (PyObject *) overlapped;
+ }
if (!success)
return PyErr_SetFromWindowsErr(0);
@@ -280,46 +517,109 @@ win32_send(PyObject *self, PyObject *args)
}
static PyObject *
-win32_WriteFile(PyObject *self, PyObject *args)
+win32_WriteFile(PyObject *self, PyObject *args, PyObject *kwds)
{
HANDLE handle;
- Py_buffer buf;
+ Py_buffer _buf, *buf;
+ PyObject *bufobj;
int written;
BOOL ret;
+ int use_overlapped = 0;
+ OverlappedObject *overlapped = NULL;
+ static char *kwlist[] = {"handle", "buffer", "overlapped", NULL};
+
+ /* First get handle and use_overlapped to know which Py_buffer to use */
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ F_HANDLE "O|i:WriteFile", kwlist,
+ &handle, &bufobj, &use_overlapped))
+ return NULL;
+
+ if (use_overlapped) {
+ overlapped = new_overlapped(handle);
+ if (!overlapped)
+ return NULL;
+ buf = &overlapped->write_buffer;
+ }
+ else
+ buf = &_buf;
- if (!PyArg_ParseTuple(args, F_HANDLE "y*:WriteFile" , &handle, &buf))
+ if (!PyArg_Parse(bufobj, "y*", buf)) {
+ Py_XDECREF(overlapped);
return NULL;
+ }
Py_BEGIN_ALLOW_THREADS
- ret = WriteFile(handle, buf.buf, buf.len, &written, NULL);
+ ret = WriteFile(handle, buf->buf, buf->len, &written,
+ overlapped ? &overlapped->overlapped : NULL);
Py_END_ALLOW_THREADS
- PyBuffer_Release(&buf);
+ if (overlapped) {
+ int err = GetLastError();
+ if (!ret) {
+ if (err == ERROR_IO_PENDING)
+ overlapped->pending = 1;
+ else {
+ Py_DECREF(overlapped);
+ return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
+ }
+ }
+ return (PyObject *) overlapped;
+ }
+
+ PyBuffer_Release(buf);
if (!ret)
return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
return PyLong_FromLong(written);
}
static PyObject *
-win32_ReadFile(PyObject *self, PyObject *args)
+win32_ReadFile(PyObject *self, PyObject *args, PyObject *kwds)
{
HANDLE handle;
int size;
DWORD nread;
PyObject *buf;
BOOL ret;
+ int use_overlapped = 0;
+ OverlappedObject *overlapped = NULL;
+ static char *kwlist[] = {"handle", "size", "overlapped", NULL};
- if (!PyArg_ParseTuple(args, F_HANDLE "i:ReadFile" , &handle, &size))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ F_HANDLE "i|i:ReadFile", kwlist,
+ &handle, &size, &use_overlapped))
return NULL;
buf = PyBytes_FromStringAndSize(NULL, size);
if (!buf)
return NULL;
+ if (use_overlapped) {
+ overlapped = new_overlapped(handle);
+ if (!overlapped) {
+ Py_DECREF(buf);
+ return NULL;
+ }
+ /* Steals reference to buf */
+ overlapped->read_buffer = buf;
+ }
Py_BEGIN_ALLOW_THREADS
- ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread, NULL);
+ ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
+ overlapped ? &overlapped->overlapped : NULL);
Py_END_ALLOW_THREADS
+ if (overlapped) {
+ int err = GetLastError();
+ if (!ret) {
+ if (err == ERROR_IO_PENDING)
+ overlapped->pending = 1;
+ else if (err != ERROR_MORE_DATA) {
+ Py_DECREF(overlapped);
+ return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
+ }
+ }
+ return (PyObject *) overlapped;
+ }
+
if (!ret && GetLastError() != ERROR_MORE_DATA) {
Py_DECREF(buf);
return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
@@ -373,19 +673,71 @@ win32_PeekNamedPipe(PyObject *self, PyObject *args)
}
}
+static PyObject *
+win32_WaitForMultipleObjects(PyObject* self, PyObject* args)
+{
+ DWORD result;
+ PyObject *handle_seq;
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+ Py_ssize_t nhandles, i;
+ int wait_flag;
+ int milliseconds = INFINITE;
+
+ if (!PyArg_ParseTuple(args, "Oi|i:WaitForMultipleObjects",
+ &handle_seq, &wait_flag, &milliseconds))
+ return NULL;
+
+ if (!PySequence_Check(handle_seq)) {
+ PyErr_Format(PyExc_TypeError,
+ "sequence type expected, got '%s'",
+ Py_TYPE(handle_seq)->tp_doc);
+ return NULL;
+ }
+ nhandles = PySequence_Length(handle_seq);
+ if (nhandles == -1)
+ return NULL;
+ if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS) {
+ PyErr_Format(PyExc_ValueError,
+ "need at most %zd handles, got a sequence of length %zd",
+ MAXIMUM_WAIT_OBJECTS, nhandles);
+ return NULL;
+ }
+ for (i = 0; i < nhandles; i++) {
+ HANDLE h;
+ PyObject *v = PySequence_GetItem(handle_seq, i);
+ if (v == NULL)
+ return NULL;
+ if (!PyArg_Parse(v, F_HANDLE, &h))
+ return NULL;
+ handles[i] = h;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ result = WaitForMultipleObjects((DWORD) nhandles, handles,
+ (BOOL) wait_flag, (DWORD) milliseconds);
+ Py_END_ALLOW_THREADS
+
+ if (result == WAIT_FAILED)
+ return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
+
+ return PyLong_FromLong((int) result);
+}
+
+
static PyMethodDef win32_methods[] = {
WIN32_FUNCTION(CloseHandle),
WIN32_FUNCTION(GetLastError),
WIN32_FUNCTION(OpenProcess),
WIN32_FUNCTION(ExitProcess),
- WIN32_FUNCTION(ConnectNamedPipe),
+ WIN32_KWARGS_FUNCTION(ConnectNamedPipe),
WIN32_FUNCTION(CreateFile),
WIN32_FUNCTION(CreateNamedPipe),
- WIN32_FUNCTION(ReadFile),
+ WIN32_KWARGS_FUNCTION(ReadFile),
WIN32_FUNCTION(PeekNamedPipe),
WIN32_FUNCTION(SetNamedPipeHandleState),
+ WIN32_FUNCTION(WaitForMultipleObjects),
WIN32_FUNCTION(WaitNamedPipe),
- WIN32_FUNCTION(WriteFile),
+ WIN32_KWARGS_FUNCTION(WriteFile),
WIN32_FUNCTION(closesocket),
WIN32_FUNCTION(recv),
WIN32_FUNCTION(send),
@@ -407,12 +759,18 @@ create_win32_namespace(void)
return NULL;
Py_INCREF(&Win32Type);
+ if (PyType_Ready(&OverlappedType) < 0)
+ return NULL;
+ PyDict_SetItemString(Win32Type.tp_dict, "Overlapped",
+ (PyObject *) &OverlappedType);
+
WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
WIN32_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
WIN32_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
+ WIN32_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
WIN32_CONSTANT(F_DWORD, GENERIC_READ);
WIN32_CONSTANT(F_DWORD, GENERIC_WRITE);
WIN32_CONSTANT(F_DWORD, INFINITE);
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 533f404..ae68c15 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -2091,7 +2091,7 @@ array_repr(arrayobject *a)
if (len == 0) {
return PyUnicode_FromFormat("array('%c')", (int)typecode);
}
- if ((typecode == 'u'))
+ if (typecode == 'u')
v = array_tounicode(a, NULL);
else
v = array_tolist(a, NULL);
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 36ca67d..ab12e2c 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -240,15 +240,37 @@ mmap_read_line_method(mmap_object *self,
return result;
}
+/* Basically the "n" format code with the ability to turn None into -1. */
+static int
+mmap_convert_ssize_t(PyObject *obj, void *result) {
+ Py_ssize_t limit;
+ if (obj == Py_None) {
+ limit = -1;
+ }
+ else if (PyNumber_Check(obj)) {
+ limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
+ if (limit == -1 && PyErr_Occurred())
+ return 0;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "integer argument expected, got '%.200s'",
+ Py_TYPE(obj)->tp_name);
+ return 0;
+ }
+ *((Py_ssize_t *)result) = limit;
+ return 1;
+}
+
static PyObject *
mmap_read_method(mmap_object *self,
PyObject *args)
{
- Py_ssize_t num_bytes, n;
+ Py_ssize_t num_bytes = -1, n;
PyObject *result;
CHECK_VALID(NULL);
- if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
+ if (!PyArg_ParseTuple(args, "|O&:read", mmap_convert_ssize_t, &num_bytes))
return(NULL);
/* silently 'adjust' out-of-range requests */
@@ -645,9 +667,9 @@ mmap_move_method(mmap_object *self, PyObject *args)
return NULL;
} else {
/* bounds check the values */
- if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
- src < 0 || src > self->size || (src + cnt) > self->size ||
- dest < 0 || dest > self->size || (dest + cnt) > self->size) {
+ if ((cnt + dest) < cnt || (cnt + src) < cnt ||
+ src > self->size || (src + cnt) > self->size ||
+ dest > self->size || (dest + cnt) > self->size) {
PyErr_SetString(PyExc_ValueError,
"source, destination, or count out of range");
return NULL;
diff --git a/Modules/nismodule.c b/Modules/nismodule.c
index a81ca8c..0af495f 100644
--- a/Modules/nismodule.c
+++ b/Modules/nismodule.c
@@ -411,7 +411,7 @@ nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
return NULL;
if ((list = PyList_New(0)) == NULL)
return NULL;
- for (maps = maps; maps; maps = maps->next) {
+ for (; maps; maps = maps->next) {
PyObject *str = PyUnicode_FromString(maps->map);
if (!str || PyList_Append(list, str) < 0)
{
diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c
index e660e50..1505731 100644
--- a/Modules/ossaudiodev.c
+++ b/Modules/ossaudiodev.c
@@ -213,6 +213,21 @@ oss_mixer_dealloc(oss_mixer_t *self)
* Helper functions
*/
+/* Check if a given file descriptor is valid (i.e. hasn't been closed).
+ * If true, return 1. Otherwise, raise ValueError and return 0.
+ */
+static int _is_fd_valid(int fd)
+{
+ /* the FD is set to -1 in oss_close()/oss_mixer_close() */
+ if (fd >= 0) {
+ return 1;
+ } else {
+ PyErr_SetString(PyExc_ValueError,
+ "Operation on closed OSS device.");
+ return 0;
+ }
+}
+
/* _do_ioctl_1() is a private helper function used for the OSS ioctls --
SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C
like this:
@@ -300,6 +315,9 @@ _do_ioctl_0(int fd, PyObject *args, char *fname, int cmd)
static PyObject *
oss_nonblock(oss_audio_t *self, PyObject *unused)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
/* Hmmm: it doesn't appear to be possible to return to blocking
mode once we're in non-blocking mode! */
if (ioctl(self->fd, SNDCTL_DSP_NONBLOCK, NULL) == -1)
@@ -311,6 +329,9 @@ oss_nonblock(oss_audio_t *self, PyObject *unused)
static PyObject *
oss_setfmt(oss_audio_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1(self->fd, args, "setfmt", SNDCTL_DSP_SETFMT);
}
@@ -318,6 +339,10 @@ static PyObject *
oss_getfmts(oss_audio_t *self, PyObject *unused)
{
int mask;
+
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (ioctl(self->fd, SNDCTL_DSP_GETFMTS, &mask) == -1)
return PyErr_SetFromErrno(PyExc_IOError);
return PyLong_FromLong(mask);
@@ -326,30 +351,45 @@ oss_getfmts(oss_audio_t *self, PyObject *unused)
static PyObject *
oss_channels(oss_audio_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1(self->fd, args, "channels", SNDCTL_DSP_CHANNELS);
}
static PyObject *
oss_speed(oss_audio_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1(self->fd, args, "speed", SNDCTL_DSP_SPEED);
}
static PyObject *
oss_sync(oss_audio_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_0(self->fd, args, "sync", SNDCTL_DSP_SYNC);
}
static PyObject *
oss_reset(oss_audio_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_0(self->fd, args, "reset", SNDCTL_DSP_RESET);
}
static PyObject *
oss_post(oss_audio_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_0(self->fd, args, "post", SNDCTL_DSP_POST);
}
@@ -364,6 +404,9 @@ oss_read(oss_audio_t *self, PyObject *args)
char *cp;
PyObject *rv;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (!PyArg_ParseTuple(args, "i:read", &size))
return NULL;
rv = PyBytes_FromStringAndSize(NULL, size);
@@ -391,6 +434,9 @@ oss_write(oss_audio_t *self, PyObject *args)
char *cp;
int rv, size;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) {
return NULL;
}
@@ -422,6 +468,9 @@ oss_writeall(oss_audio_t *self, PyObject *args)
mode, the behaviour of write() and writeall() from Python is
indistinguishable. */
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size))
return NULL;
@@ -489,6 +538,9 @@ oss_exit(PyObject *self, PyObject *unused)
static PyObject *
oss_fileno(oss_audio_t *self, PyObject *unused)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return PyLong_FromLong(self->fd);
}
@@ -503,6 +555,9 @@ oss_setparameters(oss_audio_t *self, PyObject *args)
int fmt, channels, rate;
PyObject * rv; /* return tuple (fmt, channels, rate) */
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (!PyArg_ParseTuple(args, "iii|i:setparameters",
&wanted_fmt, &wanted_channels, &wanted_rate,
&strict))
@@ -593,6 +648,9 @@ oss_bufsize(oss_audio_t *self, PyObject *unused)
audio_buf_info ai;
int nchannels=0, ssize=0;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
@@ -612,6 +670,9 @@ oss_obufcount(oss_audio_t *self, PyObject *unused)
audio_buf_info ai;
int nchannels=0, ssize=0;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
@@ -632,6 +693,9 @@ oss_obuffree(oss_audio_t *self, PyObject *unused)
audio_buf_info ai;
int nchannels=0, ssize=0;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
@@ -649,6 +713,9 @@ oss_getptr(oss_audio_t *self, PyObject *unused)
count_info info;
int req;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
if (self->mode == O_RDONLY)
req = SNDCTL_DSP_GETIPTR;
else
@@ -679,6 +746,9 @@ oss_mixer_close(oss_mixer_t *self, PyObject *unused)
static PyObject *
oss_mixer_fileno(oss_mixer_t *self, PyObject *unused)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return PyLong_FromLong(self->fd);
}
@@ -687,6 +757,9 @@ oss_mixer_fileno(oss_mixer_t *self, PyObject *unused)
static PyObject *
oss_mixer_controls(oss_mixer_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1_internal(self->fd, args, "controls",
SOUND_MIXER_READ_DEVMASK);
}
@@ -694,6 +767,9 @@ oss_mixer_controls(oss_mixer_t *self, PyObject *args)
static PyObject *
oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1_internal(self->fd, args, "stereocontrols",
SOUND_MIXER_READ_STEREODEVS);
}
@@ -701,6 +777,9 @@ oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args)
static PyObject *
oss_mixer_reccontrols(oss_mixer_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1_internal(self->fd, args, "reccontrols",
SOUND_MIXER_READ_RECMASK);
}
@@ -710,6 +789,9 @@ oss_mixer_get(oss_mixer_t *self, PyObject *args)
{
int channel, volume;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
/* Can't use _do_ioctl_1 because of encoded arg thingy. */
if (!PyArg_ParseTuple(args, "i:get", &channel))
return NULL;
@@ -730,6 +812,9 @@ oss_mixer_set(oss_mixer_t *self, PyObject *args)
{
int channel, volume, leftVol, rightVol;
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
/* Can't use _do_ioctl_1 because of encoded arg thingy. */
if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol))
return NULL;
@@ -755,6 +840,9 @@ oss_mixer_set(oss_mixer_t *self, PyObject *args)
static PyObject *
oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1_internal(self->fd, args, "get_recsrc",
SOUND_MIXER_READ_RECSRC);
}
@@ -762,6 +850,9 @@ oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
static PyObject *
oss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args)
{
+ if (!_is_fd_valid(self->fd))
+ return NULL;
+
return _do_ioctl_1(self->fd, args, "set_recsrc",
SOUND_MIXER_WRITE_RECSRC);
}
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 518fa1e..14d18bc 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -3007,6 +3007,45 @@ posix__getfileinformation(PyObject *self, PyObject *args)
info.nFileIndexHigh,
info.nFileIndexLow);
}
+
+PyDoc_STRVAR(posix__isdir__doc__,
+"Return true if the pathname refers to an existing directory.");
+
+static PyObject *
+posix__isdir(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ PyUnicodeObject *po;
+ DWORD attributes;
+
+ if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
+ Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
+
+ attributes = GetFileAttributesW(wpath);
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ Py_RETURN_FALSE;
+ goto check;
+ }
+ /* Drop the argument parsing error as narrow strings
+ are also valid. */
+ PyErr_Clear();
+
+ if (!PyArg_ParseTuple(args, "O&:_isdir",
+ PyUnicode_FSConverter, &opath))
+ return NULL;
+
+ path = PyBytes_AsString(opath);
+ attributes = GetFileAttributesA(path);
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ Py_RETURN_FALSE;
+
+check:
+ if (attributes & FILE_ATTRIBUTE_DIRECTORY)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
#endif /* MS_WINDOWS */
PyDoc_STRVAR(posix_mkdir__doc__,
@@ -4680,6 +4719,70 @@ posix_getpid(PyObject *self, PyObject *noargs)
return PyLong_FromPid(getpid());
}
+#ifdef HAVE_GETGROUPLIST
+PyDoc_STRVAR(posix_getgrouplist__doc__,
+"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
+Returns a list of groups to which a user belongs.\n\n\
+ user: username to lookup\n\
+ group: base group id of the user");
+
+static PyObject *
+posix_getgrouplist(PyObject *self, PyObject *args)
+{
+#ifdef NGROUPS_MAX
+#define MAX_GROUPS NGROUPS_MAX
+#else
+ /* defined to be 16 on Solaris7, so this should be a small number */
+#define MAX_GROUPS 64
+#endif
+
+ const char *user;
+ int i, ngroups;
+ PyObject *list;
+#ifdef __APPLE__
+ int *groups, basegid;
+#else
+ gid_t *groups, basegid;
+#endif
+ ngroups = MAX_GROUPS;
+
+ if (!PyArg_ParseTuple(args, "si", &user, &basegid))
+ return NULL;
+
+#ifdef __APPLE__
+ groups = PyMem_Malloc(ngroups * sizeof(int));
+#else
+ groups = PyMem_Malloc(ngroups * sizeof(gid_t));
+#endif
+ if (groups == NULL)
+ return PyErr_NoMemory();
+
+ if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
+ PyMem_Del(groups);
+ return posix_error();
+ }
+
+ list = PyList_New(ngroups);
+ if (list == NULL) {
+ PyMem_Del(groups);
+ return NULL;
+ }
+
+ for (i = 0; i < ngroups; i++) {
+ PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
+ if (o == NULL) {
+ Py_DECREF(list);
+ PyMem_Del(groups);
+ return NULL;
+ }
+ PyList_SET_ITEM(list, i, o);
+ }
+
+ PyMem_Del(groups);
+
+ return list;
+}
+#endif
#ifdef HAVE_GETGROUPS
PyDoc_STRVAR(posix_getgroups__doc__,
@@ -6596,20 +6699,21 @@ posix_pipe(PyObject *self, PyObject *noargs)
#ifdef HAVE_PIPE2
PyDoc_STRVAR(posix_pipe2__doc__,
-"pipe2(flags=0) -> (read_end, write_end)\n\n\
-Create a pipe with flags set atomically.\
-flags is optional and can be constructed by ORing together zero or more\n\
-of these values: O_NONBLOCK, O_CLOEXEC.\n\
+"pipe2(flags) -> (read_end, write_end)\n\n\
+Create a pipe with flags set atomically.\n\
+flags can be constructed by ORing together one or more of these values:\n\
+O_NONBLOCK, O_CLOEXEC.\n\
");
static PyObject *
-posix_pipe2(PyObject *self, PyObject *args)
+posix_pipe2(PyObject *self, PyObject *arg)
{
- int flags = 0;
+ int flags;
int fds[2];
int res;
- if (!PyArg_ParseTuple(args, "|i:pipe2", &flags))
+ flags = PyLong_AsLong(arg);
+ if (flags == -1 && PyErr_Occurred())
return NULL;
res = pipe2(fds, flags);
@@ -9390,6 +9494,9 @@ static PyMethodDef posix_methods[] = {
#ifdef HAVE_GETGID
{"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__},
#endif /* HAVE_GETGID */
+#ifdef HAVE_GETGROUPLIST
+ {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
+#endif
#ifdef HAVE_GETGROUPS
{"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
#endif
@@ -9514,7 +9621,7 @@ static PyMethodDef posix_methods[] = {
{"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
#endif
#ifdef HAVE_PIPE2
- {"pipe2", posix_pipe2, METH_VARARGS, posix_pipe2__doc__},
+ {"pipe2", posix_pipe2, METH_O, posix_pipe2__doc__},
#endif
#ifdef HAVE_MKFIFO
{"mkfifo", posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
@@ -9607,6 +9714,7 @@ static PyMethodDef posix_methods[] = {
{"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL},
{"_getfinalpathname", posix__getfinalpathname, METH_VARARGS, NULL},
{"_getfileinformation", posix__getfileinformation, METH_VARARGS, NULL},
+ {"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__},
#endif
#ifdef HAVE_GETLOADAVG
{"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 6d27ab3..94e6bcb 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -662,7 +662,9 @@ signal_sigwait(PyObject *self, PyObject *args)
if (iterable_to_sigset(signals, &set))
return NULL;
+ Py_BEGIN_ALLOW_THREADS
err = sigwait(&set, &signum);
+ Py_END_ALLOW_THREADS
if (err) {
errno = err;
return PyErr_SetFromErrno(PyExc_OSError);
diff --git a/Objects/object.c b/Objects/object.c
index e42c1d9..05c52f1 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1,5 +1,5 @@
-/* Generic object operations; and implementation of None (NoObject) */
+/* Generic object operations; and implementation of None */
#include "Python.h"
#include "frameobject.h"
@@ -1205,6 +1205,10 @@ _dir_locals(void)
Py_DECREF(names);
return NULL;
}
+ if (PyList_Sort(names)) {
+ Py_DECREF(names);
+ return NULL;
+ }
/* the locals don't need to be DECREF'd */
return names;
}
@@ -1213,7 +1217,7 @@ _dir_locals(void)
static PyObject *
_dir_object(PyObject *obj)
{
- PyObject *result;
+ PyObject *result, *sorted;
static PyObject *dir_str = NULL;
PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str);
@@ -1228,18 +1232,16 @@ _dir_object(PyObject *obj)
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;
+ /* return sorted(result) */
+ sorted = PySequence_List(result);
+ Py_DECREF(result);
+ if (sorted == NULL)
+ return NULL;
+ if (PyList_Sort(sorted)) {
+ Py_DECREF(sorted);
+ return NULL;
}
-
- return result;
+ return sorted;
}
/* Implementation of dir() -- if obj is NULL, returns the names in the current
@@ -1249,31 +1251,13 @@ _dir_object(PyObject *obj)
PyObject *
PyObject_Dir(PyObject *obj)
{
- PyObject * result;
-
- if (obj == NULL)
- /* no object -- introspect the locals */
- result = _dir_locals();
- else
- /* object -- introspect the object */
- result = _dir_object(obj);
-
- assert(result == NULL || PyList_Check(result));
-
- if (result != NULL && PyList_Sort(result) != 0) {
- /* sorting the list failed */
- Py_DECREF(result);
- result = NULL;
- }
-
- return result;
+ return (obj == NULL) ? _dir_locals() : _dir_object(obj);
}
/*
-NoObject is usable as a non-NULL undefined value, used by the macro None.
+None is as a non-NULL undefined value.
There is (and should be!) no way to create other objects of this type,
so there is exactly one (which is indestructible, by the way).
-(XXX This type and the type of NotImplemented below should be unified.)
*/
/* ARGSUSED */
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index 9869f6a..932a637 100644
--- a/Python/dynload_win.c
+++ b/Python/dynload_win.c
@@ -185,28 +185,19 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname,
{
HINSTANCE hDLL = NULL;
- wchar_t pathbuf[260];
unsigned int old_mode;
ULONG_PTR cookie = 0;
- /* We use LoadLibraryEx so Windows looks for dependent DLLs
- in directory of pathname first. However, Windows95
- can sometimes not work correctly unless the absolute
- path is used. If GetFullPathName() fails, the LoadLibrary
- will certainly fail too, so use its error code */
-
+
/* Don't display a message box when Python can't load a DLL */
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
- if (GetFullPathNameW(PyUnicode_AS_UNICODE(pathname),
- sizeof(pathbuf) / sizeof(pathbuf[0]),
- pathbuf,
- NULL)) {
- ULONG_PTR cookie = _Py_ActivateActCtx();
- /* XXX This call doesn't exist in Windows CE */
- hDLL = LoadLibraryExW(PyUnicode_AS_UNICODE(pathname), NULL,
- LOAD_WITH_ALTERED_SEARCH_PATH);
- _Py_DeactivateActCtx(cookie);
- }
+ cookie = _Py_ActivateActCtx();
+ /* We use LoadLibraryEx so Windows looks for dependent DLLs
+ in directory of pathname first. */
+ /* XXX This call doesn't exist in Windows CE */
+ hDLL = LoadLibraryExW(PyUnicode_AS_UNICODE(pathname), NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH);
+ _Py_DeactivateActCtx(cookie);
/* restore old error mode settings */
SetErrorMode(old_mode);
diff --git a/configure b/configure
index ab12eb5..7540e36 100755
--- a/configure
+++ b/configure
@@ -1,13 +1,13 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.65 for python 3.3.
+# Generated by GNU Autoconf 2.67 for python 3.3.
#
# Report bugs to <http://bugs.python.org/>.
#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -319,7 +319,7 @@ $as_echo X"$as_dir" |
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
@@ -359,19 +359,19 @@ else
fi # as_fn_arith
-# as_fn_error ERROR [LINENO LOG_FD]
-# ---------------------------------
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with status $?, using 1 if that was 0.
+# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
- as_status=$?; test $as_status -eq 0 && as_status=1
- if test "$3"; then
- as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $1" >&2
+ $as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -533,7 +533,7 @@ test -n "$DJDIR" || exec 7<&0 </dev/null
exec 6>&1
# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
@@ -833,8 +833,9 @@ do
fi
case $ac_option in
- *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
- *) ac_optarg=yes ;;
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
@@ -879,7 +880,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -905,7 +906,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1109,7 +1110,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1125,7 +1126,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1155,8 +1156,8 @@ do
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
- -*) as_fn_error "unrecognized option: \`$ac_option'
-Try \`$0 --help' for more information."
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
;;
*=*)
@@ -1164,7 +1165,7 @@ Try \`$0 --help' for more information."
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
- as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
@@ -1182,13 +1183,13 @@ done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- as_fn_error "missing argument to $ac_option"
+ as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
- fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
*) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1211,7 +1212,7 @@ do
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
- as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
@@ -1225,8 +1226,8 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
- $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
@@ -1241,9 +1242,9 @@ test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
- as_fn_error "working directory cannot be determined"
+ as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
- as_fn_error "pwd does not report name of working directory"
+ as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
@@ -1282,11 +1283,11 @@ else
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
- as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
- cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
@@ -1326,7 +1327,7 @@ Configuration:
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking...' messages
+ -q, --quiet, --silent do not print \`checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for \`--cache-file=config.cache'
-n, --no-create do not create output files
@@ -1511,9 +1512,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
python configure 3.3
-generated by GNU Autoconf 2.65
+generated by GNU Autoconf 2.67
-Copyright (C) 2009 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1629,7 +1630,7 @@ $as_echo "$ac_try_echo"; } >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } >/dev/null && {
+ test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}; then :
@@ -1653,10 +1654,10 @@ fi
ac_fn_c_check_header_mongrel ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ if eval "test \"\${$3+set}\"" = set; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
@@ -1692,7 +1693,7 @@ if ac_fn_c_try_cpp "$LINENO"; then :
else
ac_header_preproc=no
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }
@@ -1715,17 +1716,15 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( cat <<\_ASBOX
-## -------------------------------------- ##
+( $as_echo "## -------------------------------------- ##
## Report this to http://bugs.python.org/ ##
-## -------------------------------------- ##
-_ASBOX
+## -------------------------------------- ##"
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
eval "$3=\$ac_header_compiler"
@@ -1789,7 +1788,7 @@ ac_fn_c_check_header_compile ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1820,7 +1819,7 @@ ac_fn_c_check_type ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
eval "$3=no"
@@ -1874,7 +1873,7 @@ ac_fn_c_find_uintX_t ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
$as_echo_n "checking for uint$2_t... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
eval "$3=no"
@@ -1904,8 +1903,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- eval as_val=\$$3
- if test "x$as_val" = x""no; then :
+ if eval test \"x\$"$3"\" = x"no"; then :
else
break
@@ -1928,7 +1926,7 @@ ac_fn_c_find_intX_t ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
$as_echo_n "checking for int$2_t... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
eval "$3=no"
@@ -1979,8 +1977,7 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- eval as_val=\$$3
- if test "x$as_val" = x""no; then :
+ if eval test \"x\$"$3"\" = x"no"; then :
else
break
@@ -2180,7 +2177,7 @@ ac_fn_c_check_func ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2248,7 +2245,7 @@ ac_fn_c_check_member ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
$as_echo_n "checking for $2.$3... " >&6; }
-if { as_var=$4; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$4+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2296,15 +2293,18 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_c_check_member
-# ac_fn_c_check_decl LINENO SYMBOL VAR
-# ------------------------------------
-# Tests whether SYMBOL is declared, setting cache variable VAR accordingly.
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
ac_fn_c_check_decl ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
-$as_echo_n "checking whether $2 is declared... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2313,8 +2313,12 @@ $4
int
main ()
{
-#ifndef $2
- (void) $2;
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
#endif
;
@@ -2339,7 +2343,7 @@ This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by python $as_me 3.3, which was
-generated by GNU Autoconf 2.65. Invocation command line was
+generated by GNU Autoconf 2.67. Invocation command line was
$ $0 $@
@@ -2449,11 +2453,9 @@ trap 'exit_status=$?
{
echo
- cat <<\_ASBOX
-## ---------------- ##
+ $as_echo "## ---------------- ##
## Cache variables. ##
-## ---------------- ##
-_ASBOX
+## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
@@ -2487,11 +2489,9 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- cat <<\_ASBOX
-## ----------------- ##
+ $as_echo "## ----------------- ##
## Output variables. ##
-## ----------------- ##
-_ASBOX
+## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
@@ -2504,11 +2504,9 @@ _ASBOX
echo
if test -n "$ac_subst_files"; then
- cat <<\_ASBOX
-## ------------------- ##
+ $as_echo "## ------------------- ##
## File substitutions. ##
-## ------------------- ##
-_ASBOX
+## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
@@ -2522,11 +2520,9 @@ _ASBOX
fi
if test -s confdefs.h; then
- cat <<\_ASBOX
-## ----------- ##
+ $as_echo "## ----------- ##
## confdefs.h. ##
-## ----------- ##
-_ASBOX
+## ----------- ##"
echo
cat confdefs.h
echo
@@ -2581,7 +2577,12 @@ _ACEOF
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- ac_site_file1=$CONFIG_SITE
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
elif test "x$prefix" != xNONE; then
ac_site_file1=$prefix/share/config.site
ac_site_file2=$prefix/etc/config.site
@@ -2596,7 +2597,11 @@ do
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file"
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
done
@@ -2672,7 +2677,7 @@ if $ac_cache_corrupted; then
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2832,7 +2837,7 @@ if test "${enable_universalsdk+set}" = set; then :
UNIVERSALSDK=$enableval
if test ! -d "${UNIVERSALSDK}"
then
- as_fn_error "--enable-universalsdk specifies non-existing SDK: ${UNIVERSALSDK}" "$LINENO" 5
+ as_fn_error $? "--enable-universalsdk specifies non-existing SDK: ${UNIVERSALSDK}" "$LINENO" 5
fi
;;
esac
@@ -3224,7 +3229,7 @@ $as_echo "$without_gcc" >&6; }
# If the user switches compilers, we can't believe the cache
if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC"
then
- as_fn_error "cached CC is different -- throw away $cache_file
+ as_fn_error $? "cached CC is different -- throw away $cache_file
(it is also a good idea to do 'make clean' before compiling)" "$LINENO" 5
fi
@@ -3534,8 +3539,8 @@ fi
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "no acceptable C compiler found in \$PATH
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5 ; }
# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -3649,9 +3654,8 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "C compiler cannot create executables
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5 ; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -3693,8 +3697,8 @@ done
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -3751,9 +3755,9 @@ $as_echo "$ac_try_echo"; } >&5
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot run C compiled programs.
+as_fn_error $? "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
fi
fi
@@ -3804,8 +3808,8 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
@@ -4288,7 +4292,7 @@ else
# Broken: fails on valid input.
continue
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
@@ -4304,11 +4308,11 @@ else
ac_preproc_ok=:
break
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
break
fi
@@ -4347,7 +4351,7 @@ else
# Broken: fails on valid input.
continue
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
@@ -4363,18 +4367,18 @@ else
ac_preproc_ok=:
break
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." "$LINENO" 5; }
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
ac_ext=c
@@ -4435,7 +4439,7 @@ esac
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_GREP"; then
- as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_GREP=$GREP
@@ -4501,7 +4505,7 @@ esac
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
- as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
@@ -4633,8 +4637,7 @@ do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
@@ -5252,16 +5255,22 @@ bsdos*|hp*|HP*)
esac
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- for ac_t in install-sh install.sh shtool; do
- if test -f "$ac_dir/$ac_t"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/$ac_t -c"
- break 2
- fi
- done
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
done
if test -z "$ac_aux_dir"; then
- as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
fi
# These three variables are undocumented and unsupported,
@@ -5599,7 +5608,7 @@ $as_echo "$CC" >&6; }
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
else
- as_fn_error "proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way" "$LINENO" 5
+ as_fn_error $? "proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way" "$LINENO" 5
fi
@@ -6087,8 +6096,7 @@ bluetooth/bluetooth.h linux/tipc.h spawn.h util.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
@@ -6102,7 +6110,7 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then :
+if eval "test \"\${$as_ac_Header+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -6129,8 +6137,7 @@ fi
eval ac_res=\$$as_ac_Header
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
_ACEOF
@@ -6655,9 +6662,8 @@ else
if test "$ac_cv_type_int" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (int)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (int)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_int=0
fi
@@ -6689,9 +6695,8 @@ else
if test "$ac_cv_type_long" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (long)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (long)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_long=0
fi
@@ -6723,9 +6728,8 @@ else
if test "$ac_cv_type_void_p" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (void *)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (void *)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_void_p=0
fi
@@ -6757,9 +6761,8 @@ else
if test "$ac_cv_type_short" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (short)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (short)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_short=0
fi
@@ -6791,9 +6794,8 @@ else
if test "$ac_cv_type_float" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (float)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (float)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_float=0
fi
@@ -6825,9 +6827,8 @@ else
if test "$ac_cv_type_double" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (double)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (double)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_double=0
fi
@@ -6859,9 +6860,8 @@ else
if test "$ac_cv_type_fpos_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (fpos_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (fpos_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_fpos_t=0
fi
@@ -6893,9 +6893,8 @@ else
if test "$ac_cv_type_size_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (size_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (size_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_size_t=0
fi
@@ -6927,9 +6926,8 @@ else
if test "$ac_cv_type_pid_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (pid_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (pid_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_pid_t=0
fi
@@ -6988,9 +6986,8 @@ else
if test "$ac_cv_type_long_long" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (long long)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (long long)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_long_long=0
fi
@@ -7050,9 +7047,8 @@ else
if test "$ac_cv_type_long_double" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (long double)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (long double)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_long_double=0
fi
@@ -7113,9 +7109,8 @@ else
if test "$ac_cv_type__Bool" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (_Bool)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (_Bool)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof__Bool=0
fi
@@ -7162,9 +7157,8 @@ else
if test "$ac_cv_type_uintptr_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (uintptr_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (uintptr_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_uintptr_t=0
fi
@@ -7204,9 +7198,8 @@ else
if test "$ac_cv_type_off_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (off_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (off_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_off_t=0
fi
@@ -7267,9 +7260,8 @@ else
if test "$ac_cv_type_time_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (time_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (time_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_time_t=0
fi
@@ -7340,9 +7332,8 @@ else
if test "$ac_cv_type_pthread_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (pthread_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (pthread_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_pthread_t=0
fi
@@ -7429,7 +7420,7 @@ fi
MACOSX_DEFAULT_ARCH="ppc"
;;
*)
- as_fn_error "Unexpected output of 'arch' on OSX" "$LINENO" 5
+ as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
;;
esac
else
@@ -7441,7 +7432,7 @@ fi
MACOSX_DEFAULT_ARCH="ppc64"
;;
*)
- as_fn_error "Unexpected output of 'arch' on OSX" "$LINENO" 5
+ as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
;;
esac
@@ -7467,7 +7458,7 @@ $as_echo "#define WITH_NEXT_FRAMEWORK 1" >>confdefs.h
$as_echo "yes" >&6; }
if test $enable_shared = "yes"
then
- as_fn_error "Specifying both --enable-shared and --enable-framework is not supported, use only --enable-framework instead" "$LINENO" 5
+ as_fn_error $? "Specifying both --enable-shared and --enable-framework is not supported, use only --enable-framework instead" "$LINENO" 5
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
@@ -8307,12 +8298,12 @@ if test "${with_dbmliborder+set}" = set; then :
withval=$with_dbmliborder;
if test x$with_dbmliborder = xyes
then
-as_fn_error "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5
+as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5
else
for db in `echo $with_dbmliborder | sed 's/:/ /g'`; do
if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb
then
- as_fn_error "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5
+ as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5
fi
done
fi
@@ -9285,7 +9276,7 @@ if test "x$ac_cv_header_valgrind_valgrind_h" = x""yes; then :
$as_echo "#define WITH_VALGRIND 1" >>confdefs.h
else
- as_fn_error "Valgrind support requested but headers not available" "$LINENO" 5
+ as_fn_error $? "Valgrind support requested but headers not available" "$LINENO" 5
fi
@@ -9365,8 +9356,8 @@ $as_echo "MACHDEP_OBJS" >&6; }
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
clock confstr ctermid execv faccessat fchmod fchmodat fchown fchownat \
fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
- futimens futimes \
- gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \
+ futimens futimes gai_strerror \
+ getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
if_nameindex \
initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mbrtowc mkdirat mkfifo \
@@ -9384,8 +9375,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
@@ -10408,8 +10398,7 @@ for ac_func in fseek64 fseeko fstatvfs ftell64 ftello statvfs
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
@@ -10418,25 +10407,44 @@ fi
done
-for ac_func in dup2 getcwd strdup
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "dup2" "ac_cv_func_dup2"
+if test "x$ac_cv_func_dup2" = x""yes; then :
+ $as_echo "#define HAVE_DUP2 1" >>confdefs.h
else
case " $LIBOBJS " in
- *" $ac_func.$ac_objext "* ) ;;
- *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext"
+ *" dup2.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS dup2.$ac_objext"
+ ;;
+esac
+
+fi
+
+ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
+if test "x$ac_cv_func_getcwd" = x""yes; then :
+ $as_echo "#define HAVE_GETCWD 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" getcwd.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getcwd.$ac_objext"
+ ;;
+esac
+
+fi
+
+ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup"
+if test "x$ac_cv_func_strdup" = x""yes; then :
+ $as_echo "#define HAVE_STRDUP 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" strdup.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strdup.$ac_objext"
;;
esac
fi
-done
for ac_func in getpgrp
@@ -11649,7 +11657,7 @@ elif test "$withval" != yes
then LIBM=$withval
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: set LIBM=\"$withval\"" >&5
$as_echo "set LIBM=\"$withval\"" >&6; }
-else as_fn_error "proper usage is --with-libm=STRING" "$LINENO" 5
+else as_fn_error $? "proper usage is --with-libm=STRING" "$LINENO" 5
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: default LIBM=\"$LIBM\"" >&5
@@ -11673,7 +11681,7 @@ elif test "$withval" != yes
then LIBC=$withval
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: set LIBC=\"$withval\"" >&5
$as_echo "set LIBC=\"$withval\"" >&6; }
-else as_fn_error "proper usage is --with-libc=STRING" "$LINENO" 5
+else as_fn_error $? "proper usage is --with-libc=STRING" "$LINENO" 5
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: default LIBC=\"$LIBC\"" >&5
@@ -11923,8 +11931,7 @@ for ac_func in acosh asinh atanh copysign erf erfc expm1 finite gamma
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
@@ -11936,8 +11943,7 @@ for ac_func in hypot lgamma log1p log2 round tgamma
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
@@ -12200,7 +12206,7 @@ no)
15|30)
;;
*)
- as_fn_error "bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" "$LINENO" 5 ;;
+ as_fn_error $? "bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" "$LINENO" 5 ;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_big_digits" >&5
$as_echo "$enable_big_digits" >&6; }
@@ -12251,9 +12257,8 @@ else
if test "$ac_cv_type_wchar_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (wchar_t)
-See \`config.log' for more details." "$LINENO" 5; }; }
+as_fn_error 77 "cannot compute sizeof (wchar_t)
+See \`config.log' for more details" "$LINENO" 5 ; }
else
ac_cv_sizeof_wchar_t=0
fi
@@ -12622,8 +12627,8 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
;; #(
*)
- as_fn_error "unknown endianness
- presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
esac
@@ -12884,7 +12889,7 @@ else
have_readline=no
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
if test $have_readline = yes
then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -13058,7 +13063,7 @@ else
have_readline=no
fi
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
if test $have_readline = yes
then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -13980,6 +13985,7 @@ DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
+U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
@@ -14142,19 +14148,19 @@ export LANGUAGE
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-# as_fn_error ERROR [LINENO LOG_FD]
-# ---------------------------------
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with status $?, using 1 if that was 0.
+# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
- as_status=$?; test $as_status -eq 0 && as_status=1
- if test "$3"; then
- as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $1" >&2
+ $as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -14350,7 +14356,7 @@ $as_echo X"$as_dir" |
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
@@ -14404,7 +14410,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by python $as_me 3.3, which was
-generated by GNU Autoconf 2.65. Invocation command line was
+generated by GNU Autoconf 2.67. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -14466,10 +14472,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
python config.status 3.3
-configured by $0, generated by GNU Autoconf 2.65,
+configured by $0, generated by GNU Autoconf 2.67,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2009 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -14485,11 +14491,16 @@ ac_need_defaults=:
while test $# != 0
do
case $1 in
- --*=*)
+ --*=?*)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
*)
ac_option=$1
ac_optarg=$2
@@ -14511,6 +14522,7 @@ do
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
@@ -14523,7 +14535,7 @@ do
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
- as_fn_error "ambiguous option: \`$1'
+ as_fn_error $? "ambiguous option: \`$1'
Try \`$0 --help' for more information.";;
--help | --hel | -h )
$as_echo "$ac_cs_usage"; exit ;;
@@ -14532,7 +14544,7 @@ Try \`$0 --help' for more information.";;
ac_cs_silent=: ;;
# This is an error.
- -*) as_fn_error "unrecognized option: \`$1'
+ -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
*) as_fn_append ac_config_targets " $1"
@@ -14591,7 +14603,7 @@ do
"Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;;
"Modules/ld_so_aix") CONFIG_FILES="$CONFIG_FILES Modules/ld_so_aix" ;;
- *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
esac
done
@@ -14628,7 +14640,7 @@ $debug ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
-} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
@@ -14645,7 +14657,7 @@ if test "x$ac_cr" = x; then
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
- ac_cs_awk_cr='\r'
+ ac_cs_awk_cr='\\r'
else
ac_cs_awk_cr=$ac_cr
fi
@@ -14659,18 +14671,18 @@ _ACEOF
echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
echo "_ACEOF"
} >conf$$subs.sh ||
- as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
-ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
. ./conf$$subs.sh ||
- as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
if test $ac_delim_n = $ac_delim_num; then
break
elif $ac_last_try; then
- as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
@@ -14759,20 +14771,28 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
else
cat
fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
- || as_fn_error "could not setup config files machinery" "$LINENO" 5
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[ ]*\):*/\1/
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
s/^[^=]*=[ ]*$//
}'
fi
@@ -14800,7 +14820,7 @@ for ac_last_try in false false :; do
if test -z "$ac_t"; then
break
elif $ac_last_try; then
- as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
@@ -14885,7 +14905,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
- as_fn_error "could not setup config headers machinery" "$LINENO" 5
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
fi # test -n "$CONFIG_HEADERS"
@@ -14898,7 +14918,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
- :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -14926,7 +14946,7 @@ do
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
- as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
@@ -14953,7 +14973,7 @@ $as_echo "$as_me: creating $ac_file" >&6;}
case $ac_tag in
*:-:* | *:-) cat >"$tmp/stdin" \
- || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
@@ -15084,22 +15104,22 @@ s&@INSTALL@&$ac_INSTALL&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&5
+which seems to be undefined. Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&2;}
+which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$tmp/stdin"
case $ac_file in
-) cat "$tmp/out" && rm -f "$tmp/out";;
*) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
esac \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
:H)
#
@@ -15110,19 +15130,19 @@ which seems to be undefined. Please make sure it is defined." >&2;}
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
} >"$tmp/config.h" \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
$as_echo "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$tmp/config.h" "$ac_file" \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
- || as_fn_error "could not create -" "$LINENO" 5
+ || as_fn_error $? "could not create -" "$LINENO" 5
fi
;;
@@ -15142,7 +15162,7 @@ _ACEOF
ac_clean_files=$ac_clean_files_save
test $ac_write_fail = 0 ||
- as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
# configure is writing to config.log, and then calls config.status.
@@ -15163,7 +15183,7 @@ if test "$no_create" != yes; then
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
- $ac_cs_success || as_fn_exit $?
+ $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
diff --git a/configure.in b/configure.in
index 274c68d..e0b2ecb 100644
--- a/configure.in
+++ b/configure.in
@@ -2541,8 +2541,8 @@ AC_MSG_RESULT(MACHDEP_OBJS)
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
clock confstr ctermid execv faccessat fchmod fchmodat fchown fchownat \
fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
- futimens futimes \
- gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \
+ futimens futimes gai_strerror \
+ getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
if_nameindex \
initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mbrtowc mkdirat mkfifo \
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 6c45460..4935077 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -305,6 +305,9 @@
/* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */
#undef HAVE_GETC_UNLOCKED
+/* Define to 1 if you have the `getgrouplist' function. */
+#undef HAVE_GETGROUPLIST
+
/* Define to 1 if you have the `getgroups' function. */
#undef HAVE_GETGROUPS
diff --git a/setup.py b/setup.py
index 896d604..2426aad 100644
--- a/setup.py
+++ b/setup.py
@@ -1045,10 +1045,15 @@ class PyBuildExt(build_ext):
else:
sqlite_extra_link_args = ()
+ include_dirs = ["Modules/_sqlite"]
+ # Only include the directory where sqlite was found if it does
+ # not already exist in set include directories, otherwise you
+ # can end up with a bad search path order.
+ if sqlite_incdir not in self.compiler.include_dirs:
+ include_dirs.append(sqlite_incdir)
exts.append(Extension('_sqlite3', sqlite_srcs,
define_macros=sqlite_defines,
- include_dirs=["Modules/_sqlite",
- sqlite_incdir],
+ include_dirs=include_dirs,
library_dirs=sqlite_libdir,
runtime_library_dirs=sqlite_libdir,
extra_link_args=sqlite_extra_link_args,
@@ -1775,6 +1780,13 @@ class PyBuildInstall(install):
install.initialize_options(self)
self.warn_dir=0
+ # Customize subcommands to not install an egg-info file for Python
+ sub_commands = [('install_lib', install.has_lib),
+ ('install_headers', install.has_headers),
+ ('install_scripts', install.has_scripts),
+ ('install_data', install.has_data)]
+
+
class PyBuildInstallLib(install_lib):
# Do exactly what install_lib does but make sure correct access modes get
# set on installed directories and files. All installed files with get