[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