[Python-modules-commits] [python-daemonocle] 01/03: Imported Upstream version 1.0.1

Adrian Alves alvesadrian-guest at moszumanska.debian.org
Tue May 24 18:01:40 UTC 2016


This is an automated email from the git hooks/post-receive script.

alvesadrian-guest pushed a commit to branch master
in repository python-daemonocle.

commit 514f3f0fe1838b68a4dbcff41d4bbc3523cd5d5a
Author: Adrian Alves <aalves at gmail.com>
Date:   Tue May 24 14:55:10 2016 -0300

    Imported Upstream version 1.0.1
---
 .gitignore                               |   9 +
 .travis.yml                              |  15 +
 HISTORY.rst                              |  75 +++++
 MANIFEST.in                              |   1 +
 PKG-INFO                                 | 459 -------------------------------
 README.rst                               |   6 +
 daemonocle.egg-info/PKG-INFO             | 459 -------------------------------
 daemonocle.egg-info/SOURCES.txt          |  13 -
 daemonocle.egg-info/dependency_links.txt |   1 -
 daemonocle.egg-info/requires.txt         |   2 -
 daemonocle.egg-info/top_level.txt        |   1 -
 daemonocle/__init__.py                   |   4 +-
 daemonocle/cli.py                        |   8 +-
 daemonocle/{daemon.py => core.py}        | 181 +++++++-----
 daemonocle/exceptions.py                 |   2 +-
 setup.cfg                                |   5 -
 setup.py                                 |  28 +-
 tests/conftest.py                        |  83 ++++++
 tests/test_actions.py                    |  31 +++
 tests/test_basics.py                     | 315 +++++++++++++++++++++
 tests/test_cli.py                        |  95 +++++++
 tests/test_environment.py                | 185 +++++++++++++
 tests/test_shutdown.py                   | 165 +++++++++++
 23 files changed, 1120 insertions(+), 1023 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c604ce0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+*.pyc
+*.egg-info/
+.cache/
+.coverage*
+__pycache__/
+build/
+dist/
+htmlcov/
+venv/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..5394fb3
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,15 @@
+language: python
+python:
+  - 2.7
+  - 3.3
+  - 3.4
+  - 3.5
+sudo: required
+dist: trusty
+install:
+  - pip install -e .[test]
+script:
+  - flake8 -v setup.py daemonocle tests
+  - py.test -v --cov=daemonocle --cov-report=term-missing tests
+after_success:
+  - coveralls
diff --git a/HISTORY.rst b/HISTORY.rst
new file mode 100644
index 0000000..b4341c7
--- /dev/null
+++ b/HISTORY.rst
@@ -0,0 +1,75 @@
+Release History
+---------------
+
+v1.0.1 (2016-04-17)
+~~~~~~~~~~~~~~~~~~~
+
+* No changes in this release. Bumped version only to re-upload to PyPI.
+
+v1.0.0 (2016-04-17)
+~~~~~~~~~~~~~~~~~~~
+
+* Added official support for Python 2.7, 3.3, 3.4, and 3.5.
+* Added a comprehensive suite of unit tests with over 90% code coverage.
+* Dependencies (click and psutil) are no longer pinned to specific versions.
+* Fixed bug with ``atexit`` handlers not being called in intermediate processes.
+* Fixed bug when PID file is a relative path.
+* Fixed bug when STDIN doesn't have a file descriptor number.
+* Fixed bug when running in non-detached mode in a Docker container.
+* A TTY is no longer checked for when deciding how to run in non-detached mode.
+  The behavior was inconsistent across different platforms.
+* Fixed bug when a process stopped before having chance to check if it stopped.
+* Fixed bug where an exception could be raised if a PID file is already gone
+  when trying to remove it.
+* Subdirectories created for PID files now respect the ``umask`` setting.
+* The pre-``umask`` mode for PID files is now ``0o666`` instead of ``0o777``,
+  which will result in a default mode of ``0o644`` instead of ``0o755`` when
+  using the default ``umask`` of ``0o22``.
+
+v0.8 (2014-08-01)
+~~~~~~~~~~~~~~~~~
+
+* Upgraded click to version 2.5.
+* Status action now returns exit code 1 if the daemon is not running.
+
+v0.7 (2014-06-23)
+~~~~~~~~~~~~~~~~~
+
+* Fixed bug that was causing an empty PID file on Python 3.
+* Upgraded click to version 2.1.
+* Open file discriptors are no longer closed by default. This functionality is now optional via the
+  ``close_open_files`` argument to ``Daemon()``.
+* Added ``is_worker`` argument to ``DaemonCLI()`` as well as the ``pass_daemon`` decorator.
+
+v0.6 (2014-06-10)
+~~~~~~~~~~~~~~~~~
+
+* Upgraded click to version 2.0.
+
+v0.5 (2014-06-09)
+~~~~~~~~~~~~~~~~~
+
+* Fixed literal octal formatting to work with Python 3.
+
+v0.4 (2014-05-19)
+~~~~~~~~~~~~~~~~~
+
+* Fixed bug with uptime calculation in status action.
+* Upgraded click to version 0.7.
+
+v0.3 (2014-05-14)
+~~~~~~~~~~~~~~~~~
+
+* Reorganized package and cleaned up code.
+
+v0.2 (2014-05-12)
+~~~~~~~~~~~~~~~~~
+
+* Renamed ``Daemon.get_actions()`` to ``Daemon.list_actions()``.
+* Improvements to documentation.
+* Fixed bug with non-detached mode when parent is in the same process group.
+
+v0.1 (2014-05-11)
+~~~~~~~~~~~~~~~~~
+
+* Initial release.
diff --git a/MANIFEST.in b/MANIFEST.in
index 9d5d250..0b499f1 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
 include LICENSE
 include README.rst
+include HISTORY.rst
diff --git a/PKG-INFO b/PKG-INFO
deleted file mode 100644
index df3870f..0000000
--- a/PKG-INFO
+++ /dev/null
@@ -1,459 +0,0 @@
-Metadata-Version: 1.1
-Name: daemonocle
-Version: 0.8
-Summary: A Python library for creating super fancy Unix daemons
-Home-page: http://github.com/jnrbsn/daemonocle
-Author: Jonathan Robson
-Author-email: jnrbsn at gmail.com
-License: MIT
-Description: daemonocle is a library for creating your own Unix-style daemons written in Python. It solves many
-        problems that other daemon libraries have and provides some really useful features you don't often
-        see in other daemons.
-        
-        .. contents:: **Table of Contents**
-          :backlinks: none
-        
-        Installation
-        ------------
-        
-        To install via pip::
-        
-            pip install daemonocle
-        
-        Or download the source code and install manually::
-        
-            git clone https://github.com/jnrbsn/daemonocle.git
-            cd daemonocle/
-            python setup.py install
-        
-        Basic Usage
-        -----------
-        
-        Here's a **really really** basic example:
-        
-        .. code:: python
-        
-            import sys
-            import time
-        
-            import daemonocle
-        
-            # This is your daemon. It sleeps, and then sleeps again.
-            def main():
-                while True:
-                    time.sleep(10)
-        
-            if __name__ == '__main__':
-                daemon = daemonocle.Daemon(
-                    worker=main,
-                    pidfile='/var/run/daemonocle_example.pid',
-                )
-                daemon.do_action(sys.argv[1])
-        
-        And here's the same example with logging and a `Shutdown Callback`_:
-        
-        .. code:: python
-        
-            import logging
-            import sys
-            import time
-        
-            import daemonocle
-        
-            def cb_shutdown(message, code):
-                logging.info('Daemon is stopping')
-                logging.debug(message)
-        
-            def main():
-                logging.basicConfig(
-                    filename='/var/log/daemonocle_example.log',
-                    level=logging.DEBUG, format='%(asctime)s [%(levelname)s] %(message)s',
-                )
-                logging.info('Daemon is starting')
-                while True:
-                    logging.debug('Still running')
-                    time.sleep(10)
-        
-            if __name__ == '__main__':
-                daemon = daemonocle.Daemon(
-                    worker=main,
-                    shutdown_callback=cb_shutdown,
-                    pidfile='/var/run/daemonocle_example.pid',
-                )
-                daemon.do_action(sys.argv[1])
-        
-        And here's what it looks like when you run it::
-        
-            user at host:~$ python example.py start
-            Starting example.py ... OK
-            user at host:~$ python example.py status
-            example.py -- pid: 1234, status: running, uptime: 1m, %cpu: 0.0, %mem: 0.0
-            user at host:~$ python example.py stop
-            Stopping example.py ... OK
-            user at host:~$ cat /var/log/daemonocle_example.log
-            2014-05-04 12:39:21,090 [INFO] Daemon is starting
-            2014-05-04 12:39:21,091 [DEBUG] Still running
-            2014-05-04 12:39:31,091 [DEBUG] Still running
-            2014-05-04 12:39:41,091 [DEBUG] Still running
-            2014-05-04 12:39:51,093 [DEBUG] Still running
-            2014-05-04 12:40:01,094 [DEBUG] Still running
-            2014-05-04 12:40:07,113 [INFO] Daemon is stopping
-            2014-05-04 12:40:07,114 [DEBUG] Terminated by SIGTERM (15)
-        
-        For more details, see the `Detailed Usage`_ section below.
-        
-        Rationale
-        ---------
-        
-        If you think about it, a lot of Unix daemons don't really know what the hell they're doing. Have you
-        ever found yourself in a situation that looked something like this? ::
-        
-            user at host:~$ sudo example start
-            starting example ... ok
-            user at host:~$ ps aux | grep example
-            user      1234  0.0  0.0   1234  1234 pts/1    S+   12:34   0:00 grep example
-            user at host:~$ sudo example start
-            starting example ... ok
-            user at host:~$ echo $?
-            0
-            user at host:~$ tail -f /var/log/example.log
-            ...
-        
-        Or something like this? ::
-        
-            user at host:~$ sudo example stop
-            stopping example ... ok
-            user at host:~$ ps aux | grep example
-            user       123  0.0  0.0   1234  1234 ?        Ss   00:00   0:00 /usr/local/bin/example
-            user      1234  0.0  0.0   1234  1234 pts/1    S+   12:34   0:00 grep example
-            user at host:~$ sudo example stop
-            stopping example ... ok
-            user at host:~$ ps aux | grep example
-            user       123  0.0  0.0   1234  1234 ?        Ss   00:00   0:00 /usr/local/bin/example
-            user      1240  0.0  0.0   1234  1234 pts/1    S+   12:34   0:00 grep example
-            user at host:~$ sudo kill -9 123
-            ...
-        
-        Or something like this? ::
-        
-            user at host:~$ sudo example status
-            Usage: example {start|stop|restart}
-            user at host:~$ ps aux | grep example
-            ...
-        
-        These are just a few examples of unnecessarily common problems. It doesn't have to be this way.
-        
-            **Note:** You might be thinking, "Why not just write a smarter start/stop shell script wrapper
-            for your daemon that checks whether or not it actually started, actually stopped, etc.?"
-            Seriously? **It doesn't have to be this way.** I believe daemons should be more self-aware. They
-            should handle their own problems most of the time, and your start/stop script should only be a
-            very thin wrapper around your daemon or simply a symlink to your daemon.
-        
-        The Problem
-        ~~~~~~~~~~~
-        
-        If you've ever dug deep into the nitty-gritty details of how daemonization works, you're probably
-        familiar with the `standard "double fork" paradigm <http://bit.ly/stevens-daemon>`_ first introduced
-        by W. Richard Stevens in the book `Advanced Programming in the UNIX Environment
-        <http://amzn.com/0321637739>`_. One of the problems with the standard way to implement this is that
-        if the final child dies immediately when it gets around to doing real work, the original parent
-        process (the one that actually had control of your terminal) is long gone. So all you know is that
-        the process got forked, but you have no idea if it actually kept running for more than a fraction of
-        a second. And let's face it, one of the most likely times for a daemon to die is immediately after
-        it starts (due to bad configuration, permissions, etc.).
-        
-        The next problem mentioned in the section above is when you try to stop a daemon, it doesn't
-        actually stop, and you have no idea that it didn't actually stop. This happens when a process
-        doesn't respond properly to a ``SIGTERM`` signal. It happens more often than it should. The problem
-        is not necessarily the fact that it didn't stop. It's the fact that you didn't *know* that it didn't
-        stop. The start/stop script knows that it successfully sent the signal and so it assumes success.
-        This also becomes a problem when your ``restart`` command blindly calls ``stop`` and then ``start``,
-        because it will try to start a new instance of the daemon before the previous one has exited.
-        
-        These are the biggest problems most daemons have in my opinion. daemonocle solves these problems and
-        provides many other "fancy" features.
-        
-        The Solution
-        ~~~~~~~~~~~~
-        
-        The problem with the daemon immediately dying on startup and you not knowing about it is solved by
-        having the first child (the immediate parent of the final child) sleep for one second and then call
-        ``os.waitpid(pid, os.WNOHANG)`` to see if the process is still running. This is what daemonocle
-        does. So if you're daemon dies within one second of starting, you'll know about it.
-        
-        This problem with the daemon not stopping and you not knowing about it is solved by simply waiting
-        for the process to finish (with a timeout). This is what daemonocle does. (Note: When a timeout
-        occurs, it doesn't try to send a ``SIGKILL``. This is not always what you'd want and often not a
-        good idea.)
-        
-        Other Useful Features
-        ~~~~~~~~~~~~~~~~~~~~~
-        
-        Below are some other useful features that daemononcle provides that you might not find elsewhere.
-        
-        The ``status`` Action
-        +++++++++++++++++++++
-        
-        There is a ``status`` action that not only displays whether or not the daemon is running and its
-        PID, but also the uptime of the daemon and the % CPU and % memory usage of all the processes in the
-        same process group as the daemon (which are probably its children). So if you have a daemon that
-        launches mulitple worker processes, the ``status`` action will show the % CPU and % memory usage of
-        all the workers combined.
-        
-        It might look something like this::
-        
-            user at host:~$ python example.py status
-            example.py -- pid: 1234, status: running, uptime: 12d 3h 4m, %cpu: 12.4, %mem: 4.5
-        
-        Slightly Smarter ``restart`` Action
-        +++++++++++++++++++++++++++++++++++
-        
-        Have you ever tried to restart a daemon only to realize that it's not actually running? Let me
-        guess: it just gave you an error and didn't start the daemon. A lot of the time this is not a
-        problem, but if you're trying to restart the daemon in an automated way, it's more annoying to have
-        to check if it's running and do either a ``start`` or ``restart`` accordingly. With daemonocle, if
-        you try to restart a daemon that's not running, it will give you a warning saying that it wasn't
-        running and then start the daemon. This is often what people expect.
-        
-        Self-Reload
-        +++++++++++
-        
-        Daemons that use daemonocle have the ability to reload themselves by simply calling
-        ``daemon.reload()`` where ``daemon`` is your ``daemonocle.Daemon`` instance. The execution of the
-        current daemon halts wherever ``daemon.reload()`` was called, and a new daemon is started up to
-        replace the current one. From your code's perspective, it's pretty much the same as a doing a
-        ``restart`` except that it's initiated from within the daemon itself and there's no signal handling
-        involved. Here's a basic example of a daemon that watches a config file and reloads itself when the
-        config file changes:
-        
-        .. code:: python
-        
-            import os
-            import sys
-            import time
-        
-            import daemonocle
-        
-            class FileWatcher(object):
-        
-                def __init__(self, filename, daemon):
-                    self._filename = filename
-                    self._daemon = daemon
-                    self._file_mtime = os.stat(self._filename).st_mtime
-        
-                def file_has_changed(self):
-                    current_mtime = os.stat(self._filename).st_mtime
-                    if current_mtime != self._file_mtime:
-                        self._file_mtime = current_mtime
-                        return True
-                    return False
-        
-                def watch(self):
-                    while True:
-                        if self.file_has_changed():
-                            self._daemon.reload()
-                        time.sleep(1)
-        
-            if __name__ == '__main__':
-                daemon = daemonocle.Daemon(pidfile='/var/run/daemonocle_example.pid')
-                fw = FileWatcher(filename='/etc/daemonocle_example.conf', daemon=daemon)
-                daemon.worker = fw.watch
-                daemon.do_action(sys.argv[1])
-        
-        Shutdown Callback
-        +++++++++++++++++
-        
-        You may have noticed from the `Basic Usage`_ section above that a ``shutdown_callback`` was defined.
-        This function gets called whenever the daemon is shutting down in a catchable way, which should be
-        most of the time except for a ``SIGKILL`` or if your server crashes unexpectedly or loses power or
-        something like that. This function can be used for doing any sort of cleanup that your daemon needs
-        to do. Also, if you want to log (to the logger of your choice) the reason for the shutdown and the
-        intended exit code, you can use the ``message`` and ``code`` arguments that will be passed to your
-        callback (your callback must take these two arguments).
-        
-        Non-Detached Mode
-        +++++++++++++++++
-        
-        This is not particularly interesting per se, but it's worth noting that in non-detached mode, your
-        daemon will do everything else you've configured it to do (i.e. ``setuid``, ``setgid``, ``chroot``,
-        etc.) except actually detaching from your terminal. So while you're testing, you can get an
-        extremely accurate view of how your daemon will behave in the wild. It's also worth noting that
-        self-reloading works in non-detached mode, which was a little tricky to figure out initially.
-        
-        File Descriptor Handling
-        ++++++++++++++++++++++++
-        
-        One of the things that daemons typically do is close all open file descriptors and establish new
-        ones for ``STDIN``, ``STDOUT``, ``STDERR`` that just point to ``/dev/null``. This is fine most of
-        the time, but if your worker is an instance method of a class that opens files in its ``__init__()``
-        method, then you'll run into problems if you're not careful. This is also a problem if you're
-        importing a module that leaves open files behind. For example, importing the
-        `random <https://docs.python.org/3/library/random.html>`_ standard library module in Python 3
-        results in an open file descriptor for ``/dev/urandom``.
-        
-        Since this "feature" of daemons often causes more problems than it solves, and the problems it
-        causes sometimes have strange side-effects that make it very difficult to troubleshoot, this feature
-        is optional and disabled by default in daemonocle via the ``close_open_files`` option.
-        
-        Detailed Usage
-        --------------
-        
-        The ``daemonocle.Daemon`` class is the main class for creating a daemon using daemonocle. Here's the
-        constructor signature for the class:
-        
-        .. code:: python
-        
-            class daemonocle.Daemon(
-                worker=None, shutdown_callback=None, prog=None, pidfile=None, detach=True,
-                uid=None, gid=None, workdir='/', chrootdir=None, umask=022, stop_timeout=10,
-                close_open_files=False)
-        
-        And here are descriptions of all the arguments:
-        
-        **worker**
-            The function that does all the work for your daemon.
-        
-        **shutdown_callback**
-            This will get called anytime the daemon is shutting down. It should take a ``message`` and a
-            ``code`` argument. The message is a human readable message that explains why the daemon is
-            shutting down. It might useful to log this message. The code is the exit code with which it
-            intends to exit. See `Shutdown Callback`_ for more details.
-        
-        **prog**
-            The name of your program to use in output messages. Default: ``os.path.basename(sys.argv[0])``
-        
-        **pidfile**
-            The path to a PID file to use. It's not required to use a PID file, but if you don't, you won't
-            be able to use all the features you might expect. Make sure the user your daemon is running as
-            has permission to write to the directory this file is in.
-        
-        **detach**
-            Whether or not to detach from the terminal and go into the background. See `Non-Detached Mode`_
-            for more details. Default: ``True``
-        
-        **uid**
-            The user ID to switch to when the daemon starts. The default is not to switch users.
-        
-        **gid**
-            The group ID to switch to when the daemon starts. The default is not to switch groups.
-        
-        **workdir**
-            The path to a directory to change to when the daemon starts. Note that a file system cannot be
-            unmounted if a process has its working directory on that file system. So if you change the
-            default, be careful about what you change it to. Default: ``"/"``
-        
-        **chrootdir**
-            The path to a directory to set as the effective root directory when the daemon starts. The
-            default is not to do anything.
-        
-        **umask**
-            The file creation mask ("umask") for the process. Default: ``022``
-        
-        **stop_timeout**
-            Number of seconds to wait for the daemon to stop before throwing an error. Default: ``10``
-        
-        **close_open_files**
-            Whether or not to close all open files when the daemon detaches. Default: ``False``
-        
-        Actions
-        ~~~~~~~
-        
-        The default actions are ``start``, ``stop``, ``restart``, and ``status``. You can get a list of
-        available actions using the ``daemonocle.Daemon.list_actions()`` method. The recommended way to call
-        an action is using the ``daemonocle.Daemon.do_action(action)`` method. The string name of an action
-        is the same as the method name except with dashes in place of underscores.
-        
-        If you want to create your own actions, simply subclass ``daemonocle.Daemon`` and add the
-        ``@daemonocle.expose_action`` decorator to your action method, and that's it.
-        
-        Here's an example:
-        
-        .. code:: python
-        
-            import daemonocle
-        
-            class MyDaemon(daemonocle.Daemon):
-        
-                @daemonocle.expose_action
-                def full_status(self):
-                    """Get more detailed status of the daemon."""
-                    pass
-        
-        Then, if you did the basic ``daemon.do_action(sys.argv[1])`` like in all the examples above, you can
-        call your action with a command like ``python example.py full-status``.
-        
-        Integration with mitsuhiko's click
-        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-        
-        daemonocle also provides an integration with `click <http://click.pocoo.org/>`_, the "composable
-        command line utility". The integration is in the form of a custom command class
-        ``daemonocle.cli.DaemonCLI`` that you can use in conjunction with the ``@click.command()`` decorator
-        to automatically generate a command line interface with subcommands for all your actions. It also
-        automatically daemonizes the decorated function. The decorated function becomes the worker, and the
-        actions are automatically mapped from click to daemonocle.
-        
-        Here's an example:
-        
-        .. code:: python
-        
-            import time
-        
-            import click
-            from daemonocle.cli import DaemonCLI
-        
-            @click.command(cls=DaemonCLI, daemon_params={'pidfile': '/var/run/example.pid'})
-            def main():
-                """This is my awesome daemon. It pretends to do work in the background."""
-                while True:
-                    time.sleep(10)
-        
-            if __name__ == '__main__':
-                main()
-        
-        Running this example would look something like this::
-        
-            user at host:~$ python example.py --help
-            Usage: example.py [<options>] <command> [<args>]...
-        
-              This is my awesome daemon. It pretends to do work in the background.
-        
-            Options:
-              --help  Show this message and exit.
-        
-            Commands:
-              start    Start the daemon.
-              stop     Stop the daemon.
-              restart  Stop then start the daemon.
-              status   Get the status of the daemon.
-            user at host:~$ python example.py start --help
-            Usage: example.py start [<options>]
-        
-              Start the daemon.
-        
-            Options:
-              --debug  Do NOT detach and run in the background.
-              --help   Show this message and exit.
-        
-        The ``daemonocle.cli.DaemonCLI`` class also accepts a ``daemon_class`` argument that can be a
-        subclass of ``daemonocle.Daemon``. It will use your custom class, automatically create subcommands
-        for any custom actions you've defined, and use the docstrings of the action methods as the help text
-        just like click usually does.
-        
-        This integration is entirely optional. daemonocle doesn't enforce any sort of argument parsing. You
-        can use argparse, optparse, or just plain ``sys.argv`` if you want.
-        
-        Bugs, Requests, Questions, etc.
-        -------------------------------
-        
-        Please create an `issue on GitHub <https://github.com/jnrbsn/daemonocle/issues>`_.
-        
-Keywords: daemon daemonize fork unix cli
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Operating System :: POSIX :: Linux
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
diff --git a/README.rst b/README.rst
index 77eefac..2816c9f 100644
--- a/README.rst
+++ b/README.rst
@@ -5,6 +5,12 @@ daemonocle
 
 -----
 
+.. image:: https://travis-ci.org/jnrbsn/daemonocle.svg?branch=master
+    :target: https://travis-ci.org/jnrbsn/daemonocle
+
+.. image:: https://coveralls.io/repos/github/jnrbsn/daemonocle/badge.svg?branch=master
+    :target: https://coveralls.io/github/jnrbsn/daemonocle
+
 daemonocle is a library for creating your own Unix-style daemons written in Python. It solves many
 problems that other daemon libraries have and provides some really useful features you don't often
 see in other daemons.
diff --git a/daemonocle.egg-info/PKG-INFO b/daemonocle.egg-info/PKG-INFO
deleted file mode 100644
index df3870f..0000000
--- a/daemonocle.egg-info/PKG-INFO
+++ /dev/null
@@ -1,459 +0,0 @@
-Metadata-Version: 1.1
-Name: daemonocle
-Version: 0.8
-Summary: A Python library for creating super fancy Unix daemons
-Home-page: http://github.com/jnrbsn/daemonocle
-Author: Jonathan Robson
-Author-email: jnrbsn at gmail.com
-License: MIT
-Description: daemonocle is a library for creating your own Unix-style daemons written in Python. It solves many
-        problems that other daemon libraries have and provides some really useful features you don't often
-        see in other daemons.
-        
-        .. contents:: **Table of Contents**
-          :backlinks: none
-        
-        Installation
-        ------------
-        
-        To install via pip::
-        
-            pip install daemonocle
-        
-        Or download the source code and install manually::
-        
-            git clone https://github.com/jnrbsn/daemonocle.git
-            cd daemonocle/
-            python setup.py install
-        
-        Basic Usage
-        -----------
-        
-        Here's a **really really** basic example:
-        
-        .. code:: python
-        
-            import sys
-            import time
-        
-            import daemonocle
-        
-            # This is your daemon. It sleeps, and then sleeps again.
-            def main():
-                while True:
-                    time.sleep(10)
-        
-            if __name__ == '__main__':
-                daemon = daemonocle.Daemon(
-                    worker=main,
-                    pidfile='/var/run/daemonocle_example.pid',
-                )
-                daemon.do_action(sys.argv[1])
-        
-        And here's the same example with logging and a `Shutdown Callback`_:
-        
-        .. code:: python
-        
-            import logging
-            import sys
-            import time
-        
-            import daemonocle
-        
-            def cb_shutdown(message, code):
-                logging.info('Daemon is stopping')
-                logging.debug(message)
-        
-            def main():
-                logging.basicConfig(
-                    filename='/var/log/daemonocle_example.log',
-                    level=logging.DEBUG, format='%(asctime)s [%(levelname)s] %(message)s',
-                )
-                logging.info('Daemon is starting')
-                while True:
-                    logging.debug('Still running')
-                    time.sleep(10)
-        
-            if __name__ == '__main__':
-                daemon = daemonocle.Daemon(
-                    worker=main,
-                    shutdown_callback=cb_shutdown,
-                    pidfile='/var/run/daemonocle_example.pid',
-                )
-                daemon.do_action(sys.argv[1])
-        
-        And here's what it looks like when you run it::
-        
-            user at host:~$ python example.py start
-            Starting example.py ... OK
-            user at host:~$ python example.py status
-            example.py -- pid: 1234, status: running, uptime: 1m, %cpu: 0.0, %mem: 0.0
-            user at host:~$ python example.py stop
-            Stopping example.py ... OK
-            user at host:~$ cat /var/log/daemonocle_example.log
-            2014-05-04 12:39:21,090 [INFO] Daemon is starting
-            2014-05-04 12:39:21,091 [DEBUG] Still running
-            2014-05-04 12:39:31,091 [DEBUG] Still running
-            2014-05-04 12:39:41,091 [DEBUG] Still running
-            2014-05-04 12:39:51,093 [DEBUG] Still running
-            2014-05-04 12:40:01,094 [DEBUG] Still running
-            2014-05-04 12:40:07,113 [INFO] Daemon is stopping
-            2014-05-04 12:40:07,114 [DEBUG] Terminated by SIGTERM (15)
-        
-        For more details, see the `Detailed Usage`_ section below.
-        
-        Rationale
-        ---------
-        
-        If you think about it, a lot of Unix daemons don't really know what the hell they're doing. Have you
-        ever found yourself in a situation that looked something like this? ::
-        
-            user at host:~$ sudo example start
-            starting example ... ok
-            user at host:~$ ps aux | grep example
-            user      1234  0.0  0.0   1234  1234 pts/1    S+   12:34   0:00 grep example
-            user at host:~$ sudo example start
-            starting example ... ok
-            user at host:~$ echo $?
-            0
-            user at host:~$ tail -f /var/log/example.log
-            ...
-        
-        Or something like this? ::
-        
-            user at host:~$ sudo example stop
-            stopping example ... ok
-            user at host:~$ ps aux | grep example
-            user       123  0.0  0.0   1234  1234 ?        Ss   00:00   0:00 /usr/local/bin/example
-            user      1234  0.0  0.0   1234  1234 pts/1    S+   12:34   0:00 grep example
-            user at host:~$ sudo example stop
-            stopping example ... ok
-            user at host:~$ ps aux | grep example
-            user       123  0.0  0.0   1234  1234 ?        Ss   00:00   0:00 /usr/local/bin/example
-            user      1240  0.0  0.0   1234  1234 pts/1    S+   12:34   0:00 grep example
-            user at host:~$ sudo kill -9 123
-            ...
-        
-        Or something like this? ::
-        
-            user at host:~$ sudo example status
-            Usage: example {start|stop|restart}
-            user at host:~$ ps aux | grep example
-            ...
-        
-        These are just a few examples of unnecessarily common problems. It doesn't have to be this way.
-        
-            **Note:** You might be thinking, "Why not just write a smarter start/stop shell script wrapper
-            for your daemon that checks whether or not it actually started, actually stopped, etc.?"
-            Seriously? **It doesn't have to be this way.** I believe daemons should be more self-aware. They
-            should handle their own problems most of the time, and your start/stop script should only be a
-            very thin wrapper around your daemon or simply a symlink to your daemon.
-        
-        The Problem
-        ~~~~~~~~~~~
-        
-        If you've ever dug deep into the nitty-gritty details of how daemonization works, you're probably
-        familiar with the `standard "double fork" paradigm <http://bit.ly/stevens-daemon>`_ first introduced
-        by W. Richard Stevens in the book `Advanced Programming in the UNIX Environment
-        <http://amzn.com/0321637739>`_. One of the problems with the standard way to implement this is that
-        if the final child dies immediately when it gets around to doing real work, the original parent
-        process (the one that actually had control of your terminal) is long gone. So all you know is that
-        the process got forked, but you have no idea if it actually kept running for more than a fraction of
-        a second. And let's face it, one of the most likely times for a daemon to die is immediately after
-        it starts (due to bad configuration, permissions, etc.).
-        
-        The next problem mentioned in the section above is when you try to stop a daemon, it doesn't
-        actually stop, and you have no idea that it didn't actually stop. This happens when a process
-        doesn't respond properly to a ``SIGTERM`` signal. It happens more often than it should. The problem
-        is not necessarily the fact that it didn't stop. It's the fact that you didn't *know* that it didn't
-        stop. The start/stop script knows that it successfully sent the signal and so it assumes success.
-        This also becomes a problem when your ``restart`` command blindly calls ``stop`` and then ``start``,
-        because it will try to start a new instance of the daemon before the previous one has exited.
-        
-        These are the biggest problems most daemons have in my opinion. daemonocle solves these problems and
-        provides many other "fancy" features.
-        
-        The Solution
-        ~~~~~~~~~~~~
-        
-        The problem with the daemon immediately dying on startup and you not knowing about it is solved by
-        having the first child (the immediate parent of the final child) sleep for one second and then call
-        ``os.waitpid(pid, os.WNOHANG)`` to see if the process is still running. This is what daemonocle
-        does. So if you're daemon dies within one second of starting, you'll know about it.
-        
-        This problem with the daemon not stopping and you not knowing about it is solved by simply waiting
-        for the process to finish (with a timeout). This is what daemonocle does. (Note: When a timeout
-        occurs, it doesn't try to send a ``SIGKILL``. This is not always what you'd want and often not a
-        good idea.)
-        
-        Other Useful Features
-        ~~~~~~~~~~~~~~~~~~~~~
-        
-        Below are some other useful features that daemononcle provides that you might not find elsewhere.
-        
-        The ``status`` Action
-        +++++++++++++++++++++
-        
-        There is a ``status`` action that not only displays whether or not the daemon is running and its
-        PID, but also the uptime of the daemon and the % CPU and % memory usage of all the processes in the
-        same process group as the daemon (which are probably its children). So if you have a daemon that
-        launches mulitple worker processes, the ``status`` action will show the % CPU and % memory usage of
-        all the workers combined.
-        
-        It might look something like this::
-        
-            user at host:~$ python example.py status
-            example.py -- pid: 1234, status: running, uptime: 12d 3h 4m, %cpu: 12.4, %mem: 4.5
-        
-        Slightly Smarter ``restart`` Action
-        +++++++++++++++++++++++++++++++++++
-        
-        Have you ever tried to restart a daemon only to realize that it's not actually running? Let me
-        guess: it just gave you an error and didn't start the daemon. A lot of the time this is not a
-        problem, but if you're trying to restart the daemon in an automated way, it's more annoying to have
-        to check if it's running and do either a ``start`` or ``restart`` accordingly. With daemonocle, if
-        you try to restart a daemon that's not running, it will give you a warning saying that it wasn't
-        running and then start the daemon. This is often what people expect.
-        
-        Self-Reload
-        +++++++++++
-        
-        Daemons that use daemonocle have the ability to reload themselves by simply calling
-        ``daemon.reload()`` where ``daemon`` is your ``daemonocle.Daemon`` instance. The execution of the
-        current daemon halts wherever ``daemon.reload()`` was called, and a new daemon is started up to
-        replace the current one. From your code's perspective, it's pretty much the same as a doing a
-        ``restart`` except that it's initiated from within the daemon itself and there's no signal handling
-        involved. Here's a basic example of a daemon that watches a config file and reloads itself when the
-        config file changes:
-        
-        .. code:: python
-        
-            import os
-            import sys
-            import time
-        
-            import daemonocle
-        
-            class FileWatcher(object):
-        
-                def __init__(self, filename, daemon):
-                    self._filename = filename
-                    self._daemon = daemon
-                    self._file_mtime = os.stat(self._filename).st_mtime
-        
-                def file_has_changed(self):
-                    current_mtime = os.stat(self._filename).st_mtime
-                    if current_mtime != self._file_mtime:
-                        self._file_mtime = current_mtime
-                        return True
-                    return False
-        
-                def watch(self):
-                    while True:
-                        if self.file_has_changed():
-                            self._daemon.reload()
-                        time.sleep(1)
-        
-            if __name__ == '__main__':
-                daemon = daemonocle.Daemon(pidfile='/var/run/daemonocle_example.pid')
-                fw = FileWatcher(filename='/etc/daemonocle_example.conf', daemon=daemon)
-                daemon.worker = fw.watch
-                daemon.do_action(sys.argv[1])
-        
-        Shutdown Callback
-        +++++++++++++++++
-        
-        You may have noticed from the `Basic Usage`_ section above that a ``shutdown_callback`` was defined.
-        This function gets called whenever the daemon is shutting down in a catchable way, which should be
-        most of the time except for a ``SIGKILL`` or if your server crashes unexpectedly or loses power or
-        something like that. This function can be used for doing any sort of cleanup that your daemon needs
-        to do. Also, if you want to log (to the logger of your choice) the reason for the shutdown and the
-        intended exit code, you can use the ``message`` and ``code`` arguments that will be passed to your
-        callback (your callback must take these two arguments).
-        
-        Non-Detached Mode
-        +++++++++++++++++
-        
-        This is not particularly interesting per se, but it's worth noting that in non-detached mode, your
-        daemon will do everything else you've configured it to do (i.e. ``setuid``, ``setgid``, ``chroot``,
-        etc.) except actually detaching from your terminal. So while you're testing, you can get an
-        extremely accurate view of how your daemon will behave in the wild. It's also worth noting that
-        self-reloading works in non-detached mode, which was a little tricky to figure out initially.
-        
-        File Descriptor Handling
-        ++++++++++++++++++++++++
-        
-        One of the things that daemons typically do is close all open file descriptors and establish new
-        ones for ``STDIN``, ``STDOUT``, ``STDERR`` that just point to ``/dev/null``. This is fine most of
-        the time, but if your worker is an instance method of a class that opens files in its ``__init__()``
-        method, then you'll run into problems if you're not careful. This is also a problem if you're
-        importing a module that leaves open files behind. For example, importing the
-        `random <https://docs.python.org/3/library/random.html>`_ standard library module in Python 3
-        results in an open file descriptor for ``/dev/urandom``.
-        
-        Since this "feature" of daemons often causes more problems than it solves, and the problems it
-        causes sometimes have strange side-effects that make it very difficult to troubleshoot, this feature
-        is optional and disabled by default in daemonocle via the ``close_open_files`` option.
-        
-        Detailed Usage
-        --------------
-        
-        The ``daemonocle.Daemon`` class is the main class for creating a daemon using daemonocle. Here's the
-        constructor signature for the class:
-        
-        .. code:: python
-        
-            class daemonocle.Daemon(
-                worker=None, shutdown_callback=None, prog=None, pidfile=None, detach=True,
-                uid=None, gid=None, workdir='/', chrootdir=None, umask=022, stop_timeout=10,
-                close_open_files=False)
-        
-        And here are descriptions of all the arguments:
-        
-        **worker**
-            The function that does all the work for your daemon.
-        
-        **shutdown_callback**
-            This will get called anytime the daemon is shutting down. It should take a ``message`` and a
-            ``code`` argument. The message is a human readable message that explains why the daemon is
-            shutting down. It might useful to log this message. The code is the exit code with which it
-            intends to exit. See `Shutdown Callback`_ for more details.
-        
-        **prog**
-            The name of your program to use in output messages. Default: ``os.path.basename(sys.argv[0])``
-        
-        **pidfile**
-            The path to a PID file to use. It's not required to use a PID file, but if you don't, you won't
-            be able to use all the features you might expect. Make sure the user your daemon is running as
-            has permission to write to the directory this file is in.
-        
-        **detach**
-            Whether or not to detach from the terminal and go into the background. See `Non-Detached Mode`_
-            for more details. Default: ``True``
-        
-        **uid**
-            The user ID to switch to when the daemon starts. The default is not to switch users.
-        
-        **gid**
-            The group ID to switch to when the daemon starts. The default is not to switch groups.
-        
-        **workdir**
-            The path to a directory to change to when the daemon starts. Note that a file system cannot be
-            unmounted if a process has its working directory on that file system. So if you change the
-            default, be careful about what you change it to. Default: ``"/"``
-        
-        **chrootdir**
-            The path to a directory to set as the effective root directory when the daemon starts. The
-            default is not to do anything.
-        
-        **umask**
-            The file creation mask ("umask") for the process. Default: ``022``
-        
-        **stop_timeout**
-            Number of seconds to wait for the daemon to stop before throwing an error. Default: ``10``
-        
-        **close_open_files**
-            Whether or not to close all open files when the daemon detaches. Default: ``False``
... 1600 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-daemonocle.git



More information about the Python-modules-commits mailing list