mit neuen venv und exe-Files

This commit is contained in:
2024-11-03 17:26:54 +01:00
parent 07c05a338a
commit 0c373ff593
15115 changed files with 1998469 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Nothing public here
__all__ = []

View File

@@ -0,0 +1,126 @@
# pylint: disable=no-member
# This module is only used to create and compile the gevent._corecffi module;
# nothing should be directly imported from it except `ffi`, which should only be
# used for `ffi.compile()`; programs should import gevent._corecfffi.
# However, because we are using "out-of-line" mode, it is necessary to examine
# this file to know what functions are created and available on the generated
# module.
from __future__ import absolute_import, print_function
import sys
import os
import os.path # pylint:disable=no-name-in-module
from cffi import FFI
sys.path.append(".")
try:
import _setuplibev
import _setuputils
except ImportError:
print("This file must be imported with setup.py in the current working dir.")
raise
thisdir = os.path.dirname(os.path.abspath(__file__))
parentdir = os.path.abspath(os.path.join(thisdir, '..'))
setup_dir = os.path.abspath(os.path.join(thisdir, '..', '..', '..'))
__all__ = []
ffi = FFI()
distutils_ext = _setuplibev.build_extension()
def read_source(name):
# pylint:disable=unspecified-encoding
with open(os.path.join(thisdir, name), 'r') as f:
return f.read()
# cdef goes to the cffi library and determines what can be used in
# Python.
_cdef = read_source('_corecffi_cdef.c')
# These defines and uses help keep the C file readable and lintable by
# C tools.
_cdef = _cdef.replace('#define GEVENT_STRUCT_DONE int', '')
_cdef = _cdef.replace("GEVENT_STRUCT_DONE _;", '...;')
_cdef = _cdef.replace('#define GEVENT_ST_NLINK_T int',
'typedef int... nlink_t;')
_cdef = _cdef.replace('GEVENT_ST_NLINK_T', 'nlink_t')
if _setuplibev.LIBEV_EMBED:
# Arrange access to the loop internals
_cdef += """
struct ev_loop {
int backend_fd;
int activecnt;
...;
};
"""
# arrange to be configured.
_setuputils.ConfiguringBuildExt.gevent_add_pre_run_action(distutils_ext.configure)
if sys.platform.startswith('win'):
# We must have the vfd_open, etc, functions on
# Windows. But on other platforms, going through
# CFFI to just return the file-descriptor is slower
# than just doing it in Python, so we check for and
# workaround their absence in corecffi.py
_cdef += """
typedef int... vfd_socket_t;
int vfd_open(vfd_socket_t);
vfd_socket_t vfd_get(int);
void vfd_free(int);
"""
# source goes to the C compiler
_source = read_source('_corecffi_source.c')
macros = list(distutils_ext.define_macros)
try:
# We need the data pointer.
macros.remove(('EV_COMMON', ''))
except ValueError:
pass
ffi.cdef(_cdef)
ffi.set_source(
'gevent.libev._corecffi',
_source,
include_dirs=distutils_ext.include_dirs + [
thisdir, # "libev.h"
parentdir, # _ffi/alloc.c
],
define_macros=macros,
undef_macros=distutils_ext.undef_macros,
libraries=distutils_ext.libraries,
)
if __name__ == '__main__':
# XXX: Note, on Windows, we would need to specify the external libraries
# that should be linked in, such as ws2_32 and (because libev_vfd.h makes
# Python.h calls) the proper Python library---at least for PyPy. I never got
# that to work though, and calling python functions is strongly discouraged
# from CFFI code.
# On macOS to make the non-embedded case work correctly, against
# our local copy of libev:
#
# 1) configure and make libev
# 2) CPPFLAGS=-Ideps/libev/ LDFLAGS=-Ldeps/libev/.libs GEVENTSETUP_EMBED_LIBEV=0 \
# python setup.py build_ext -i
# 3) export DYLD_LIBRARY_PATH=`pwd`/deps/libev/.libs
#
# The DYLD_LIBRARY_PATH is because the linker hard-codes
# /usr/local/lib/libev.4.dylib in the corecffi.so dylib, because
# that's the "install name" of the libev dylib that was built.
# Adding a -rpath to the LDFLAGS doesn't change things.
# This can be fixed with `install_name_tool`:
#
# 3) install_name_tool -change /usr/local/lib/libev.4.dylib \
# `pwd`/deps/libev/.libs/libev.4.dylib \
# src/gevent/libev/_corecffi.abi3.so
ffi.compile(verbose=True)

View File

@@ -0,0 +1,470 @@
# pylint: disable=too-many-lines, protected-access, redefined-outer-name, not-callable
# pylint: disable=no-member
from __future__ import absolute_import, print_function
import sys
# pylint: disable=undefined-all-variable
__all__ = [
'get_version',
'get_header_version',
'supported_backends',
'recommended_backends',
'embeddable_backends',
'time',
'loop',
]
from zope.interface import implementer
from gevent._interfaces import ILoop
from gevent.libev import _corecffi # pylint:disable=no-name-in-module,import-error
ffi = _corecffi.ffi # pylint:disable=no-member
libev = _corecffi.lib # pylint:disable=no-member
if hasattr(libev, 'vfd_open'):
# Must be on windows
# pylint:disable=c-extension-no-member
assert sys.platform.startswith("win"), "vfd functions only needed on windows"
vfd_open = libev.vfd_open
vfd_free = libev.vfd_free
vfd_get = libev.vfd_get
else:
vfd_open = vfd_free = vfd_get = lambda fd: fd
libev.gevent_set_ev_alloc()
#####
## NOTE on Windows:
# The C implementation does several things specially for Windows;
# a possibly incomplete list is:
#
# - the loop runs a periodic signal checker;
# - the io watcher constructor is different and it has a destructor;
# - the child watcher is not defined
#
# The CFFI implementation does none of these things, and so
# is possibly NOT FUNCTIONALLY CORRECT on Win32
#####
from gevent._ffi.loop import AbstractCallbacks
from gevent._ffi.loop import assign_standard_callbacks
class _Callbacks(AbstractCallbacks):
# pylint:disable=arguments-differ,arguments-renamed
def python_check_callback(self, *args):
# There's a pylint bug (pylint 2.9.3, astroid 2.6.2) that causes pylint to crash
# with an AttributeError on certain types of arguments-differ errors
# But code in _ffi/loop depends on being able to find the watcher_ptr
# argument is the local frame. BUT it gets invoked before the function body runs.
# Hence the override of _find_watcher_ptr_in_traceback.
# pylint:disable=unused-variable
_loop, watcher_ptr, _events = args
AbstractCallbacks.python_check_callback(self, watcher_ptr)
def _find_watcher_ptr_in_traceback(self, tb):
if tb is not None:
l = tb.tb_frame.f_locals
if 'watcher_ptr' in l:
return l['watcher_ptr']
if 'args' in l and len(l['args']) == 3:
return l['args'][1]
return AbstractCallbacks._find_watcher_ptr_in_traceback(self, tb)
def python_prepare_callback(self, _loop_ptr, watcher_ptr, _events):
AbstractCallbacks.python_prepare_callback(self, watcher_ptr)
def _find_loop_from_c_watcher(self, watcher_ptr):
loop_handle = ffi.cast('struct ev_watcher*', watcher_ptr).data
return self.from_handle(loop_handle)
_callbacks = assign_standard_callbacks(ffi, libev, _Callbacks)
UNDEF = libev.EV_UNDEF
NONE = libev.EV_NONE
READ = libev.EV_READ
WRITE = libev.EV_WRITE
TIMER = libev.EV_TIMER
PERIODIC = libev.EV_PERIODIC
SIGNAL = libev.EV_SIGNAL
CHILD = libev.EV_CHILD
STAT = libev.EV_STAT
IDLE = libev.EV_IDLE
PREPARE = libev.EV_PREPARE
CHECK = libev.EV_CHECK
EMBED = libev.EV_EMBED
FORK = libev.EV_FORK
CLEANUP = libev.EV_CLEANUP
ASYNC = libev.EV_ASYNC
CUSTOM = libev.EV_CUSTOM
ERROR = libev.EV_ERROR
READWRITE = libev.EV_READ | libev.EV_WRITE
MINPRI = libev.EV_MINPRI
MAXPRI = libev.EV_MAXPRI
BACKEND_PORT = libev.EVBACKEND_PORT
BACKEND_KQUEUE = libev.EVBACKEND_KQUEUE
BACKEND_EPOLL = libev.EVBACKEND_EPOLL
BACKEND_POLL = libev.EVBACKEND_POLL
BACKEND_SELECT = libev.EVBACKEND_SELECT
FORKCHECK = libev.EVFLAG_FORKCHECK
NOINOTIFY = libev.EVFLAG_NOINOTIFY
SIGNALFD = libev.EVFLAG_SIGNALFD
NOSIGMASK = libev.EVFLAG_NOSIGMASK
from gevent._ffi.loop import EVENTS
GEVENT_CORE_EVENTS = EVENTS
def get_version():
return 'libev-%d.%02d' % (libev.ev_version_major(), libev.ev_version_minor())
def get_header_version():
return 'libev-%d.%02d' % (libev.EV_VERSION_MAJOR, libev.EV_VERSION_MINOR)
# This list backends in the order they are actually tried by libev,
# as defined in loop_init. The names must be lower case.
_flags = [
# IOCP --- not supported/used.
(libev.EVBACKEND_PORT, 'port'),
(libev.EVBACKEND_KQUEUE, 'kqueue'),
(libev.EVBACKEND_IOURING, 'linux_iouring'),
(libev.EVBACKEND_LINUXAIO, "linux_aio"),
(libev.EVBACKEND_EPOLL, 'epoll'),
(libev.EVBACKEND_POLL, 'poll'),
(libev.EVBACKEND_SELECT, 'select'),
(libev.EVFLAG_NOENV, 'noenv'),
(libev.EVFLAG_FORKCHECK, 'forkcheck'),
(libev.EVFLAG_SIGNALFD, 'signalfd'),
(libev.EVFLAG_NOSIGMASK, 'nosigmask')
]
_flags_str2int = dict((string, flag) for (flag, string) in _flags)
def _flags_to_list(flags):
result = []
for code, value in _flags:
if flags & code:
result.append(value)
flags &= ~code
if not flags:
break
if flags:
result.append(flags)
return result
if sys.version_info[0] >= 3:
basestring = (bytes, str)
integer_types = (int,)
else:
import __builtin__ # pylint:disable=import-error
basestring = (__builtin__.basestring,)
integer_types = (int, __builtin__.long)
def _flags_to_int(flags):
# Note, that order does not matter, libev has its own predefined order
if not flags:
return 0
if isinstance(flags, integer_types):
return flags
result = 0
try:
if isinstance(flags, basestring):
flags = flags.split(',')
for value in flags:
value = value.strip().lower()
if value:
result |= _flags_str2int[value]
except KeyError as ex:
raise ValueError('Invalid backend or flag: %s\nPossible values: %s' % (ex, ', '.join(sorted(_flags_str2int.keys()))))
return result
def _str_hex(flag):
if isinstance(flag, integer_types):
return hex(flag)
return str(flag)
def _check_flags(flags):
as_list = []
flags &= libev.EVBACKEND_MASK
if not flags:
return
if not flags & libev.EVBACKEND_ALL:
raise ValueError('Invalid value for backend: 0x%x' % flags)
if not flags & libev.ev_supported_backends():
as_list = [_str_hex(x) for x in _flags_to_list(flags)]
raise ValueError('Unsupported backend: %s' % '|'.join(as_list))
def supported_backends():
return _flags_to_list(libev.ev_supported_backends())
def recommended_backends():
return _flags_to_list(libev.ev_recommended_backends())
def embeddable_backends():
return _flags_to_list(libev.ev_embeddable_backends())
def time():
return libev.ev_time()
from gevent._ffi.loop import AbstractLoop
from gevent.libev import watcher as _watchers
_events_to_str = _watchers._events_to_str # exported
@implementer(ILoop)
class loop(AbstractLoop):
# pylint:disable=too-many-public-methods
# libuv parameters simply won't accept anything lower than 1ms
# (0.001s), but libev takes fractional seconds. In practice, on
# one machine, libev can sleep for very small periods of time:
#
# sleep(0.00001) -> 0.000024
# sleep(0.0001) -> 0.000156
# sleep(0.001) -> 0.00136 (which is comparable to libuv)
approx_timer_resolution = 0.00001
error_handler = None
_CHECK_POINTER = 'struct ev_check *'
_PREPARE_POINTER = 'struct ev_prepare *'
_TIMER_POINTER = 'struct ev_timer *'
def __init__(self, flags=None, default=None):
AbstractLoop.__init__(self, ffi, libev, _watchers, flags, default)
self._default = bool(libev.ev_is_default_loop(self._ptr))
def _init_loop(self, flags, default):
c_flags = _flags_to_int(flags)
_check_flags(c_flags)
c_flags |= libev.EVFLAG_NOENV
c_flags |= libev.EVFLAG_FORKCHECK
if default is None:
default = True
if default:
ptr = libev.gevent_ev_default_loop(c_flags)
if not ptr:
raise SystemError("ev_default_loop(%s) failed" % (c_flags, ))
else:
ptr = libev.ev_loop_new(c_flags)
if not ptr:
raise SystemError("ev_loop_new(%s) failed" % (c_flags, ))
if default or SYSERR_CALLBACK is None:
set_syserr_cb(self._handle_syserr)
# Mark this loop as being used.
libev.ev_set_userdata(ptr, ptr)
return ptr
def _init_and_start_check(self):
libev.ev_check_init(self._check, libev.python_check_callback)
self._check.data = self._handle_to_self
libev.ev_check_start(self._ptr, self._check)
self.unref()
def _init_and_start_prepare(self):
libev.ev_prepare_init(self._prepare, libev.python_prepare_callback)
libev.ev_prepare_start(self._ptr, self._prepare)
self.unref()
def _init_callback_timer(self):
libev.ev_timer_init(self._timer0, libev.gevent_noop, 0.0, 0.0)
def _stop_callback_timer(self):
libev.ev_timer_stop(self._ptr, self._timer0)
def _start_callback_timer(self):
libev.ev_timer_start(self._ptr, self._timer0)
def _stop_aux_watchers(self):
super(loop, self)._stop_aux_watchers()
if libev.ev_is_active(self._prepare):
self.ref()
libev.ev_prepare_stop(self._ptr, self._prepare)
if libev.ev_is_active(self._check):
self.ref()
libev.ev_check_stop(self._ptr, self._check)
if libev.ev_is_active(self._timer0):
libev.ev_timer_stop(self._timer0)
def _setup_for_run_callback(self):
# XXX: libuv needs to start the callback timer to be sure
# that the loop wakes up and calls this. Our C version doesn't
# do this.
# self._start_callback_timer()
self.ref() # we should go through the loop now
def destroy(self):
if self._ptr:
super(loop, self).destroy()
# pylint:disable=comparison-with-callable
if globals()["SYSERR_CALLBACK"] == self._handle_syserr:
set_syserr_cb(None)
def _can_destroy_loop(self, ptr):
# Is it marked as destroyed?
return libev.ev_userdata(ptr)
def _destroy_loop(self, ptr):
# Mark as destroyed.
libev.ev_set_userdata(ptr, ffi.NULL)
libev.ev_loop_destroy(ptr)
libev.gevent_zero_prepare(self._prepare)
libev.gevent_zero_check(self._check)
libev.gevent_zero_timer(self._timer0)
del self._prepare
del self._check
del self._timer0
@property
def MAXPRI(self):
return libev.EV_MAXPRI
@property
def MINPRI(self):
return libev.EV_MINPRI
def _default_handle_error(self, context, type, value, tb): # pylint:disable=unused-argument
super(loop, self)._default_handle_error(context, type, value, tb)
libev.ev_break(self._ptr, libev.EVBREAK_ONE)
def run(self, nowait=False, once=False):
flags = 0
if nowait:
flags |= libev.EVRUN_NOWAIT
if once:
flags |= libev.EVRUN_ONCE
libev.ev_run(self._ptr, flags)
def reinit(self):
libev.ev_loop_fork(self._ptr)
def ref(self):
libev.ev_ref(self._ptr)
def unref(self):
libev.ev_unref(self._ptr)
def break_(self, how=libev.EVBREAK_ONE):
libev.ev_break(self._ptr, how)
def verify(self):
libev.ev_verify(self._ptr)
def now(self):
return libev.ev_now(self._ptr)
def update_now(self):
libev.ev_now_update(self._ptr)
def __repr__(self):
return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), self._format())
@property
def iteration(self):
return libev.ev_iteration(self._ptr)
@property
def depth(self):
return libev.ev_depth(self._ptr)
@property
def backend_int(self):
return libev.ev_backend(self._ptr)
@property
def backend(self):
backend = libev.ev_backend(self._ptr)
for key, value in _flags:
if key == backend:
return value
return backend
@property
def pendingcnt(self):
return libev.ev_pending_count(self._ptr)
def closing_fd(self, fd):
pending_before = libev.ev_pending_count(self._ptr)
libev.ev_feed_fd_event(self._ptr, fd, 0xFFFF)
pending_after = libev.ev_pending_count(self._ptr)
return pending_after > pending_before
if sys.platform != "win32":
def install_sigchld(self):
libev.gevent_install_sigchld_handler()
def reset_sigchld(self):
libev.gevent_reset_sigchld_handler()
def fileno(self):
if self._ptr and LIBEV_EMBED:
# If we don't embed, we can't access these fields,
# the type is opaque
fd = self._ptr.backend_fd
if fd >= 0:
return fd
@property
def activecnt(self):
if not self._ptr:
raise ValueError('operation on destroyed loop')
if LIBEV_EMBED:
return self._ptr.activecnt
return -1
@ffi.def_extern()
def _syserr_cb(msg):
try:
msg = ffi.string(msg)
SYSERR_CALLBACK(msg, ffi.errno)
except:
set_syserr_cb(None)
raise # let cffi print the traceback
def set_syserr_cb(callback):
global SYSERR_CALLBACK
if callback is None:
libev.ev_set_syserr_cb(ffi.NULL)
SYSERR_CALLBACK = None
elif callable(callback):
libev.ev_set_syserr_cb(libev._syserr_cb)
SYSERR_CALLBACK = callback
else:
raise TypeError('Expected callable or None, got %r' % (callback, ))
SYSERR_CALLBACK = None
LIBEV_EMBED = libev.LIBEV_EMBED

View File

@@ -0,0 +1,287 @@
# pylint: disable=too-many-lines, protected-access, redefined-outer-name, not-callable
# pylint: disable=no-member
from __future__ import absolute_import, print_function
import sys
from gevent.libev import _corecffi # pylint:disable=no-name-in-module,import-error
# Nothing public here
__all__ = []
ffi = _corecffi.ffi # pylint:disable=no-member
libev = _corecffi.lib # pylint:disable=no-member
if hasattr(libev, 'vfd_open'):
# Must be on windows
# pylint:disable=c-extension-no-member
assert sys.platform.startswith("win"), "vfd functions only needed on windows"
vfd_open = libev.vfd_open
vfd_free = libev.vfd_free
vfd_get = libev.vfd_get
else:
vfd_open = vfd_free = vfd_get = lambda fd: fd
#####
## NOTE on Windows:
# The C implementation does several things specially for Windows;
# a possibly incomplete list is:
#
# - the loop runs a periodic signal checker;
# - the io watcher constructor is different and it has a destructor;
# - the child watcher is not defined
#
# The CFFI implementation does none of these things, and so
# is possibly NOT FUNCTIONALLY CORRECT on Win32
#####
_NOARGS = ()
_events = [(libev.EV_READ, 'READ'),
(libev.EV_WRITE, 'WRITE'),
(libev.EV__IOFDSET, '_IOFDSET'),
(libev.EV_PERIODIC, 'PERIODIC'),
(libev.EV_SIGNAL, 'SIGNAL'),
(libev.EV_CHILD, 'CHILD'),
(libev.EV_STAT, 'STAT'),
(libev.EV_IDLE, 'IDLE'),
(libev.EV_PREPARE, 'PREPARE'),
(libev.EV_CHECK, 'CHECK'),
(libev.EV_EMBED, 'EMBED'),
(libev.EV_FORK, 'FORK'),
(libev.EV_CLEANUP, 'CLEANUP'),
(libev.EV_ASYNC, 'ASYNC'),
(libev.EV_CUSTOM, 'CUSTOM'),
(libev.EV_ERROR, 'ERROR')]
from gevent._ffi import watcher as _base
def _events_to_str(events):
return _base.events_to_str(events, _events)
class watcher(_base.watcher):
_FFI = ffi
_LIB = libev
_watcher_prefix = 'ev'
# Flags is a bitfield with the following meaning:
# 0000 -> default, referenced (when active)
# 0010 -> ev_unref has been called
# 0100 -> not referenced; independent of 0010
_flags = 0
def __init__(self, _loop, ref=True, priority=None, args=_base._NOARGS):
if ref:
self._flags = 0
else:
self._flags = 4
super(watcher, self).__init__(_loop, ref=ref, priority=priority, args=args)
def _watcher_ffi_set_priority(self, priority):
libev.ev_set_priority(self._watcher, priority)
def _watcher_ffi_init(self, args):
self._watcher_init(self._watcher,
self._watcher_callback,
*args)
def _watcher_ffi_start(self):
self._watcher_start(self.loop._ptr, self._watcher)
def _watcher_ffi_ref(self):
if self._flags & 2: # we've told libev we're not referenced
self.loop.ref()
self._flags &= ~2
def _watcher_ffi_unref(self):
if self._flags & 6 == 4:
# We're not referenced, but we haven't told libev that
self.loop.unref()
self._flags |= 2 # now we've told libev
def _get_ref(self):
return not self._flags & 4
def _set_ref(self, value):
if value:
if not self._flags & 4:
return # ref is already True
if self._flags & 2: # ev_unref was called, undo
self.loop.ref()
self._flags &= ~6 # do not want unref, no outstanding unref
else:
if self._flags & 4:
return # ref is already False
self._flags |= 4 # we're not referenced
if not self._flags & 2 and libev.ev_is_active(self._watcher):
# we haven't told libev we're not referenced, but it thinks we're
# active so we need to undo that
self.loop.unref()
self._flags |= 2 # libev knows we're not referenced
ref = property(_get_ref, _set_ref)
def _get_priority(self):
return libev.ev_priority(self._watcher)
@_base.not_while_active
def _set_priority(self, priority):
libev.ev_set_priority(self._watcher, priority)
priority = property(_get_priority, _set_priority)
def feed(self, revents, callback, *args):
self.callback = callback
self.args = args or _NOARGS
if self._flags & 6 == 4:
self.loop.unref()
self._flags |= 2
libev.ev_feed_event(self.loop._ptr, self._watcher, revents)
if not self._flags & 1:
# Py_INCREF(<PyObjectPtr>self)
self._flags |= 1
@property
def pending(self):
return bool(self._watcher and libev.ev_is_pending(self._watcher))
class io(_base.IoMixin, watcher):
EVENT_MASK = libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE
def _get_fd(self):
return vfd_get(self._watcher.fd)
@_base.not_while_active
def _set_fd(self, fd):
vfd = vfd_open(fd)
vfd_free(self._watcher.fd)
self._watcher_init(self._watcher, self._watcher_callback, vfd, self._watcher.events)
fd = property(_get_fd, _set_fd)
def _get_events(self):
return self._watcher.events
@_base.not_while_active
def _set_events(self, events):
self._watcher_init(self._watcher, self._watcher_callback, self._watcher.fd, events)
events = property(_get_events, _set_events)
@property
def events_str(self):
return _events_to_str(self._watcher.events)
def _format(self):
return ' fd=%s events=%s' % (self.fd, self.events_str)
class timer(_base.TimerMixin, watcher):
@property
def at(self):
return self._watcher.at
def again(self, callback, *args, **kw):
# Exactly the same as start(), just with a different initializer
# function
self._watcher_start = libev.ev_timer_again
try:
self.start(callback, *args, **kw)
finally:
del self._watcher_start
class signal(_base.SignalMixin, watcher):
pass
class idle(_base.IdleMixin, watcher):
pass
class prepare(_base.PrepareMixin, watcher):
pass
class check(_base.CheckMixin, watcher):
pass
class fork(_base.ForkMixin, watcher):
pass
class async_(_base.AsyncMixin, watcher):
def send(self):
libev.ev_async_send(self.loop._ptr, self._watcher)
@property
def pending(self):
return self._watcher is not None and bool(libev.ev_async_pending(self._watcher))
# Provide BWC for those that have async
locals()['async'] = async_
class _ClosedWatcher(object):
__slots__ = ('pid', 'rpid', 'rstatus')
def __init__(self, other):
self.pid = other.pid
self.rpid = other.rpid
self.rstatus = other.rstatus
def __bool__(self):
return False
__nonzero__ = __bool__
class child(_base.ChildMixin, watcher):
_watcher_type = 'child'
def close(self):
# Capture the properties we defer to our _watcher, because
# we're about to discard it.
closed_watcher = _ClosedWatcher(self._watcher)
super(child, self).close()
self._watcher = closed_watcher
@property
def pid(self):
return self._watcher.pid
@property
def rpid(self):
return self._watcher.rpid
@rpid.setter
def rpid(self, value):
self._watcher.rpid = value
@property
def rstatus(self):
return self._watcher.rstatus
@rstatus.setter
def rstatus(self, value):
self._watcher.rstatus = value
class stat(_base.StatMixin, watcher):
_watcher_type = 'stat'
@property
def attr(self):
if not self._watcher.attr.st_nlink:
return
return self._watcher.attr
@property
def prev(self):
if not self._watcher.prev.st_nlink:
return
return self._watcher.prev
@property
def interval(self):
return self._watcher.interval