Hello community,

here is the log from the commit of package python-python-daemon for 
openSUSE:Factory checked in at 2016-02-16 09:18:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python-daemon (Old)
 and      /work/SRC/openSUSE:Factory/.python-python-daemon.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-python-daemon"

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-python-daemon/python-python-daemon.changes    
    2015-09-08 17:42:44.000000000 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-python-daemon.new/python-python-daemon.changes
   2016-02-16 09:18:22.000000000 +0100
@@ -1,0 +2,18 @@
+Mon Feb  1 10:41:01 UTC 2016 - [email protected]
+
+- update to 2.1.1
+  * Default ‘initgroups’ option to False. Using ‘os.initgroups’ requires
+    permission to set process GID, so this now needs to be explicitly
+    requested.
+
+-------------------------------------------------------------------
+Mon Dec  7 22:37:30 UTC 2015 - [email protected]
+
+- update to 2.1.0:
+  * Add a DaemonContext option, ‘initgroups’, which specifies whether to
+    set the daemon process's supplementary groups.
+  * Set the process groups using ‘os.initgroups’.
+    Thanks to Malcolm Purvis for contributing an implementation of this
+    feature.
+
+-------------------------------------------------------------------

Old:
----
  python-daemon-2.0.6.tar.gz

New:
----
  python-daemon-2.1.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-python-daemon.spec ++++++
--- /var/tmp/diff_new_pack.ToW5tN/_old  2016-02-16 09:18:23.000000000 +0100
+++ /var/tmp/diff_new_pack.ToW5tN/_new  2016-02-16 09:18:23.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python-python-daemon
-Version:        2.0.6
+Version:        2.1.1
 Release:        0
 Url:            http://pypi.python.org/pypi/python-daemon/
 Summary:        Library to implement a well-behaved Unix daemon process

++++++ python-daemon-2.0.6.tar.gz -> python-daemon-2.1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/ChangeLog 
new/python-daemon-2.1.1/ChangeLog
--- old/python-daemon-2.0.6/ChangeLog   2015-08-30 11:14:42.000000000 +0200
+++ new/python-daemon-2.1.1/ChangeLog   2016-01-30 03:04:46.000000000 +0100
@@ -1,3 +1,27 @@
+Version 2.1.1
+=============
+
+:Released: 2016-01-30
+:Maintainer: Ben Finney <[email protected]>
+
+* Default ‘initgroups’ option to False. Using ‘os.initgroups’ requires
+  permission to set process GID, so this now needs to be explicitly
+  requested.
+
+
+Version 2.1.0
+=============
+
+:Released: 2015-11-26
+:Maintainer: Ben Finney <[email protected]>
+
+* Add a DaemonContext option, ‘initgroups’, which specifies whether to
+  set the daemon process's supplementary groups.
+* Set the process groups using ‘os.initgroups’.
+  Thanks to Malcolm Purvis for contributing an implementation of this
+  feature.
+
+
 Version 2.0.6
 =============
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/PKG-INFO 
new/python-daemon-2.1.1/PKG-INFO
--- old/python-daemon-2.0.6/PKG-INFO    2015-08-30 11:16:48.000000000 +0200
+++ new/python-daemon-2.1.1/PKG-INFO    2016-01-30 03:06:58.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-daemon
-Version: 2.0.6
+Version: 2.1.1
 Summary: Library to implement a well-behaved Unix daemon process.
 Home-page: https://alioth.debian.org/projects/python-daemon/
 Author: Ben Finney
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/daemon/__init__.py 
new/python-daemon-2.1.1/daemon/__init__.py
--- old/python-daemon-2.0.6/daemon/__init__.py  2015-01-07 06:29:20.000000000 
+0100
+++ new/python-daemon-2.1.1/daemon/__init__.py  2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # daemon/__init__.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2009–2015 Ben Finney <[email protected]>
+# Copyright © 2009–2016 Ben Finney <[email protected]>
 # Copyright © 2006 Robert Niederreiter
 #
 # This is free software: you may copy, modify, and/or distribute this work
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/daemon/_metadata.py 
new/python-daemon-2.1.1/daemon/_metadata.py
--- old/python-daemon-2.0.6/daemon/_metadata.py 2015-01-22 21:14:50.000000000 
+0100
+++ new/python-daemon-2.1.1/daemon/_metadata.py 2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # daemon/_metadata.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/daemon/daemon.py 
new/python-daemon-2.1.1/daemon/daemon.py
--- old/python-daemon-2.0.6/daemon/daemon.py    2015-08-30 11:10:43.000000000 
+0200
+++ new/python-daemon-2.1.1/daemon/daemon.py    2016-01-30 03:02:20.000000000 
+0100
@@ -3,7 +3,7 @@
 # daemon/daemon.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 # Copyright © 2007–2008 Robert Niederreiter, Jens Klein
 # Copyright © 2004–2005 Chad J. Schroeder
 # Copyright © 2003 Clark Evans
@@ -22,6 +22,7 @@
 
 import os
 import sys
+import pwd
 import resource
 import errno
 import signal
@@ -196,6 +197,15 @@
             relinquish any effective privilege elevation inherited by the
             process.
 
+        `initgroups`
+            :Default: ``False``
+
+            If true, set the daemon process's supplementary groups as
+            determined by the specified `uid`.
+
+            This will require that the current process UID has
+            permission to change the process's owning GID.
+
         `prevent_core`
             :Default: ``True``
 
@@ -237,6 +247,7 @@
             umask=0,
             uid=None,
             gid=None,
+            initgroups=False,
             prevent_core=True,
             detach_process=None,
             files_preserve=None,
@@ -263,6 +274,7 @@
         if gid is None:
             gid = os.getgid()
         self.gid = gid
+        self.initgroups = initgroups
 
         if detach_process is None:
             detach_process = is_detach_process_context_required()
@@ -303,8 +315,13 @@
               by the process. Note that the specified directory needs to
               already be set up for this purpose.
 
-            * Set the process UID and GID to the `uid` and `gid` attribute
-              values.
+            * Set the process owner (UID and GID) to the `uid` and `gid`
+              attribute values.
+
+              If the `initgroups` attribute is true, also set the process's
+              supplementary groups to all the user's groups (i.e. those
+              groups whose membership includes the username corresponding
+              to `uid`).
 
             * Close all open file descriptors. This excludes those listed in
               the `files_preserve` attribute, and those that correspond to the
@@ -353,7 +370,7 @@
 
         change_file_creation_mask(self.umask)
         change_working_directory(self.working_directory)
-        change_process_owner(self.uid, self.gid)
+        change_process_owner(self.uid, self.gid, self.initgroups)
 
         if self.detach_process:
             detach_process_context()
@@ -580,20 +597,47 @@
         raise error
 
 
-def change_process_owner(uid, gid):
-    """ Change the owning UID and GID of this process.
+def get_username_for_uid(uid):
+    """ Get the username for the specified UID. """
+    passwd_entry = pwd.getpwuid(uid)
+    username = passwd_entry.pw_name
+
+    return username
+
+
+def change_process_owner(uid, gid, initgroups=False):
+    """ Change the owning UID, GID, and groups of this process.
 
         :param uid: The target UID for the daemon process.
         :param gid: The target GID for the daemon process.
+        :param initgroups: If true, initialise the supplementary
+            groups of the process.
         :return: ``None``.
 
-        Set the GID then the UID of the process (in that order, to avoid
-        permission errors) to the specified `gid` and `uid` values.
-        Requires appropriate OS privileges for this process.
+        Sets the owning GID and UID of the process (in that order, to
+        avoid permission errors) to the specified `gid` and `uid`
+        values.
+
+        If `initgroups` is true, the supplementary groups of the
+        process are also initialised, with those corresponding to the
+        username for the target UID.
+
+        All these operations require appropriate OS privileges. If
+        permission is denied, a ``DaemonOSEnvironmentError`` is
+        raised.
 
         """
     try:
-        os.setgid(gid)
+        username = get_username_for_uid(uid)
+    except KeyError:
+        # We don't have a username to pass to ‘os.initgroups’.
+        initgroups = False
+
+    try:
+        if initgroups:
+            os.initgroups(username, gid)
+        else:
+            os.setgid(gid)
         os.setuid(uid)
     except Exception as exc:
         error = DaemonOSEnvironmentError(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/daemon/pidfile.py 
new/python-daemon-2.1.1/daemon/pidfile.py
--- old/python-daemon-2.0.6/daemon/pidfile.py   2015-01-10 05:51:52.000000000 
+0100
+++ new/python-daemon-2.1.1/daemon/pidfile.py   2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # daemon/pidfile.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/daemon/runner.py 
new/python-daemon-2.1.1/daemon/runner.py
--- old/python-daemon-2.0.6/daemon/runner.py    2015-02-02 03:50:22.000000000 
+0100
+++ new/python-daemon-2.1.1/daemon/runner.py    2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # daemon/runner.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2009–2015 Ben Finney <[email protected]>
+# Copyright © 2009–2016 Ben Finney <[email protected]>
 # Copyright © 2007–2008 Robert Niederreiter, Jens Klein
 # Copyright © 2003 Clark Evans
 # Copyright © 2002 Noah Spurrier
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/doc/CREDITS 
new/python-daemon-2.1.1/doc/CREDITS
--- old/python-daemon-2.0.6/doc/CREDITS 2014-12-23 07:12:27.000000000 +0100
+++ new/python-daemon-2.1.1/doc/CREDITS 2015-11-26 09:24:29.000000000 +0100
@@ -1,7 +1,7 @@
 Credits for contributors to ‘python-daemon’
 ###########################################
 
-:Updated: 2014-12-23
+:Updated: 2015-11-26
 
 The ‘python-daemon’ library is the work of many contributors.
 
@@ -32,6 +32,7 @@
 
 People who have also contributed substantial improvements:
 
+* Malcolm Purvis
 
 
 ..
@@ -46,7 +47,7 @@
     mode: text
     mode: rst
     time-stamp-format: "%:y-%02m-%02d"
-    time-stamp-start: "^:Updated:[         ]+"
+    time-stamp-start: "^:Updated:[      ]+"
     time-stamp-end: "$"
     time-stamp-line-limit: 20
     End:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/doc/TODO 
new/python-daemon-2.1.1/doc/TODO
--- old/python-daemon-2.0.6/doc/TODO    2015-01-10 12:14:25.000000000 +0100
+++ new/python-daemon-2.1.1/doc/TODO    2015-11-27 00:49:57.000000000 +0100
@@ -1,7 +1,7 @@
 TODO for ‘python-daemon’ library
 ################################
 
-:Updated: 2015-01-10
+:Updated: 2015-11-27
 
 =======
 PENDING
@@ -16,6 +16,9 @@
 * Evaluate switching to ‘flufl.lock’ library for PID lockfile behaviour
   <http://pypi.python.org/pypi/flufl.lock>_.
 
+* Evaluate switching to ‘Fasteners’ library for PID lockfile behaviour
+  <https://pypi.python.org/pypi/fasteners>_.
+
 Features
 ========
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/doc/hacking.txt 
new/python-daemon-2.1.1/doc/hacking.txt
--- old/python-daemon-2.0.6/doc/hacking.txt     2014-11-28 08:20:04.000000000 
+0100
+++ new/python-daemon-2.1.1/doc/hacking.txt     2015-09-27 03:14:46.000000000 
+0200
@@ -2,7 +2,7 @@
 #################
 
 :Author: Ben Finney <[email protected]>
-:Updated: 2014-11-28
+:Updated: 2015-09-27
 
 
 Project layout
@@ -23,18 +23,53 @@
 Python
 ------
 
-All Python code should conform to the guidelines in PEP8_. In
-particular:
+All Python code should conform to the guidelines in :PEP:`8` and :PEP:`257`.
+In particular:
 
-* Indent each level using 4 spaces (``U+0020 SPACE``), and no TABs
-  (``U+0008 CHARACTER TABULATION``).
+Indentation
++++++++++++
+
+* Indent each level using 4 space characters (``U+0020 SPACE``).
+
+* Indent continuation lines two levels (8 spaces). This will help
+  distinguish them from adjacent code blocks indented one level.
+
+  Do not attempt to align continuation lines with characters on the
+  previous line.
+
+* Do not insert TAB (``U+0008 CHARACTER TABULATION``) characters into
+  source code. This allows the code to render the same in different
+  programs, and improves the ability to cut-and-paste the code.
+
+Example::
+
+    flim = flambake(
+            foo=eeny.meeny.miney.moe.Catcher(),
+            bar="eggs", baz="spam")
+    found_anomolous_wibble = False
+    for wibble in flim:
+        if wibble in [
+                zork for zork in zorkulate(wibble)]:
+            found_anomolous_wibble = True
+            break
+        wibble_accumulator.append(wibble)
+    zinkify(wibble_accumulator)
+
+Naming
+++++++
 
 * Name modules in lower case, ``multiplewordslikethis``.
 
 * Name classes in title case, ``MultipleWordsLikeThis``.
 
-* Name functions, instances and other variables in lower case,
-  ``multiple_words_like_this``.
+* Name functions, instances, and other variables in lower case,
+  ``multiplewordslikethis`` or ``multiple_words_like_this``.
+
+* Do not choose ``camelCaseNames``, which are inconsistently
+  capitalised.
+
+Documenting code
+++++++++++++++++
 
 * Every module, class, and function has a Python doc string explaining
   its purpose and API.
@@ -42,7 +77,7 @@
   *Exception*: Functions whose purpose and API are mandated by Python
   itself (dunder-named methods) do not need a doc string.
 
-* Doc strings are written as triple-quoted strings.
+* Every doc string conforms to :PEP:`257`. Additionally:
 
   * The text of the doc string is marked up with reStructuredText.
 
@@ -68,45 +103,49 @@
   Example::
 
     def frobnicate(spam, algorithm="dv"):
-        """ Perform frobnication on ``spam``.
+        """ Perform frobnication on the `spam` travortionate.
 
             :param spam: A travortionate (as a sequence of strings).
             :param algorithm: The name of the algorithm to use for
                 frobnicating the travortionate.
             :return: The frobnicated travortionate, if it is
-                non-empty; otherwise None.
+                non-empty; otherwise ``None``.
 
             The frobnication is done by the Dietzel-Venkman algorithm,
-            and optimises for the case where ``spam`` is freebled and
+            and optimises for the case where `spam` is freebled and
             agglutinative.
 
             """
         spagnify(spam)
         # …
 
+Import statements
++++++++++++++++++
+
 * All ``import`` statements appear at the top of the module.
 
-* Each ``import`` statement imports a single module, or multiple names
-  from a single module.
+* Each ``import`` statement imports a single module, or (using
+  ``from``) multiple names from a single module.
 
   Example::
 
     import sys
     import os
-    from spam import foo, bar, baz
-
-..  _PEP8: http://www.python.org/dev/peps/pep-0008/
+    from spam import (foo, bar, baz)
 
-Additional style guidelines:
+Additional style guidelines
++++++++++++++++++++++++++++
 
 * All text files (including program code) are encoded in UTF-8.
 
 * A page break (``U+000C FORM FEED``) whitespace character is used
-  within a module to break up semantically separate areas of the
+  within a text file to break up semantically separate areas of the
   module.
 
 * Editor hints for Emacs and Vim appear in a comment block at the
-  file's end::
+  file's end.
+
+  For Python source code::
 
       
       # Local variables:
@@ -115,6 +154,16 @@
       # End:
       # vim: fileencoding=utf-8 filetype=python :
 
+  For reStructuredText documents::
+
+      
+      # Local variables:
+      # coding: utf-8
+      # mode: text
+      # mode: rst
+      # End:
+      # vim: fileencoding=utf-8 filetype=rst :
+
 
 Unit tests
 ==========
@@ -173,7 +222,7 @@
     coding: utf-8
     mode: rst
     time-stamp-format: "%:y-%02m-%02d"
-    time-stamp-start: "^:Updated:[     ]+"
+    time-stamp-start: "^:Updated:[      ]+"
     time-stamp-end: "$"
     time-stamp-line-limit: 20
     End:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/python_daemon.egg-info/PKG-INFO 
new/python-daemon-2.1.1/python_daemon.egg-info/PKG-INFO
--- old/python-daemon-2.0.6/python_daemon.egg-info/PKG-INFO     2015-08-30 
11:16:48.000000000 +0200
+++ new/python-daemon-2.1.1/python_daemon.egg-info/PKG-INFO     2016-01-30 
03:06:44.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-daemon
-Version: 2.0.6
+Version: 2.1.1
 Summary: Library to implement a well-behaved Unix daemon process.
 Home-page: https://alioth.debian.org/projects/python-daemon/
 Author: Ben Finney
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-daemon-2.0.6/python_daemon.egg-info/version_info.json 
new/python-daemon-2.1.1/python_daemon.egg-info/version_info.json
--- old/python-daemon-2.0.6/python_daemon.egg-info/version_info.json    
2015-08-30 11:16:48.000000000 +0200
+++ new/python-daemon-2.1.1/python_daemon.egg-info/version_info.json    
2016-01-30 03:06:44.000000000 +0100
@@ -1,6 +1,6 @@
 {
-    "release_date": "2015-08-30", 
-    "version": "2.0.6", 
-    "maintainer": "Ben Finney <[email protected]>", 
-    "body": "* Lower dependency for \u2018unittest2\u2019, we can work with an 
earlier version.\n* Specify development status \u201cProduction/Stable\u201d in 
Trove classifiers.\n* Migrate to \u2018mock\u2019 version 1.3 with 
corresponding API changes.\n* Use current Python concept of 
\u201cbasestring\u201d to test for an attribute name.\n  Thanks to Arthur de 
Jong for the bug report.\n"
+    "release_date": "2016-01-30",
+    "version": "2.1.1",
+    "maintainer": "Ben Finney <[email protected]>",
+    "body": "* Default \u2018initgroups\u2019 option to False. Using 
\u2018os.initgroups\u2019 requires\n  permission to set process GID, so this 
now needs to be explicitly requested.\n"
 }
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/setup.cfg 
new/python-daemon-2.1.1/setup.cfg
--- old/python-daemon-2.0.6/setup.cfg   2015-08-30 11:16:48.000000000 +0200
+++ new/python-daemon-2.1.1/setup.cfg   2016-01-30 03:06:58.000000000 +0100
@@ -8,7 +8,7 @@
 sign = true
 
 [egg_info]
-tag_build = 
-tag_date = 0
 tag_svn_revision = 0
+tag_date = 0
+tag_build = 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/setup.py 
new/python-daemon-2.1.1/setup.py
--- old/python-daemon-2.0.6/setup.py    2015-08-30 11:08:58.000000000 +0200
+++ new/python-daemon-2.1.1/setup.py    2016-01-30 03:01:02.000000000 +0100
@@ -3,7 +3,7 @@
 # setup.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 # Copyright © 2008 Robert Niederreiter, Jens Klein
 #
 # This is free software: you may copy, modify, and/or distribute this work
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test/__init__.py 
new/python-daemon-2.1.1/test/__init__.py
--- old/python-daemon-2.0.6/test/__init__.py    2015-01-10 05:51:02.000000000 
+0100
+++ new/python-daemon-2.1.1/test/__init__.py    2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # test/__init__.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test/scaffold.py 
new/python-daemon-2.1.1/test/scaffold.py
--- old/python-daemon-2.0.6/test/scaffold.py    2015-02-22 20:46:58.000000000 
+0100
+++ new/python-daemon-2.1.1/test/scaffold.py    2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # test/scaffold.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2007–2015 Ben Finney <[email protected]>
+# Copyright © 2007–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
@@ -38,13 +38,6 @@
 import testtools.testcase
 
 
-test_dir = os.path.dirname(os.path.abspath(__file__))
-parent_dir = os.path.dirname(test_dir)
-if not test_dir in sys.path:
-    sys.path.insert(1, test_dir)
-if not parent_dir in sys.path:
-    sys.path.insert(1, parent_dir)
-
 # Disable all but the most critical logging messages.
 logging.disable(logging.CRITICAL)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test/test_daemon.py 
new/python-daemon-2.1.1/test/test_daemon.py
--- old/python-daemon-2.0.6/test/test_daemon.py 2015-08-30 11:10:43.000000000 
+0200
+++ new/python-daemon-2.1.1/test/test_daemon.py 2016-01-30 03:02:20.000000000 
+0100
@@ -3,7 +3,7 @@
 # test/test_daemon.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
@@ -17,6 +17,7 @@
 
 import os
 import sys
+import pwd
 import tempfile
 import resource
 import errno
@@ -84,6 +85,29 @@
     testcase.mock_pidlockfile = mock.MagicMock()
     testcase.mock_pidlockfile.path = testcase.fake_pidfile_path
 
+    testcase.test_pwent = pwd.struct_passwd(sequence=[
+            testcase.getUniqueString(), # pw_name
+            testcase.getUniqueString(), # pw_passwd
+            testcase.getUniqueInteger(), # pw_uid
+            testcase.getUniqueInteger(), # pw_gid
+            testcase.getUniqueString(), # pw_gecos
+            testcase.getUniqueString(), # pw_dir
+            testcase.getUniqueString(), # pw_shell
+            ])
+    def fake_getpwuid(uid):
+        pwent = None
+        if uid == testcase.test_pwent.pw_uid:
+            pwent = testcase.test_pwent
+        else:
+            raise KeyError("getpwuid(): uid not found: %(uid)r" % vars())
+        return pwent
+
+    func_patcher_pwd_getpwuid = mock.patch.object(
+            pwd, "getpwuid",
+            side_effect=fake_getpwuid)
+    func_patcher_pwd_getpwuid.start()
+    testcase.addCleanup(func_patcher_pwd_getpwuid.stop)
+
     testcase.daemon_context_args = dict(
             stdin=testcase.stream_files_by_name['stdin'],
             stdout=testcase.stream_files_by_name['stdout'],
@@ -169,7 +193,7 @@
     def test_has_specified_uid(self):
         """ Should have specified uid option. """
         args = dict(
-                uid=object(),
+                uid=self.getUniqueInteger(),
                 )
         expected_id = args['uid']
         instance = daemon.daemon.DaemonContext(**args)
@@ -185,7 +209,7 @@
     def test_has_specified_gid(self):
         """ Should have specified gid option. """
         args = dict(
-                gid=object(),
+                gid=self.getUniqueInteger(),
                 )
         expected_id = args['gid']
         instance = daemon.daemon.DaemonContext(**args)
@@ -198,6 +222,22 @@
         instance = daemon.daemon.DaemonContext(**args)
         self.assertEqual(expected_id, instance.gid)
 
+    def test_has_specified_initgroups(self):
+        """ Should have specified `initgroups` option. """
+        args = dict(
+                initgroups=False,
+                )
+        expected_value = args['initgroups']
+        instance = daemon.daemon.DaemonContext(**args)
+        self.assertEqual(expected_value, instance.initgroups)
+
+    def test_has_default_initgroups(self):
+        """ Should have default `initgroups` option. """
+        args = dict()
+        expected_value = False
+        instance = daemon.daemon.DaemonContext(**args)
+        self.assertEqual(expected_value, instance.initgroups)
+
     def test_has_specified_detach_process(self):
         """ Should have specified detach_process option. """
         args = dict(
@@ -359,7 +399,7 @@
                 mock.call.prevent_core_dump(),
                 mock.call.change_file_creation_mask(mock.ANY),
                 mock.call.change_working_directory(mock.ANY),
-                mock.call.change_process_owner(mock.ANY, mock.ANY),
+                mock.call.change_process_owner(mock.ANY, mock.ANY, mock.ANY),
                 mock.call.detach_process_context(),
                 mock.call.DaemonContext._make_signal_handler_map(),
                 mock.call.set_signal_handlers(mock.ANY),
@@ -436,16 +476,18 @@
         self.mock_module_daemon.change_file_creation_mask.assert_called_with(
                 umask)
 
-    def test_changes_owner_to_specified_uid_and_gid(self):
-        """ Should change process UID and GID to `uid` and `gid` options. """
+    def test_changes_owner_to_specified_uid_and_gid_and_initgroups(self):
+        """ Should change owner using `uid`, `gid`, `initgroups` options. """
         instance = self.test_instance
-        uid = object()
-        gid = object()
-        instance.uid = uid
-        instance.gid = gid
+        test_uid = self.getUniqueInteger()
+        test_gid = self.getUniqueInteger()
+        test_initgroups = object()
+        instance.uid = test_uid
+        instance.gid = test_gid
+        instance.initgroups = test_initgroups
         instance.open()
         self.mock_module_daemon.change_process_owner.assert_called_with(
-                uid, gid)
+                test_uid, test_gid, test_initgroups)
 
     def test_detaches_process_context(self):
         """ Should request detach of process context. """
@@ -992,6 +1034,7 @@
         self.assertIn(unicode(test_error), unicode(exc))
 
 
[email protected](os, "initgroups")
 @mock.patch.object(os, "setgid")
 @mock.patch.object(os, "setuid")
 class change_process_owner_TestCase(scaffold.TestCase):
@@ -1001,17 +1044,43 @@
         """ Set up test fixtures. """
         super(change_process_owner_TestCase, self).setUp()
 
-        self.test_uid = object()
-        self.test_gid = object()
+        setup_daemon_context_fixtures(self)
+
+        self.test_uid = self.test_pwent.pw_uid
+        self.test_gid = self.test_pwent.pw_gid
         self.test_args = dict(
                 uid=self.test_uid,
                 gid=self.test_gid,
                 )
 
-    def test_changes_gid_and_uid_in_order(
+    def test_sets_groups_and_uid_in_order(
+            self,
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should change process groups and UID in correct order.
+
+            Since the process requires appropriate privilege to use
+            either of `setuid` or `setgid`, changing the UID must be
+            done last.
+
+            """
+        args = self.test_args
+        args['initgroups'] = True
+        mock_os_module = mock.MagicMock()
+        mock_os_module.attach_mock(mock_func_os_setuid, "setuid")
+        mock_os_module.attach_mock(mock_func_os_setgid, "setgid")
+        mock_os_module.attach_mock(mock_func_os_initgroups, "initgroups")
+        daemon.daemon.change_process_owner(**args)
+        mock_os_module.assert_has_calls([
+                mock.call.initgroups(mock.ANY, mock.ANY),
+                mock.call.setuid(mock.ANY),
+                ])
+
+    def test_sets_gid_and_uid_in_order(
             self,
-            mock_func_os_setuid, mock_func_os_setgid):
-        """ Should change process GID and UID in correct order.
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should set process GID and UID in correct order.
 
             Since the process requires appropriate privilege to use
             either of `setuid` or `setgid`, changing the UID must be
@@ -1019,39 +1088,79 @@
 
             """
         args = self.test_args
+        args['initgroups'] = False
         mock_os_module = mock.MagicMock()
         mock_os_module.attach_mock(mock_func_os_setuid, "setuid")
         mock_os_module.attach_mock(mock_func_os_setgid, "setgid")
+        mock_os_module.attach_mock(mock_func_os_initgroups, "initgroups")
         daemon.daemon.change_process_owner(**args)
         mock_os_module.assert_has_calls([
                 mock.call.setgid(mock.ANY),
                 mock.call.setuid(mock.ANY),
                 ])
 
-    def test_changes_group_id_to_gid(
+    def test_specifies_username_to_initgroups(
             self,
-            mock_func_os_setuid, mock_func_os_setgid):
-        """ Should change process GID to specified value. """
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should specify the UID's username to ‘os.initgroups’. """
         args = self.test_args
-        gid = self.test_gid
+        args['initgroups'] = True
+        expected_username = self.test_pwent.pw_name
+        daemon.daemon.change_process_owner(**args)
+        mock_func_os_initgroups.assert_called_with(expected_username, mock.ANY)
+
+    def test_sets_group_id_to_gid_using_initgroups(
+            self,
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should change process GID using ‘os.initgroups’. """
+        args = self.test_args
+        args['initgroups'] = True
+        expected_gid = self.test_gid
+        daemon.daemon.change_process_owner(**args)
+        mock_func_os_initgroups.assert_called_once_with(mock.ANY, expected_gid)
+
+    def test_changes_group_id_to_gid_using_setgid(
+            self,
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should change process GID using ‘os.setgid’. """
+        args = self.test_args
+        expected_gid = self.test_gid
+        daemon.daemon.change_process_owner(**args)
+        mock_func_os_setgid.assert_called_once_with(expected_gid)
+
+    def test_calls_setgid_when_username_not_found(
+            self,
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should call ‘os.setgid’ when no username for the UID. """
+        args = self.test_args
+        args['initgroups'] = True
+        expected_gid = self.test_gid
+        pwd.getpwuid.side_effect = KeyError("No such entry")
         daemon.daemon.change_process_owner(**args)
-        mock_func_os_setgid.assert_called_once_with(gid)
+        mock_func_os_setgid.assert_called_once_with(expected_gid)
 
     def test_changes_user_id_to_uid(
             self,
-            mock_func_os_setuid, mock_func_os_setgid):
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
         """ Should change process UID to specified value. """
         args = self.test_args
-        uid = self.test_uid
+        expected_uid = self.test_uid
         daemon.daemon.change_process_owner(**args)
-        mock_func_os_setuid.assert_called_once_with(uid)
+        mock_func_os_setuid.assert_called_once_with(expected_uid)
 
-    def test_raises_daemon_error_on_os_error_from_setgid(
+    def test_raises_daemon_error_on_os_error_from_setting_groups(
             self,
-            mock_func_os_setuid, mock_func_os_setgid):
-        """ Should raise a DaemonError on receiving an OSError from setgid. """
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
+        """ Should raise a DaemonError on error from setting GID. """
         args = self.test_args
         test_error = OSError(errno.EPERM, "No switching for you!")
+        mock_func_os_initgroups.side_effect = test_error
         mock_func_os_setgid.side_effect = test_error
         expected_error = daemon.daemon.DaemonOSEnvironmentError
         exc = self.assertRaises(
@@ -1061,7 +1170,8 @@
 
     def test_raises_daemon_error_on_os_error_from_setuid(
             self,
-            mock_func_os_setuid, mock_func_os_setgid):
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
         """ Should raise a DaemonError on receiving an OSError from setuid. """
         args = self.test_args
         test_error = OSError(errno.EPERM, "No switching for you!")
@@ -1074,7 +1184,8 @@
 
     def test_error_message_contains_original_error_message(
             self,
-            mock_func_os_setuid, mock_func_os_setgid):
+            mock_func_os_setuid, mock_func_os_setgid,
+            mock_func_os_initgroups):
         """ Should raise a DaemonError with original message. """
         args = self.test_args
         test_error = OSError(errno.EINVAL, "Whatchoo talkin' 'bout?")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test/test_metadata.py 
new/python-daemon-2.1.1/test/test_metadata.py
--- old/python-daemon-2.0.6/test/test_metadata.py       2015-02-02 
03:38:13.000000000 +0100
+++ new/python-daemon-2.1.1/test/test_metadata.py       2016-01-30 
03:01:02.000000000 +0100
@@ -3,7 +3,7 @@
 # test/test_metadata.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test/test_pidfile.py 
new/python-daemon-2.1.1/test/test_pidfile.py
--- old/python-daemon-2.0.6/test/test_pidfile.py        2015-02-02 
04:56:12.000000000 +0100
+++ new/python-daemon-2.1.1/test/test_pidfile.py        2016-01-30 
03:01:02.000000000 +0100
@@ -3,7 +3,7 @@
 # test/test_pidfile.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test/test_runner.py 
new/python-daemon-2.1.1/test/test_runner.py
--- old/python-daemon-2.0.6/test/test_runner.py 2015-01-11 09:38:02.000000000 
+0100
+++ new/python-daemon-2.1.1/test/test_runner.py 2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # test/test_runner.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2009–2015 Ben Finney <[email protected]>
+# Copyright © 2009–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the Apache License, version 2.0 as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/test_version.py 
new/python-daemon-2.1.1/test_version.py
--- old/python-daemon-2.0.6/test_version.py     2015-02-03 02:10:54.000000000 
+0100
+++ new/python-daemon-2.1.1/test_version.py     2016-01-30 03:01:02.000000000 
+0100
@@ -3,7 +3,7 @@
 # test_version.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the GNU General Public License as published by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-daemon-2.0.6/version.py 
new/python-daemon-2.1.1/version.py
--- old/python-daemon-2.0.6/version.py  2015-02-06 01:57:57.000000000 +0100
+++ new/python-daemon-2.1.1/version.py  2016-01-30 03:01:02.000000000 +0100
@@ -3,7 +3,7 @@
 # version.py
 # Part of ‘python-daemon’, an implementation of PEP 3143.
 #
-# Copyright © 2008–2015 Ben Finney <[email protected]>
+# Copyright © 2008–2016 Ben Finney <[email protected]>
 #
 # This is free software: you may copy, modify, and/or distribute this work
 # under the terms of the GNU General Public License as published by the


Reply via email to