From 4873012914a7f89d198801f8a7966c1e825eb60c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <piotr.maslanka@henrietta.com.pl>
Date: Mon, 30 Dec 2019 20:37:51 +0100
Subject: [PATCH] daemon cleaned up

---
 docs/exception_handling/index.rst | 13 +++++++++++
 docs/index.rst                    |  1 +
 satella/posix/__init__.py         |  7 ++----
 satella/posix/daemon.py           |  7 ++++--
 satella/posix/pidlock.py          | 36 ++++++++++++++++++++-----------
 satella/posix/signals.py          | 10 ++++++---
 6 files changed, 52 insertions(+), 22 deletions(-)
 create mode 100644 docs/exception_handling/index.rst

diff --git a/docs/exception_handling/index.rst b/docs/exception_handling/index.rst
new file mode 100644
index 00000000..0ea44485
--- /dev/null
+++ b/docs/exception_handling/index.rst
@@ -0,0 +1,13 @@
+Exception handling
+==================
+
+Satella provides a rich functionality to register exception hooks.
+
+Writing your own exception handlers
+-----------------------------------
+
+To write your own exception handlers, subclass the following class:
+
+.. autoclass:: satella.exception_handling.BaseExceptionHandler
+    :members:
+
diff --git a/docs/index.rst b/docs/index.rst
index bea56862..30e19e9e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,6 +14,7 @@ Welcome to satella's documentation!
            coding/concurrent
            instrumentation/traceback
            instrumentation/metrics
+           exception_handling/index
            json
            posix
            recipes
diff --git a/satella/posix/__init__.py b/satella/posix/__init__.py
index 183ac7e0..88c5ed05 100644
--- a/satella/posix/__init__.py
+++ b/satella/posix/__init__.py
@@ -1,17 +1,13 @@
-# coding=UTF-8
 """
-UNIX things
+POSIX things
 """
-from __future__ import print_function, absolute_import, division
 
-import logging
 import os
 
 from .daemon import daemonize
 from .pidlock import AcquirePIDLock
 from .signals import hang_until_sig
 
-logger = logging.getLogger(__name__)
 
 __all__ = [
     'daemonize',
@@ -27,6 +23,7 @@ def is_running_as_root():
     Is this process running as root?
 
     Checks whether EUID is 0
+
     :return: bool
     """
     return os.geteuid() == 0
diff --git a/satella/posix/daemon.py b/satella/posix/daemon.py
index 73615c42..69d81a02 100644
--- a/satella/posix/daemon.py
+++ b/satella/posix/daemon.py
@@ -20,6 +20,9 @@ logger = logging.getLogger(__name__)
 DEVNULL = '/dev/null'
 
 
+__all__ = ['daemonize']
+
+
 def daemonize(exit_via: tp.Callable = sys.exit,
               redirect_std_to_devnull: bool = True,
               uid: tp.Optional[int] = None,
@@ -58,10 +61,10 @@ def daemonize(exit_via: tp.Callable = sys.exit,
     _parse_ug(gid, grp, 'gr_gid', os.setegid)
 
 
-def _parse_ug(no, module, fieldname, osfun):
+def _parse_ug(no, module, field_name, osfun):
     if no is not None:
         if isinstance(no, str):
-            no = getattr(module.getpwnam(no), fieldname)
+            no = getattr(module.getpwnam(no), field_name)
         osfun(no)
 
 
diff --git a/satella/posix/pidlock.py b/satella/posix/pidlock.py
index ef920b07..30ded11a 100644
--- a/satella/posix/pidlock.py
+++ b/satella/posix/pidlock.py
@@ -24,13 +24,17 @@ class AcquirePIDLock:
 
     Usage:
 
-        with AcquirePIDLock('myservice.pid'):
+    >>> with AcquirePIDLock('myservice.pid'):
+    >>>     ... rest of code ..
 
-            .. rest of code ..
+    Or alternatively
 
-    Exiting the context manager deletes the file.
+    >>> pid_lock = AcquirePIDLock('myservice.pid')
+    >>> pid_lock.acquire()
+    >>> ...
+    >>> pid_lock.release()
 
-    The constructor doesn't throw, __enter__ does, one of:
+    The constructor doesn't throw, __enter__ or acquire() does, one of:
 
     * AcquirePIDLock.FailedToAcquire - base class for errors. Thrown if can't read the file
     * AcquirePIDLock.LockIsHeld - lock is already held. This has two attributes - pid (int), the PID of holder,
@@ -55,8 +59,18 @@ class AcquirePIDLock:
 
         self.fileno = None
 
-    def _acquire(self):
-        """The mechanical process of acquisition"""
+    def release(self):
+        if self.fileno is not None:
+            os.close(self.fileno)
+            os.unlink(self.path)
+
+    def acquire(self):
+        """
+        Acquire the PID lock
+
+        :raises LockIsHeld: if lock if held
+        :raises FailedToAcquire: if for example a directory exists in that place
+        """
         try:
             self.fileno = os.open(self.path, os.O_CREAT | os.O_EXCL)
         except (IOError, OSError):
@@ -69,7 +83,7 @@ class AcquirePIDLock:
                             'PID file found but doesn''t have an int, skipping')
                         return
             except IOError as e:
-                raise FailedToAcquire()
+                raise FailedToAcquire(repr(e))
 
             # Is this process alive?
             try:
@@ -81,17 +95,15 @@ class AcquirePIDLock:
 
     def __enter__(self):
         try:
-            self._acquire()
+            self.acquire()
         except LockIsHeld as e:
             if self.delete_on_dead and (not e.is_alive):
                 os.unlink(self.path)
-                self._acquire()
+                self.acquire()
             else:
                 raise
 
         self.success = True
 
     def __exit__(self, exc_type, exc_val, exc_tb):
-        if self.fileno is not None:
-            os.close(self.fileno)
-            os.unlink(self.path)
+        self.release()
diff --git a/satella/posix/signals.py b/satella/posix/signals.py
index 9c3b1959..ad51aa5a 100644
--- a/satella/posix/signals.py
+++ b/satella/posix/signals.py
@@ -14,10 +14,14 @@ def __sighandler(a, b):
     end = True
 
 
-def hang_until_sig(extra_signals: tp.Optional[tp.List] = None):
-    """Will hang until this process receives SIGTERM or SIGINT.
+def hang_until_sig(extra_signals: tp.Optional[tp.List[int]] = None):
+    """
+    Will hang until this process receives SIGTERM or SIGINT.
     If you pass extra signal IDs (signal.SIG*) with extra_signals,
-    then also on those signals this call will release."""
+    then also on those signals this call will release.
+
+    :param extra_signals: a list of extra signals to listen to
+    """
     extra_signals = extra_signals or []
     global end
 
-- 
GitLab