[Python-modules-commits] [cysignals] 01/01: Import cysignals_1.3.1+ds.orig.tar.xz

Jerome Benoit calculus-guest at moszumanska.debian.org
Fri Nov 4 05:08:14 UTC 2016


This is an automated email from the git hooks/post-receive script.

calculus-guest pushed a commit to branch upstream
in repository cysignals.

commit e8a4a49e5ae6b8fac96174eb275b426b5fe3376d
Author: Jerome Benoit <calculus at rezozer.net>
Date:   Wed Nov 2 15:02:56 2016 +0000

    Import cysignals_1.3.1+ds.orig.tar.xz
---
 Makefile                       |   2 +-
 PKG-INFO                       |   2 +-
 VERSION                        |   2 +-
 configure.ac                   |   8 +-
 rundoctests.py                 |  24 +++
 setup.py                       | 148 ++++++++------
 src/cysignals/debug.h.in       |   8 +-
 src/cysignals/implementation.c |  15 --
 src/cysignals/macros.h         |  15 ++
 src/cysignals/pselect.pyx      | 441 +++++++++++++++++++++++++++++++++++++++++
 10 files changed, 577 insertions(+), 88 deletions(-)

diff --git a/Makefile b/Makefile
index b7421a4..7a8c251 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,7 @@ distclean: clean
 check: check-doctest check-example
 
 check-doctest: install
-	$(PYTHON) -m doctest src/cysignals/*.pyx
+	$(PYTHON) -B rundoctests.py src/cysignals/*.pyx
 
 check-example: install
 	cd example && $(PYTHON) setup.py build
diff --git a/PKG-INFO b/PKG-INFO
index 652d61c..166201e 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: cysignals
-Version: 1.2.0
+Version: 1.3.1
 Summary: Interrupt and signal handling for Cython
 Home-page: https://github.com/sagemath/cysignals
 Author: Martin R. Albrecht, François Bissey, Volker Braun, Jeroen Demeyer
diff --git a/VERSION b/VERSION
index 26aaba0..3a3cd8c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.0
+1.3.1
diff --git a/configure.ac b/configure.ac
index 20cd006..8921bc3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,11 +40,9 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM([], [asm("leal (%eax), %eax; emms");])],
 )
 
 
-AC_CONFIG_COMMANDS([build/src/config.pxd],
-    # Generate a file config.pxd whose contents will be copied to
-    # __init__.pxd to set correct compiler options.
-    # The -Ddummy works around https://github.com/cython/cython/pull/485
-    [[echo "# distutils: extra_link_args = $LIBS -Ddummy" >build/src/config.pxd]],
+AC_CONFIG_COMMANDS([build/src/cysignals/__init__.pxd],
+    # Generate a file __init__.pxd to set correct compiler options.
+    [[echo "# distutils: extra_link_args = $LIBS" >build/src/cysignals/__init__.pxd]],
     [LIBS=$LIBS])
 
 
diff --git a/rundoctests.py b/rundoctests.py
new file mode 100755
index 0000000..ea7cf26
--- /dev/null
+++ b/rundoctests.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# Run doctests for cysignals
+#
+# We add the ELLIPSIS flag by default and we run all tests even if
+# one fails.
+#
+
+import doctest
+import sys
+
+flags = doctest.ELLIPSIS
+
+filenames = sys.argv[1:]
+print("Doctesting {} files.".format(len(filenames)))
+
+success = True
+for f in filenames:
+    print(f)
+    failures, _ = doctest.testfile(f, module_relative=False, optionflags=flags)
+    if failures:
+        success = False
+
+sys.exit(0 if success else 1)
diff --git a/setup.py b/setup.py
index 3c66e62..5dbcb24 100755
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,10 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 from distutils.core import setup, Distribution
-from distutils.command.build_py import build_py
+from distutils.command.build_py import build_py as _build_py
+from distutils.command.build_ext import build_ext as _build_ext
 from distutils.extension import Extension
-from Cython.Build import cythonize
+from Cython.Build.Dependencies import cythonize
 
 import warnings
 warnings.simplefilter("always")
@@ -24,71 +25,40 @@ kwds = dict(include_dirs=[opj("src", "cysignals"),
 extensions = [
     Extension("cysignals.signals", ["src/cysignals/signals.pyx"], **kwds),
     Extension("cysignals.alarm", ["src/cysignals/alarm.pyx"], **kwds),
-    Extension("cysignals.tests", ["src/cysignals/tests.pyx"], **kwds)
+    Extension("cysignals.pselect", ["src/cysignals/pselect.pyx"], **kwds),
+    Extension("cysignals.tests", ["src/cysignals/tests.pyx"], **kwds),
 ]
 
 
-# Run configure if it wasn't run before. We check this by the presence
-# of config.pxd
-config_pxd_file = opj(cythonize_dir, "src", "config.pxd")
-if not os.path.isfile(config_pxd_file):
-    import subprocess
-    subprocess.check_call(["make", "configure"])
-    subprocess.check_call(["sh", "configure"])
-
-
-# Determine installation directory from distutils
-inst = Distribution().get_command_obj("install")
-inst.finalize_options()
-install_dir = opj(inst.install_platlib, "cysignals")
-
-
-# Add an __init__.pxd file setting the correct compiler options.
-# The variable "init_pxd" is the string which should be written to
-# __init__.pxd
-init_pxd = "# distutils: include_dirs = {0}\n".format(install_dir)
-# Append config.pxd
-with open(config_pxd_file) as c:
-    init_pxd += c.read()
-
-# First, try to read the existing __init__.pxd file and write it only
-# if it changed.
-init_pxd_file = opj(cythonize_dir, "src", "cysignals", "__init__.pxd")
-try:
-    f = open(init_pxd_file, "r+")
-except IOError:
+def write_if_changed(filename, text):
+    """
+    Write ``text`` to ``filename`` but only if it differs from the
+    current content of ``filename``. If needed, the file and the
+    containing directory are created.
+    """
     try:
-        os.makedirs(os.path.dirname(init_pxd_file))
-    except OSError:
-        pass
-    f = open(init_pxd_file, "w+")
-
-if f.read() != init_pxd:
-    print("generating {0}".format(init_pxd_file))
-    f.seek(0)
-    f.truncate()
-    f.write(init_pxd)
-f.close()
-
-
-# Run Cython
-extensions=cythonize(extensions, build_dir=cythonize_dir,
-                     include_path=["src", opj(cythonize_dir, "src")])
-
-# Deprecate Cython without https://github.com/cython/cython/pull/486
-if os.path.isdir(opj(cythonize_dir, "cysignals")):
-    warnings.warn(
-        "building cysignals with Cython versions older than 0.24 is deprecated, "
-        "you should upgrade Cython and remove the %r directory" % cythonize_dir,
-        DeprecationWarning)
-
-# Fix include_dirs (i.e. ignore the __init__.pxd for this compilation)
-for ext in extensions:
-    ext.include_dirs = kwds['include_dirs']
+        f = open(filename, "r+")
+    except IOError:
+        try:
+            os.makedirs(os.path.dirname(filename))
+        except OSError:
+            pass
+        f = open(filename, "w")
+    else:
+        if f.read() == text:
+            # File is up-to-date
+            f.close()
+            return
+        f.seek(0)
+        f.truncate()
+
+    print("generating {0}".format(filename))
+    f.write(text)
+    f.close()
 
 
 # Run Distutils
-class build_py_cython(build_py):
+class build_py(_build_py):
     """
     Custom distutils build_py class. For every package FOO, we also
     check package data for a "fake" FOO-cython package.
@@ -118,6 +88,60 @@ class build_py_cython(build_py):
                 data.append((package, src_dir, build_dir, filenames))
         return data
 
+
+class build_ext(_build_ext):
+    def finalize_options(self):
+        _build_ext.finalize_options(self)
+        self.create_init_pxd()
+        ext_modules = self.distribution.ext_modules
+        if ext_modules:
+            self.distribution.ext_modules[:] = self.cythonize(ext_modules)
+
+    def cythonize(self, extensions):
+        return cythonize(extensions,
+                build_dir=cythonize_dir, include_path=["src"])
+
+    def create_init_pxd(self):
+        """
+        Create an ``__init__.pxd`` file in the build directory. This
+        file will then be installed.
+
+        The ``__init__.pxd`` file sets the correct compiler options for
+        packages using cysignals.
+        """
+        dist = self.distribution
+
+        # Determine installation directory
+        inst = dist.get_command_obj("install")
+        inst.ensure_finalized()
+        install_dir = opj(inst.install_platlib, "cysignals")
+
+        # The variable "init_pxd" is the string which should be written to
+        # __init__.pxd
+        init_pxd = "# distutils: include_dirs = {0}\n".format(install_dir)
+        # Append __init__.pxd from configure
+        init_pxd += self.get_init_pxd()
+
+        init_pxd_file = opj(self.build_lib, "cysignals", "__init__.pxd")
+        write_if_changed(init_pxd_file, init_pxd)
+
+    def get_init_pxd(self):
+        """
+        Get the contents of ``__init__.pxd`` as generated by configure.
+        """
+        configure_init_pxd_file = opj(cythonize_dir, "src", "cysignals", "__init__.pxd")
+        # Run configure if needed
+        try:
+            f = open(configure_init_pxd_file, "r")
+        except IOError:
+            import subprocess
+            subprocess.check_call(["make", "configure"])
+            subprocess.check_call(["sh", "configure"])
+            f = open(configure_init_pxd_file, "r")
+        with f:
+            return f.read()
+
+
 setup(
     name="cysignals",
     author=u"Martin R. Albrecht, François Bissey, Volker Braun, Jeroen Demeyer",
@@ -134,7 +158,7 @@ setup(
     package_dir={"cysignals": opj("src", "cysignals"),
                  "cysignals-cython": opj(cythonize_dir, "src", "cysignals")},
     package_data={"cysignals": ["*.pxi", "*.pxd", "*.h"],
-                  "cysignals-cython": ["__init__.pxd", "*.h"]},
+                  "cysignals-cython": ["*.h"]},
     scripts=glob(opj("src", "scripts", "*")),
-    cmdclass=dict(build_py=build_py_cython),
+    cmdclass=dict(build_py=build_py, build_ext=build_ext),
 )
diff --git a/src/cysignals/debug.h.in b/src/cysignals/debug.h.in
index 4c67836..daa0d8d 100644
--- a/src/cysignals/debug.h.in
+++ b/src/cysignals/debug.h.in
@@ -1,7 +1,9 @@
 /*
- * Whether or not to compile debug routines for the interrupt handling
- * code (0: disable, 1: enable).  Enabling will make the code slower.
- * The debug level itself needs to be set in implementation.c
+ * Should cysignals be compiled with support for verbose debugging
+ * output? The debug level itself needs to be set using the C function
+ * _set_debug_level() or the Python function set_debug_level().
+ * Enabling this will make the code slower, even if the debug level is
+ * set to 0.
  */
 #ifndef ENABLE_DEBUG_CYSIGNALS
 #undef ENABLE_DEBUG_CYSIGNALS
diff --git a/src/cysignals/implementation.c b/src/cysignals/implementation.c
index 47d8249..5afcba1 100644
--- a/src/cysignals/implementation.c
+++ b/src/cysignals/implementation.c
@@ -326,21 +326,6 @@ static void setup_cysignals_handlers(void)
 }
 
 
-static inline int _set_debug_level(int level)
-{
-#if ENABLE_DEBUG_CYSIGNALS
-    int old = cysigs.debug_level;
-    cysigs.debug_level = level;
-    return old;
-#else
-    if (level == 0)
-        return 0;    /* 0 is the only valid debug level */
-    else
-        return -1;   /* Error */
-#endif
-}
-
-
 static void print_sep(void)
 {
     fprintf(stderr,
diff --git a/src/cysignals/macros.h b/src/cysignals/macros.h
index f68786d..39d5add 100644
--- a/src/cysignals/macros.h
+++ b/src/cysignals/macros.h
@@ -274,6 +274,21 @@ static inline void sig_error(void)
 }
 
 
+static inline int _set_debug_level(int level)
+{
+#if ENABLE_DEBUG_CYSIGNALS
+    int old = cysigs.debug_level;
+    cysigs.debug_level = level;
+    return old;
+#else
+    if (level == 0)
+        return 0;    /* 0 is the only valid debug level */
+    else
+        return -1;   /* Error */
+#endif
+}
+
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
diff --git a/src/cysignals/pselect.pyx b/src/cysignals/pselect.pyx
new file mode 100644
index 0000000..3ba08ff
--- /dev/null
+++ b/src/cysignals/pselect.pyx
@@ -0,0 +1,441 @@
+"""
+Interface to the ``pselect()`` system call
+
+This module defines a class :class:`PSelecter` which can be used to
+call the system call ``pselect()`` and which can also be used in a
+``with`` statement to block given signals until
+:meth:`PSelecter.pselect` is called.
+
+Waiting for subprocesses
+------------------------
+
+One possible use is to wait with a **timeout** until **any child process**
+exits, as opposed to ``os.wait()`` which doesn't have a timeout or
+``multiprocessing.Process.join()`` which waits for one specific process.
+
+Since ``SIGCHLD`` is ignored by default, we first need to install a
+signal handler for ``SIGCHLD``. It doesn't matter what it does, as long
+as the signal isn't ignored::
+
+    >>> import signal
+    >>> def dummy_handler(sig, frame):
+    ...     pass
+    >>> _ = signal.signal(signal.SIGCHLD, dummy_handler)
+
+We wait for a child created using the ``subprocess`` module::
+
+    >>> from cysignals.pselect import PSelecter
+    >>> from subprocess import *
+    >>> with PSelecter([signal.SIGCHLD]) as sel:
+    ...     p = Popen(["sleep", "1"])
+    ...     _ = sel.sleep()
+    >>> p.poll()  # p should be finished
+    0
+
+Now using the ``multiprocessing`` module::
+
+    >>> from cysignals.pselect import PSelecter
+    >>> from multiprocessing import *
+    >>> import time
+    >>> with PSelecter([signal.SIGCHLD]) as sel:
+    ...     p = Process(target=time.sleep, args=(1,))
+    ...     p.start()
+    ...     _ = sel.sleep()
+    ...     p.is_alive()  # p should be finished
+    False
+
+"""
+
+#*****************************************************************************
+#       Copyright (C) 2013 Jeroen Demeyer <jdemeyer at cage.ugent.be>
+#
+#  cysignals is free software: you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published
+#  by the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  cysignals is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public License
+#  along with cysignals.  If not, see <http://www.gnu.org/licenses/>.
+#
+#*****************************************************************************
+
+cimport libc.errno
+from posix.signal cimport *
+from posix.select cimport *
+
+
+cpdef int get_fileno(f) except -1:
+    """
+    Return the file descriptor of ``f``.
+
+    INPUT:
+
+    - ``f`` -- an object with a ``.fileno`` method or an integer,
+      which is a file descriptor.
+
+    OUTPUT: A C ``long`` representing the file descriptor.
+
+    EXAMPLES::
+
+        >>> from os import devnull
+        >>> from cysignals.pselect import get_fileno
+        >>> get_fileno(open(devnull)) > 2
+        True
+        >>> get_fileno(42)
+        42
+        >>> get_fileno(None)
+        Traceback (most recent call last):
+        ...
+        TypeError: an integer is required
+        >>> get_fileno(-1)
+        Traceback (most recent call last):
+        ...
+        ValueError: Invalid file descriptor
+        >>> get_fileno(2**30)
+        Traceback (most recent call last):
+        ...
+        ValueError: Invalid file descriptor
+
+    """
+    cdef int n
+    try:
+        n = f.fileno()
+    except AttributeError:
+        n = f
+    if n < 0 or n >= FD_SETSIZE:
+        raise ValueError("Invalid file descriptor")
+    return n
+
+
+cdef class PSelecter:
+    """
+    This class gives an interface to the ``pselect`` system call.
+
+    It can be used in a ``with`` statement to block given signals
+    such that they can only occur during the :meth:`pselect()` or
+    :meth:`sleep()` calls.
+
+    As an example, we block the ``SIGHUP`` and ``SIGALRM`` signals and
+    then raise a ``SIGALRM`` signal. The interrupt will only be seen
+    during the :meth:`sleep` call::
+
+        >>> from cysignals import AlarmInterrupt
+        >>> from cysignals.pselect import PSelecter
+        >>> import os, signal, time
+        >>> with PSelecter([signal.SIGHUP, signal.SIGALRM]) as sel:
+        ...     os.kill(os.getpid(), signal.SIGALRM)
+        ...     time.sleep(0.5)  # Simply sleep, no interrupt detected
+        ...     try:
+        ...         _ = sel.sleep(1)  # Interrupt seen here
+        ...     except AlarmInterrupt:
+        ...         print("Interrupt OK")
+        Interrupt OK
+
+    .. WARNING::
+
+        If ``SIGCHLD`` is blocked inside the ``with`` block, then you
+        should not use ``Popen().wait()`` or ``Process().join()``
+        because those might block, even if the process has actually
+        exited. Use non-blocking alternatives such as ``Popen.poll()``
+        or ``multiprocessing.active_children()`` instead.
+    """
+    cdef sigset_t oldset
+    cdef sigset_t blockset
+
+    def __cinit__(self):
+        """
+        Store old signal mask, needed if this class is used *without*
+        a ``with`` statement.
+
+        EXAMPLES::
+
+            >>> from cysignals.pselect import PSelecter
+            >>> PSelecter()
+            <cysignals.pselect.PSelecter ...>
+
+        """
+        cdef sigset_t emptyset
+        sigemptyset(&emptyset)
+        sigprocmask(SIG_BLOCK, &emptyset, &self.oldset)
+
+    def __init__(self, block=[]):
+        """
+        Store list of signals to block during ``pselect()``.
+
+        EXAMPLES::
+
+            >>> from cysignals.pselect import PSelecter
+            >>> from signal import *
+            >>> PSelecter([SIGINT, SIGSEGV])
+            <cysignals.pselect.PSelecter ...>
+
+        """
+        sigemptyset(&self.blockset)
+        for sig in block:
+            sigaddset(&self.blockset, sig)
+
+    def __enter__(self):
+        """
+        Block signals chosen during :meth:`__init__` in this ``with`` block.
+
+        OUTPUT: ``self``
+
+        TESTS:
+
+        Test nesting, where the inner ``with`` statements should have no
+        influence, in particular they should not unblock signals which
+        were already blocked upon entering::
+
+            >>> from cysignals import AlarmInterrupt
+            >>> from cysignals.pselect import PSelecter
+            >>> import os, signal
+            >>> with PSelecter([signal.SIGALRM]) as sel:
+            ...     os.kill(os.getpid(), signal.SIGALRM)
+            ...     with PSelecter([signal.SIGFPE]) as sel2:
+            ...         _ = sel2.sleep(0.1)
+            ...     with PSelecter([signal.SIGALRM]) as sel3:
+            ...         _ = sel3.sleep(0.1)
+            ...     try:
+            ...         _ = sel.sleep(0.1)
+            ...     except AlarmInterrupt:
+            ...         print("Interrupt OK")
+            Interrupt OK
+
+        """
+        sigprocmask(SIG_BLOCK, &self.blockset, &self.oldset)
+        return self
+
+    def __exit__(self, type, value, traceback):
+        """
+        Reset signal mask to what it was before :meth:`__enter__`.
+
+        EXAMPLES:
+
+        Install a ``SIGCHLD`` handler::
+
+            >>> import signal
+            >>> def child_handler(sig, frame):
+            ...     global got_child
+            ...     got_child = 1
+            >>> _ = signal.signal(signal.SIGCHLD, child_handler)
+            >>> got_child = 0
+
+        Start a process which will cause a ``SIGCHLD`` signal::
+
+            >>> import time
+            >>> from multiprocessing import *
+            >>> from cysignals.pselect import PSelecter
+            >>> w = PSelecter([signal.SIGCHLD])
+            >>> with w:
+            ...     p = Process(target=time.sleep, args=(0.25,))
+            ...     t0 = time.time()
+            ...     p.start()
+
+        This ``sleep`` should be interruptible now::
+
+            >>> time.sleep(1)
+            >>> t = time.time() - t0
+            >>> (0.2 <= t <= 0.9) or t
+            True
+            >>> got_child
+            1
+            >>> p.join()
+
+        """
+        sigprocmask(SIG_SETMASK, &self.oldset, NULL)
+
+    def pselect(self, rlist=[], wlist=[], xlist=[], timeout=None):
+        """
+        Wait until one of the given files is ready, or a signal has
+        been received, or until ``timeout`` seconds have past.
+
+        INPUT:
+
+        - ``rlist`` -- (default: ``[]``) a list of files to wait for
+          reading.
+
+        - ``wlist`` -- (default: ``[]``) a list of files to wait for
+          writing.
+
+        - ``xlist`` -- (default: ``[]``) a list of files to wait for
+          exceptions.
+
+        - ``timeout`` -- (default: ``None``) a timeout in seconds,
+          where ``None`` stands for no timeout.
+
+        OUTPUT: A 4-tuple ``(rready, wready, xready, tmout)`` where the
+        first three are lists of file descriptors which are ready,
+        that is a subset of ``(rlist, wlist, xlist)``. The fourth is a
+        boolean which is ``True`` if and only if the command timed out.
+        If ``pselect`` was interrupted by a signal, the output is
+        ``([], [], [], False)``.
+
+        .. SEEALSO::
+
+            Use the :meth:`sleep` method instead if you don't care about
+            file descriptors.
+
+        EXAMPLES:
+
+        The file ``/dev/null`` should always be available for reading
+        and writing::
+
+            >>> from cysignals.pselect import PSelecter
+            >>> f = open(os.devnull, "r+")
+            >>> sel = PSelecter()
+            >>> sel.pselect(rlist=[f])
+            ([<...'/dev/null'...>], [], [], False)
+            >>> sel.pselect(wlist=[f])
+            ([], [<...'/dev/null'...>], [], False)
+
+        A list of various files, all of them should be ready for
+        reading. Also create a pipe, which should be ready for
+        writing, but not reading (since nothing has been written)::
+
+            >>> import os, sys
+            >>> f = open(os.devnull, "r")
+            >>> g = open(sys.executable, "r")
+            >>> (pr, pw) = os.pipe()
+            >>> r, w, x, t = PSelecter().pselect([f,g,pr,pw], [pw], [pr,pw])
+            >>> len(r), len(w), len(x), t
+            (2, 1, 0, False)
+
+        Checking for exceptions on the pipe should simply time out::
+
+            >>> sel.pselect(xlist=[pr,pw], timeout=0.2)
+            ([], [], [], True)
+
+        TESTS:
+
+        It is legal (but silly) to list the same file multiple times::
+
+            >>> r, w, x, t = PSelecter().pselect([f,g,f,f,g])
+            >>> len(r)
+            5
+
+        Invalid input::
+
+            >>> PSelecter().pselect([None])
+            Traceback (most recent call last):
+            ...
+            TypeError: an integer is required
+
+        Open a file and close it, but save the (invalid) file
+        descriptor::
+
+            >>> f = open(os.devnull, "r")
+            >>> n = f.fileno()
+            >>> f.close()
+            >>> PSelecter().pselect([n])
+            Traceback (most recent call last):
+            ...
+            OSError: ...
+
+        """
+        # Convert given lists to fd_set
+        cdef fd_set rfds, wfds, xfds
+        FD_ZERO(&rfds)
+        FD_ZERO(&wfds)
+        FD_ZERO(&xfds)
+
+        cdef int nfds = 0
+        cdef int n
+        for f in rlist:
+            n = get_fileno(f)
+            if (n >= nfds): nfds = n + 1
+            FD_SET(n, &rfds)
+        for f in wlist:
+            n = get_fileno(f)
+            if (n >= nfds): nfds = n + 1
+            FD_SET(n, &wfds)
+        for f in xlist:
+            n = get_fileno(f)
+            if (n >= nfds): nfds = n + 1
+            FD_SET(n, &xfds)
+
+        cdef double tm
+        cdef timespec tv
+        cdef timespec *ptv = NULL
+        cdef int ret
+        if timeout is not None:
+            tm = timeout
+            if tm < 0:
+                tm = 0
+            tv.tv_sec = <long>tm
+            tv.tv_nsec = <long>(1e9 * (tm - <double>tv.tv_sec))
+            ptv = &tv
+
+        ret = pselect(nfds, &rfds, &wfds, &xfds, ptv, &self.oldset)
+        # No file descriptors ready => timeout
+        if ret == 0:
+            return ([], [], [], True)
+
+        # Error?
+        cdef int err
+        if ret < 0:
+            # Save this value in case Python statements change it.
+            err = libc.errno.errno
+            if err == libc.errno.EINTR:
+                return ([], [], [], False)
+            import os
+            raise OSError(err, os.strerror(err))
+
+        # Figure out which file descriptors to return
+        rready = []
+        wready = []
+        xready = []
+        for f in rlist:
+            n = get_fileno(f)
+            if FD_ISSET(n, &rfds):
+                rready.append(f)
+        for f in wlist:
+            n = get_fileno(f)
+            if FD_ISSET(n, &wfds):
+                wready.append(f)
+        for f in xlist:
+            n = get_fileno(f)
+            if FD_ISSET(n, &xfds):
+                xready.append(f)
+
+        return (rready, wready, xready, False)
+
+    def sleep(self, timeout=None):
+        """
+        Wait until a signal has been received, or until ``timeout``
+        seconds have past.
+
+        This is implemented as a special case of :meth:`pselect` with
+        empty lists of file descriptors.
+
+        INPUT:
+
+        - ``timeout`` -- (default: ``None``) a timeout in seconds,
+          where ``None`` stands for no timeout.
+
+        OUTPUT: A boolean which is ``True`` if the call timed out,
+        False if it was interrupted.
+
+        EXAMPLES:
+
+        A simple wait with timeout::
+
+            >>> from cysignals.pselect import PSelecter
+            >>> sel = PSelecter()
+            >>> sel.sleep(timeout=0.1)
+            True
+
+        0 or negative time-outs are allowed, ``sleep`` should then
+        return immediately::
+
+            >>> sel.sleep(timeout=0)
+            True
+            >>> sel.sleep(timeout=-123.45)
+            True
+
+        """
+        return self.pselect(timeout=timeout)[3]

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/cysignals.git



More information about the Python-modules-commits mailing list