diff options
Diffstat (limited to 'pkg/osx')
-rw-r--r-- | pkg/osx/__init__.py | 2 | ||||
-rw-r--r-- | pkg/osx/_metadata.py | 28 | ||||
-rw-r--r-- | pkg/osx/daemon.py | 75 | ||||
-rw-r--r-- | pkg/osx/pidfile.py | 4 | ||||
-rw-r--r-- | pkg/osx/runner.py | 40 |
5 files changed, 76 insertions, 73 deletions
diff --git a/pkg/osx/__init__.py b/pkg/osx/__init__.py index 4731a6ef..77ff624b 100644 --- a/pkg/osx/__init__.py +++ b/pkg/osx/__init__.py @@ -41,7 +41,7 @@ from __future__ import (absolute_import, unicode_literals) from .daemon import DaemonContext - + # Local variables: # coding: utf-8 # mode: python diff --git a/pkg/osx/_metadata.py b/pkg/osx/_metadata.py index 6d22a2b7..88843df7 100644 --- a/pkg/osx/_metadata.py +++ b/pkg/osx/_metadata.py @@ -21,10 +21,11 @@ import datetime import pkg_resources - + distribution_name = "python-daemon" version_info_filename = "version_info.json" + def get_distribution_version_info(filename=version_info_filename): """ Get the version info from the installed distribution. @@ -37,10 +38,10 @@ def get_distribution_version_info(filename=version_info_filename): """ version_info = { - 'release_date': "UNKNOWN", - 'version': "UNKNOWN", - 'maintainer': "UNKNOWN", - } + 'release_date': "UNKNOWN", + 'version': "UNKNOWN", + 'maintainer': "UNKNOWN", + } try: distribution = pkg_resources.get_distribution(distribution_name) @@ -58,12 +59,13 @@ version_info = get_distribution_version_info() version_installed = version_info['version'] - + rfc822_person_regex = re.compile( - "^(?P<name>[^<]+) <(?P<email>[^>]+)>$") + "^(?P<name>[^<]+) <(?P<email>[^>]+)>$") ParsedPerson = collections.namedtuple('ParsedPerson', ['name', 'email']) + def parse_person_field(value): """ Parse a person field into name and email address. @@ -80,18 +82,18 @@ def parse_person_field(value): if len(value): if match is not None: result = ParsedPerson( - name=match.group('name'), - email=match.group('email')) + name=match.group('name'), + email=match.group('email')) else: result = ParsedPerson(name=value, email=None) - return result + return result author_name = "Ben Finney" author_email = "ben+python@benfinney.id.au" author = "{name} <{email}>".format(name=author_name, email=author_email) - + class YearRange: """ A range of years spanning a period. """ @@ -140,11 +142,11 @@ build_date = version_info['release_date'] copyright_year_range = make_year_range(copyright_year_begin, build_date) copyright = "Copyright © {year_range} {author} and others".format( - year_range=copyright_year_range, author=author) + year_range=copyright_year_range, author=author) license = "Apache-2" url = "https://alioth.debian.org/projects/python-daemon/" - + # Local variables: # coding: utf-8 # mode: python diff --git a/pkg/osx/daemon.py b/pkg/osx/daemon.py index 07810cf1..7ca8770e 100644 --- a/pkg/osx/daemon.py +++ b/pkg/osx/daemon.py @@ -36,7 +36,7 @@ except NameError: basestring = str unicode = str - + class DaemonError(Exception): """ Base exception class for errors from this module. """ @@ -56,7 +56,7 @@ class DaemonOSEnvironmentError(DaemonError, OSError): class DaemonProcessDetachError(DaemonError, OSError): """ Exception raised when process detach fails. """ - + class DaemonContext: """ Context for turning the current program into a daemon process. @@ -245,7 +245,7 @@ class DaemonContext: stdout=None, stderr=None, signal_map=None, - ): + ): """ Set up a new instance. """ self.chroot_directory = chroot_directory self.working_directory = working_directory @@ -427,8 +427,8 @@ class DaemonContext: """ exception = SystemExit( - "Terminating on signal {signal_number!r}".format( - signal_number=signal_number)) + "Terminating on signal {signal_number!r}".format( + signal_number=signal_number)) raise exception def _get_exclude_file_descriptors(self): @@ -454,8 +454,8 @@ class DaemonContext: if files_preserve is None: files_preserve = [] files_preserve.extend( - item for item in [self.stdin, self.stdout, self.stderr] - if hasattr(item, 'fileno')) + item for item in [self.stdin, self.stdout, self.stderr] + if hasattr(item, 'fileno')) exclude_descriptors = set() for item in files_preserve: @@ -502,8 +502,8 @@ class DaemonContext: """ signal_handler_map = dict( - (signal_number, self._make_signal_handler(target)) - for (signal_number, target) in self.signal_map.items()) + (signal_number, self._make_signal_handler(target)) + for (signal_number, target) in self.signal_map.items()) return signal_handler_map @@ -529,7 +529,7 @@ def _get_file_descriptor(obj): return file_descriptor - + def change_working_directory(directory): """ Change the working directory of this process. @@ -541,7 +541,7 @@ def change_working_directory(directory): os.chdir(directory) except Exception as exc: error = DaemonOSEnvironmentError( - "Unable to change working directory ({exc})".format(exc=exc)) + "Unable to change working directory ({exc})".format(exc=exc)) raise error @@ -561,7 +561,7 @@ def change_root_directory(directory): os.chroot(directory) except Exception as exc: error = DaemonOSEnvironmentError( - "Unable to change root directory ({exc})".format(exc=exc)) + "Unable to change root directory ({exc})".format(exc=exc)) raise error @@ -576,7 +576,7 @@ def change_file_creation_mask(mask): os.umask(mask) except Exception as exc: error = DaemonOSEnvironmentError( - "Unable to change file creation mask ({exc})".format(exc=exc)) + "Unable to change file creation mask ({exc})".format(exc=exc)) raise error @@ -597,10 +597,10 @@ def change_process_owner(uid, gid): os.setuid(uid) except Exception as exc: error = DaemonOSEnvironmentError( - "Unable to change process owner ({exc})".format(exc=exc)) + "Unable to change process owner ({exc})".format(exc=exc)) raise error - + def prevent_core_dump(): """ Prevent this process from generating a core dump. @@ -618,15 +618,15 @@ def prevent_core_dump(): core_limit_prev = resource.getrlimit(core_resource) except ValueError as exc: error = DaemonOSEnvironmentError( - "System does not support RLIMIT_CORE resource limit" - " ({exc})".format(exc=exc)) + "System does not support RLIMIT_CORE resource limit" + " ({exc})".format(exc=exc)) raise error # Set hard and soft limits to zero, i.e. no core dump at all. core_limit = (0, 0) resource.setrlimit(core_resource, core_limit) - + def detach_process_context(): """ Detach the process context from parent and session. @@ -656,15 +656,15 @@ def detach_process_context(): os._exit(0) except OSError as exc: error = DaemonProcessDetachError( - "{message}: [{exc.errno:d}] {exc.strerror}".format( - message=error_message, exc=exc)) + "{message}: [{exc.errno:d}] {exc.strerror}".format( + message=error_message, exc=exc)) raise error fork_then_exit_parent(error_message="Failed first fork") os.setsid() fork_then_exit_parent(error_message="Failed second fork") - + def is_process_started_by_init(): """ Determine whether the current process is started by `init`. @@ -700,7 +700,7 @@ def is_socket(fd): try: socket_type = file_socket.getsockopt( - socket.SOL_SOCKET, socket.SO_TYPE) + socket.SOL_SOCKET, socket.SO_TYPE) except socket.error as exc: exc_errno = exc.args[0] if exc_errno == errno.ENOTSOCK: @@ -759,7 +759,7 @@ def is_detach_process_context_required(): return result - + def close_file_descriptor_if_open(fd): """ Close a file descriptor if already open. @@ -778,13 +778,14 @@ def close_file_descriptor_if_open(fd): pass else: error = DaemonOSEnvironmentError( - "Failed to close file descriptor {fd:d} ({exc})".format( - fd=fd, exc=exc)) + "Failed to close file descriptor {fd:d} ({exc})".format( + fd=fd, exc=exc)) raise error MAXFD = 2048 + def get_maximum_file_descriptors(): """ Get the maximum number of open file descriptors for this process. @@ -820,7 +821,7 @@ def close_all_open_files(exclude=set()): if fd not in exclude: close_file_descriptor_if_open(fd) - + def redirect_stream(system_stream, target_stream): """ Redirect a system stream to a specified file. @@ -844,7 +845,7 @@ def redirect_stream(system_stream, target_stream): target_fd = target_stream.fileno() os.dup2(target_fd, system_stream.fileno()) - + def make_default_signal_map(): """ Make the default signal map for this system. @@ -855,15 +856,15 @@ def make_default_signal_map(): """ name_map = { - 'SIGTSTP': None, - 'SIGTTIN': None, - 'SIGTTOU': None, - 'SIGTERM': 'terminate', - } + 'SIGTSTP': None, + 'SIGTTIN': None, + 'SIGTTOU': None, + 'SIGTERM': 'terminate', + } signal_map = dict( - (getattr(signal, name), target) - for (name, target) in name_map.items() - if hasattr(signal, name)) + (getattr(signal, name), target) + for (name, target) in name_map.items() + if hasattr(signal, name)) return signal_map @@ -895,7 +896,7 @@ def register_atexit_function(func): """ atexit.register(func) - + def _chain_exception_from_existing_exception_context(exc, as_cause=False): """ Decorate the specified exception with the existing exception context. @@ -918,7 +919,7 @@ def _chain_exception_from_existing_exception_context(exc, as_cause=False): exc.__context__ = existing_exc exc.__traceback__ = existing_traceback - + # Local variables: # coding: utf-8 # mode: python diff --git a/pkg/osx/pidfile.py b/pkg/osx/pidfile.py index 4517ee0e..68f7b2ac 100644 --- a/pkg/osx/pidfile.py +++ b/pkg/osx/pidfile.py @@ -17,7 +17,7 @@ from __future__ import (absolute_import, unicode_literals) from lockfile.pidlockfile import PIDLockFile - + class TimeoutPIDLockFile(PIDLockFile, object): """ Lockfile with default timeout, implemented as a Unix PID file. @@ -59,7 +59,7 @@ class TimeoutPIDLockFile(PIDLockFile, object): timeout = self.acquire_timeout super(TimeoutPIDLockFile, self).acquire(timeout, *args, **kwargs) - + # Local variables: # coding: utf-8 # mode: python diff --git a/pkg/osx/runner.py b/pkg/osx/runner.py index 6973cf1c..de9025d3 100644 --- a/pkg/osx/runner.py +++ b/pkg/osx/runner.py @@ -37,7 +37,7 @@ from .daemon import (basestring, unicode) from .daemon import DaemonContext from .daemon import _chain_exception_from_existing_exception_context - + class DaemonRunnerError(Exception): """ Abstract base class for errors from DaemonRunner. """ @@ -65,7 +65,7 @@ class DaemonRunnerStartFailureError(DaemonRunnerError, RuntimeError): class DaemonRunnerStopFailureError(DaemonRunnerError, RuntimeError): """ Raised when failure stopping DaemonRunner. """ - + class DaemonRunner: """ Controller for a callable running in a separate background process. @@ -110,12 +110,12 @@ class DaemonRunner: self.daemon_context.stdin = open(app.stdin_path, 'rt') self.daemon_context.stdout = open(app.stdout_path, 'w+t') self.daemon_context.stderr = open( - app.stderr_path, 'w+t', buffering=0) + app.stderr_path, 'w+t', buffering=0) self.pidfile = None if app.pidfile_path is not None: self.pidfile = make_pidlockfile( - app.pidfile_path, app.pidfile_timeout) + app.pidfile_path, app.pidfile_timeout) self.daemon_context.pidfile = self.pidfile def _usage_exit(self, argv): @@ -130,7 +130,7 @@ class DaemonRunner: usage_exit_code = 2 action_usage = "|".join(self.action_funcs.keys()) message = "usage: {progname} {usage}".format( - progname=progname, usage=action_usage) + progname=progname, usage=action_usage) emit_message(message) sys.exit(usage_exit_code) @@ -175,8 +175,8 @@ class DaemonRunner: self.daemon_context.open() except lockfile.AlreadyLocked: error = DaemonRunnerStartFailureError( - "PID file {pidfile.path!r} already locked".format( - pidfile=self.pidfile)) + "PID file {pidfile.path!r} already locked".format( + pidfile=self.pidfile)) raise error pid = os.getpid() @@ -198,8 +198,8 @@ class DaemonRunner: os.kill(pid, signal.SIGTERM) except OSError as exc: error = DaemonRunnerStopFailureError( - "Failed to terminate {pid:d}: {exc}".format( - pid=pid, exc=exc)) + "Failed to terminate {pid:d}: {exc}".format( + pid=pid, exc=exc)) raise error def _stop(self): @@ -212,8 +212,8 @@ class DaemonRunner: """ if not self.pidfile.is_locked(): error = DaemonRunnerStopFailureError( - "PID file {pidfile.path!r} not locked".format( - pidfile=self.pidfile)) + "PID file {pidfile.path!r} not locked".format( + pidfile=self.pidfile)) raise error if is_pidfile_stale(self.pidfile): @@ -228,10 +228,10 @@ class DaemonRunner: self._start() action_funcs = { - 'start': _start, - 'stop': _stop, - 'restart': _restart, - } + 'start': _start, + 'stop': _stop, + 'restart': _restart, + } def _get_action_func(self): """ Get the function for the specified action. @@ -249,8 +249,8 @@ class DaemonRunner: func = self.action_funcs[self.action] except KeyError: error = DaemonRunnerInvalidActionError( - "Unknown action: {action!r}".format( - action=self.action)) + "Unknown action: {action!r}".format( + action=self.action)) raise error return func @@ -279,11 +279,11 @@ def make_pidlockfile(path, acquire_timeout): """ Make a PIDLockFile instance with the given filesystem path. """ if not isinstance(path, basestring): error = ValueError("Not a filesystem path: {path!r}".format( - path=path)) + path=path)) raise error if not os.path.isabs(path): error = ValueError("Not an absolute path: {path!r}".format( - path=path)) + path=path)) raise error lockfile = pidfile.TimeoutPIDLockFile(path, acquire_timeout) @@ -316,7 +316,7 @@ def is_pidfile_stale(pidfile): return result - + # Local variables: # coding: utf-8 # mode: python |