mirror of
https://github.com/rembo10/headphones.git
synced 2026-07-13 20:44:00 +01:00
@@ -38,6 +38,7 @@ class SimplePlugin(object):
|
||||
"""
|
||||
|
||||
def __init__(self, bus):
|
||||
"""Initialize a simple plugin."""
|
||||
self.bus = bus
|
||||
|
||||
def subscribe(self):
|
||||
@@ -93,6 +94,7 @@ class SignalHandler(object):
|
||||
del k, v
|
||||
|
||||
def __init__(self, bus):
|
||||
"""Initialize a signal handler plugin."""
|
||||
self.bus = bus
|
||||
# Set default handlers
|
||||
self.handlers = {'SIGTERM': self.bus.exit,
|
||||
@@ -117,8 +119,7 @@ class SignalHandler(object):
|
||||
self.bus.exit()
|
||||
|
||||
def _is_daemonized(self):
|
||||
"""Return boolean indicating if the current process is
|
||||
running as a daemon.
|
||||
"""Check if current process is running as a daemon.
|
||||
|
||||
The criteria to determine the `daemon` condition is to verify
|
||||
if the current pid is not the same as the one that got used on
|
||||
@@ -223,6 +224,7 @@ class DropPrivileges(SimplePlugin):
|
||||
"""
|
||||
|
||||
def __init__(self, bus, umask=None, uid=None, gid=None):
|
||||
"""Initialize the privilege dropping plugin."""
|
||||
SimplePlugin.__init__(self, bus)
|
||||
self.finalized = False
|
||||
self.uid = uid
|
||||
@@ -288,6 +290,7 @@ class DropPrivileges(SimplePlugin):
|
||||
self._umask = val
|
||||
|
||||
def start(self):
|
||||
"""Drop the process privileges."""
|
||||
# uid/gid
|
||||
def current_ids():
|
||||
"""Return the current (uid, gid) if available."""
|
||||
@@ -353,6 +356,7 @@ class Daemonizer(SimplePlugin):
|
||||
|
||||
def __init__(self, bus, stdin='/dev/null', stdout='/dev/null',
|
||||
stderr='/dev/null'):
|
||||
"""Initialize the daemonizer plugin."""
|
||||
SimplePlugin.__init__(self, bus)
|
||||
self.stdin = stdin
|
||||
self.stdout = stdout
|
||||
@@ -360,6 +364,7 @@ class Daemonizer(SimplePlugin):
|
||||
self.finalized = False
|
||||
|
||||
def start(self):
|
||||
"""Attempt to daemonize the process."""
|
||||
if self.finalized:
|
||||
self.bus.log('Already deamonized.')
|
||||
|
||||
@@ -382,6 +387,7 @@ class Daemonizer(SimplePlugin):
|
||||
def daemonize(
|
||||
stdin='/dev/null', stdout='/dev/null', stderr='/dev/null',
|
||||
logger=lambda msg: None):
|
||||
"""Daemonize the process."""
|
||||
# See http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||
# (or http://www.faqs.org/faqs/unix-faq/programmer/faq/ section 1.7)
|
||||
# and http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
|
||||
@@ -428,11 +434,13 @@ class PIDFile(SimplePlugin):
|
||||
"""Maintain a PID file via a WSPBus."""
|
||||
|
||||
def __init__(self, bus, pidfile):
|
||||
"""Initialize the PID file plugin."""
|
||||
SimplePlugin.__init__(self, bus)
|
||||
self.pidfile = pidfile
|
||||
self.finalized = False
|
||||
|
||||
def start(self):
|
||||
"""Write a PID file to disk."""
|
||||
pid = os.getpid()
|
||||
if self.finalized:
|
||||
self.bus.log('PID %r already written to %r.' % (pid, self.pidfile))
|
||||
@@ -444,6 +452,7 @@ class PIDFile(SimplePlugin):
|
||||
start.priority = 70
|
||||
|
||||
def exit(self):
|
||||
"""Delete the PID file from disk."""
|
||||
try:
|
||||
os.remove(self.pidfile)
|
||||
self.bus.log('PID file removed: %r.' % self.pidfile)
|
||||
@@ -462,11 +471,12 @@ class PerpetualTimer(threading.Timer):
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"Override parent constructor to allow 'bus' to be provided."
|
||||
"""Override parent constructor to allow 'bus' to be provided."""
|
||||
self.bus = kwargs.pop('bus', None)
|
||||
super(PerpetualTimer, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
"""Run an infinitely repeated callable."""
|
||||
while True:
|
||||
self.finished.wait(self.interval)
|
||||
if self.finished.isSet():
|
||||
@@ -494,6 +504,7 @@ class BackgroundTask(threading.Thread):
|
||||
"""
|
||||
|
||||
def __init__(self, interval, function, args=[], kwargs={}, bus=None):
|
||||
"""Initialize a background task parameters."""
|
||||
super(BackgroundTask, self).__init__()
|
||||
self.interval = interval
|
||||
self.function = function
|
||||
@@ -506,9 +517,11 @@ class BackgroundTask(threading.Thread):
|
||||
self.daemon = True
|
||||
|
||||
def cancel(self):
|
||||
"""Set a task cancellation flag."""
|
||||
self.running = False
|
||||
|
||||
def run(self):
|
||||
"""Start running the repeated background task in the loop."""
|
||||
self.running = True
|
||||
while self.running:
|
||||
time.sleep(self.interval)
|
||||
@@ -539,6 +552,7 @@ class Monitor(SimplePlugin):
|
||||
"""
|
||||
|
||||
def __init__(self, bus, callback, frequency=60, name=None):
|
||||
"""Initialize the monitor plugin."""
|
||||
SimplePlugin.__init__(self, bus)
|
||||
self.callback = callback
|
||||
self.frequency = frequency
|
||||
@@ -611,6 +625,7 @@ class Autoreloader(Monitor):
|
||||
"""A regular expression by which to match filenames."""
|
||||
|
||||
def __init__(self, bus, frequency=1, match='.*'):
|
||||
"""Initialize the auto-reloader monitor plugin."""
|
||||
self.mtimes = {}
|
||||
self.files = set()
|
||||
self.match = match
|
||||
@@ -717,6 +732,7 @@ class ThreadManager(SimplePlugin):
|
||||
"""A map of {thread ident: index number} pairs."""
|
||||
|
||||
def __init__(self, bus):
|
||||
"""Initialize the thread manager plugin."""
|
||||
self.threads = {}
|
||||
SimplePlugin.__init__(self, bus)
|
||||
self.bus.listeners.setdefault('acquire_thread', set())
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
r"""
|
||||
Server interfaces.
|
||||
|
||||
Starting in CherryPy 3.1, cherrypy.server is implemented as an
|
||||
:ref:`Engine Plugin<plugins>`. It's an instance of
|
||||
:class:`cherrypy._cpserver.Server`, which is a subclass of
|
||||
@@ -127,6 +129,8 @@ import portend
|
||||
|
||||
|
||||
class Timeouts:
|
||||
"""Timeout constants."""
|
||||
|
||||
occupied = 5
|
||||
free = 1
|
||||
|
||||
@@ -146,6 +150,7 @@ class ServerAdapter(object):
|
||||
"""
|
||||
|
||||
def __init__(self, bus, httpserver=None, bind_addr=None):
|
||||
"""Initialize the HTTP server plugin."""
|
||||
self.bus = bus
|
||||
self.httpserver = httpserver
|
||||
self.bind_addr = bind_addr
|
||||
@@ -153,10 +158,12 @@ class ServerAdapter(object):
|
||||
self.running = False
|
||||
|
||||
def subscribe(self):
|
||||
"""Subscribe control methods to the bus lifecycle events."""
|
||||
self.bus.subscribe('start', self.start)
|
||||
self.bus.subscribe('stop', self.stop)
|
||||
|
||||
def unsubscribe(self):
|
||||
"""Unsubcribe control methods to the bus lifecycle events."""
|
||||
self.bus.unsubscribe('start', self.start)
|
||||
self.bus.unsubscribe('stop', self.stop)
|
||||
|
||||
@@ -212,7 +219,9 @@ class ServerAdapter(object):
|
||||
return '%s://%s' % (scheme, host)
|
||||
|
||||
def _start_http_thread(self):
|
||||
"""HTTP servers MUST be running in new threads, so that the
|
||||
"""Start the HTTP server thread.
|
||||
|
||||
HTTP servers MUST be running in new threads, so that the
|
||||
main thread persists to receive KeyboardInterrupt's. If an
|
||||
exception is raised in the httpserver's thread then it's
|
||||
trapped here, and the bus (and therefore our httpserver)
|
||||
@@ -258,9 +267,10 @@ class ServerAdapter(object):
|
||||
|
||||
@property
|
||||
def bound_addr(self):
|
||||
"""
|
||||
The bind address, or if it's an ephemeral port and the
|
||||
socket has been bound, return the actual port bound.
|
||||
"""The bind address.
|
||||
|
||||
If it's an ephemeral port and the socket has been bound,
|
||||
return the actual port bound.
|
||||
"""
|
||||
host, port = self.bind_addr
|
||||
if port == 0 and self.httpserver.socket:
|
||||
@@ -292,6 +302,7 @@ class FlupCGIServer(object):
|
||||
"""Adapter for a flup.server.cgi.WSGIServer."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the flup CGI Server plugin."""
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.ready = False
|
||||
@@ -315,6 +326,7 @@ class FlupFCGIServer(object):
|
||||
"""Adapter for a flup.server.fcgi.WSGIServer."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the FCGI server parameters."""
|
||||
if kwargs.get('bindAddress', None) is None:
|
||||
import socket
|
||||
if not hasattr(socket, 'fromfd'):
|
||||
@@ -360,6 +372,7 @@ class FlupSCGIServer(object):
|
||||
"""Adapter for a flup.server.scgi.WSGIServer."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the SCGI server parameters."""
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.ready = False
|
||||
@@ -395,7 +408,8 @@ class FlupSCGIServer(object):
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _safe_wait(host, port):
|
||||
"""
|
||||
"""Warn when bind interface is ambiguous.
|
||||
|
||||
On systems where a loopback interface is not available and the
|
||||
server is bound to all interfaces, it's difficult to determine
|
||||
whether the server is in fact occupying the port. In this case,
|
||||
|
||||
@@ -17,10 +17,12 @@ class ConsoleCtrlHandler(plugins.SimplePlugin):
|
||||
"""A WSPBus plugin for handling Win32 console events (like Ctrl-C)."""
|
||||
|
||||
def __init__(self, bus):
|
||||
"""Initialize the console control handler."""
|
||||
self.is_set = False
|
||||
plugins.SimplePlugin.__init__(self, bus)
|
||||
|
||||
def start(self):
|
||||
"""Register handling of the console control events."""
|
||||
if self.is_set:
|
||||
self.bus.log('Handler for console events already set.', level=20)
|
||||
return
|
||||
@@ -34,6 +36,7 @@ class ConsoleCtrlHandler(plugins.SimplePlugin):
|
||||
self.is_set = True
|
||||
|
||||
def stop(self):
|
||||
"""Unregister the console control handlers."""
|
||||
if not self.is_set:
|
||||
self.bus.log('Handler for console events already off.', level=20)
|
||||
return
|
||||
@@ -78,6 +81,7 @@ class Win32Bus(wspbus.Bus):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize a Win32 bus implementation."""
|
||||
self.events = {}
|
||||
wspbus.Bus.__init__(self)
|
||||
|
||||
@@ -94,10 +98,12 @@ class Win32Bus(wspbus.Bus):
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""The bus state."""
|
||||
return self._state
|
||||
|
||||
@state.setter
|
||||
def state(self, value):
|
||||
"""Set the bus state."""
|
||||
self._state = value
|
||||
event = self._get_state_event(value)
|
||||
win32event.PulseEvent(event)
|
||||
@@ -144,6 +150,7 @@ control_codes = _ControlCodes({'graceful': 138})
|
||||
|
||||
|
||||
def signal_child(service, command):
|
||||
"""Send a control command to a service."""
|
||||
if command == 'stop':
|
||||
win32serviceutil.StopService(service)
|
||||
elif command == 'restart':
|
||||
@@ -165,16 +172,19 @@ class PyWebService(win32serviceutil.ServiceFramework):
|
||||
_svc_description_ = 'Python Web Service'
|
||||
|
||||
def SvcDoRun(self):
|
||||
"""Start the service."""
|
||||
from cherrypy import process
|
||||
process.bus.start()
|
||||
process.bus.block()
|
||||
|
||||
def SvcStop(self):
|
||||
"""Stop the service."""
|
||||
from cherrypy import process
|
||||
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
|
||||
process.bus.exit()
|
||||
|
||||
def SvcOther(self, control):
|
||||
"""Send a command to the service."""
|
||||
from cherrypy import process
|
||||
process.bus.publish(control_codes.key_for(control))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user