Hello community,

here is the log from the commit of package python-daiquiri for openSUSE:Factory 
checked in at 2020-11-10 13:46:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-daiquiri (Old)
 and      /work/SRC/openSUSE:Factory/.python-daiquiri.new.11331 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-daiquiri"

Tue Nov 10 13:46:34 2020 rev:8 rq:847413 version:3.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-daiquiri/python-daiquiri.changes  
2020-04-02 17:45:16.445523456 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-daiquiri.new.11331/python-daiquiri.changes   
    2020-11-10 13:53:30.434843881 +0100
@@ -1,0 +2,7 @@
+Tue Nov 10 07:54:11 UTC 2020 - Dirk Mueller <dmuel...@suse.com>
+
+- update to 3.0.0:
+  * Remove python 2 support
+  * Add python 3.9 support
+
+-------------------------------------------------------------------

Old:
----
  daiquiri-2.1.1.tar.gz

New:
----
  daiquiri-3.0.0.tar.gz

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

Other differences:
------------------
++++++ python-daiquiri.spec ++++++
--- /var/tmp/diff_new_pack.Z5ap4Z/_old  2020-11-10 13:53:31.298842247 +0100
+++ /var/tmp/diff_new_pack.Z5ap4Z/_new  2020-11-10 13:53:31.298842247 +0100
@@ -17,8 +17,9 @@
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%global skip_python2 1
 Name:           python-daiquiri
-Version:        2.1.1
+Version:        3.0.0
 Release:        0
 Summary:        Library to configure Python logging
 License:        Apache-2.0

++++++ daiquiri-2.1.1.tar.gz -> daiquiri-3.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/.circleci/config.yml 
new/daiquiri-3.0.0/.circleci/config.yml
--- old/daiquiri-2.1.1/.circleci/config.yml     2019-12-16 09:30:18.000000000 
+0100
+++ new/daiquiri-3.0.0/.circleci/config.yml     2020-11-06 10:56:59.000000000 
+0100
@@ -23,11 +23,6 @@
       - image: circleci/python:3.8
     steps:
       - tox: {target: docs}
-  py27:
-    docker:
-      - image: circleci/python:2.7
-    steps:
-      - tox: {target: py27}
   py36:
     docker:
       - image: circleci/python:3.6
@@ -43,6 +38,11 @@
       - image: circleci/python:3.8
     steps:
       - tox: {target: py38}
+  py39:
+    docker:
+      - image: circleci/python:3.9
+    steps:
+      - tox: {target: py39}
 
 
 workflows:
@@ -51,8 +51,8 @@
   test:
     jobs:
       - pep8
-      - py27
       - py36
       - py37
       - py38
+      - py39
       - docs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/.mergify.yml 
new/daiquiri-3.0.0/.mergify.yml
--- old/daiquiri-2.1.1/.mergify.yml     2019-12-16 09:33:55.000000000 +0100
+++ new/daiquiri-3.0.0/.mergify.yml     2020-11-06 10:34:09.000000000 +0100
@@ -2,13 +2,8 @@
   - name: automatic merge
     conditions:
       - base=master
-      - "status-success=ci/circleci: pep8"
-      - "status-success=ci/circleci: docs"
-      - "status-success=ci/circleci: py27"
-      - "status-success=ci/circleci: py36"
-      - "status-success=ci/circleci: py37"
-      - "status-success=ci/circleci: py38"
-      - "#approved-reviews-by>=1"
+      - "status-success=ci/circleci: test"
+      - status-success=test
       - label!=work-in-progress
     actions:
       merge:
@@ -17,3 +12,11 @@
     conditions: []
     actions:
       dismiss_reviews: {}
+  - name: automatic merge from maintainer
+    conditions:
+      - author=jd
+      - status-success=test
+      - label!=work-in-progress
+    actions:
+      merge:
+        strict: "smart"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/PKG-INFO new/daiquiri-3.0.0/PKG-INFO
--- old/daiquiri-2.1.1/PKG-INFO 2020-03-09 10:12:39.477614400 +0100
+++ new/daiquiri-3.0.0/PKG-INFO 2020-11-06 13:46:12.686851500 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: daiquiri
-Version: 2.1.1
+Version: 3.0.0
 Summary: Library to configure Python logging easily
 Home-page: https://github.com/jd/daiquiri
 Author: Julien Danjou
@@ -31,11 +31,10 @@
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Provides-Extra: test
 Provides-Extra: systemd
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/__init__.py 
new/daiquiri-3.0.0/daiquiri/__init__.py
--- old/daiquiri-2.1.1/daiquiri/__init__.py     2020-02-27 10:43:46.000000000 
+0100
+++ new/daiquiri-3.0.0/daiquiri/__init__.py     2020-11-06 13:43:33.000000000 
+0100
@@ -19,7 +19,7 @@
 
 
 class KeywordArgumentAdapter(logging.LoggerAdapter):
-    """Logger adapter to add keyword arguments to log record's extra data
+    """Logger adapter to add keyword arguments to log record's extra data.
 
     Keywords passed to the log call are added to the "extra"
     dictionary passed to the underlying logger so they are emitted
@@ -37,23 +37,22 @@
         # Make a new extra dictionary combining the values we were
         # given when we were constructed and anything from kwargs.
         extra = self.extra.copy()
-        if 'extra' in kwargs:
-            extra.update(kwargs.pop('extra'))
+        if "extra" in kwargs:
+            extra.update(kwargs.pop("extra"))
         # Move any unknown keyword arguments into the extra
         # dictionary.
         for name in list(kwargs.keys()):
-            if name == 'exc_info':
+            if name == "exc_info":
                 continue
             extra[name] = kwargs.pop(name)
-        extra['_daiquiri_extra_keys'] = set(extra.keys())
-        kwargs['extra'] = extra
+        extra["_daiquiri_extra_keys"] = set(extra.keys())
+        kwargs["extra"] = extra
         return msg, kwargs
 
     if sys.version_info.major == 2:
+
         def setLevel(self, level):
-            """
-            Set the specified level on the underlying logger.
-            """
+            """Set the specified level on the underlying logger."""
             self.logger.setLevel(level)
 
 
@@ -67,16 +66,21 @@
     return KeywordArgumentAdapter(logging.getLogger(name), kwargs)
 
 
-def setup(level=logging.WARNING, outputs=[output.STDERR], program_name=None,
-          capture_warnings=True, set_excepthook=True):
-    """Setup Python logging.
+def setup(
+    level=logging.WARNING,
+    outputs=[output.STDERR],
+    program_name=None,
+    capture_warnings=True,
+    set_excepthook=True,
+):
+    """Set up Python logging.
 
-    This will setup basic handlers for Python logging.
+    This sets up basic handlers for Python logging.
 
     :param level: Root log level.
     :param outputs: Iterable of outputs to log to.
     :param program_name: The name of the program. Auto-detected if not set.
-    :param capture_warnings: Capture warnings from the `warnings' module.
+    :param capture_warnings: Capture warnings from the `warnings` module.
     """
     root_logger = logging.getLogger(None)
 
@@ -99,7 +103,8 @@
 
         def logging_excepthook(exc_type, value, tb):
             program_logger.critical(
-                "".join(traceback.format_exception(exc_type, value, tb)))
+                "".join(traceback.format_exception(exc_type, value, tb))
+            )
 
         sys.excepthook = logging_excepthook
 
@@ -107,15 +112,15 @@
         logging.captureWarnings(True)
 
 
-def parse_and_set_default_log_levels(default_log_levels, separator='='):
+def parse_and_set_default_log_levels(default_log_levels, separator="="):
     """Set default log levels for some loggers.
 
     :param default_log_levels: List of strings with format
-    <logger_name><separator><log_level>
-
+                               <logger_name><separator><log_level>
     """
-    return set_default_log_levels((pair.split(separator, 1)
-                                   for pair in default_log_levels))
+    return set_default_log_levels(
+        (pair.split(separator, 1) for pair in default_log_levels)
+    )
 
 
 def set_default_log_levels(loggers_and_log_levels):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/formatter.py 
new/daiquiri-3.0.0/daiquiri/formatter.py
--- old/daiquiri-2.1.1/daiquiri/formatter.py    2020-01-16 11:05:47.000000000 
+0100
+++ new/daiquiri-3.0.0/daiquiri/formatter.py    2020-11-06 13:43:33.000000000 
+0100
@@ -9,6 +9,8 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+"""Formatters."""
+
 import logging
 
 from pythonjsonlogger import jsonlogger
@@ -26,20 +28,21 @@
 
 
 class ColorFormatter(logging.Formatter):
-    """Colorizes log output"""
+    """Colorizes log output."""
 
     # TODO(jd) Allow configuration
     LEVEL_COLORS = {
-        logging.DEBUG: '\033[00;32m',  # GREEN
-        logging.INFO: '\033[00;36m',  # CYAN
-        logging.WARN: '\033[01;33m',  # BOLD YELLOW
-        logging.ERROR: '\033[01;31m',  # BOLD RED
-        logging.CRITICAL: '\033[01;31m',  # BOLD RED
+        logging.DEBUG: "\033[00;32m",  # GREEN
+        logging.INFO: "\033[00;36m",  # CYAN
+        logging.WARN: "\033[01;33m",  # BOLD YELLOW
+        logging.ERROR: "\033[01;31m",  # BOLD RED
+        logging.CRITICAL: "\033[01;31m",  # BOLD RED
     }
 
-    COLOR_STOP = '\033[0m'
+    COLOR_STOP = "\033[0m"
 
     def add_color(self, record):
+        """Add color to a record."""
         if getattr(record, "_stream_is_a_tty", False):
             record.color = self.LEVEL_COLORS[record.levelno]
             record.color_stop = self.COLOR_STOP
@@ -48,10 +51,12 @@
             record.color_stop = ""
 
     def remove_color(self, record):
+        """Remove color from a record."""
         del record.color
         del record.color_stop
 
     def format(self, record):
+        """Format a record."""
         self.add_color(record)
         s = super(ColorFormatter, self).format(record)
         self.remove_color(record)
@@ -63,10 +68,13 @@
 
     Any keywords passed to a logging call will be formatted into a
     "extras" string and included in a logging message.
+
     Example:
         logger.info('my message', extra='keyword')
+
     will cause an "extras" string of:
         [extra: keyword]
+
     to be inserted into the format in place of %(extras)s.
 
     The optional `keywords` argument must be passed into the init
@@ -77,28 +85,31 @@
     Special keywords:
 
     keywords
-      A set of strings containing keywords to filter out of the
-      "extras" string.
+        A set of strings containing keywords to filter out of the
+        "extras" string.
 
     extras_template
-      A format string to use instead of '[{0}: {1}]'
+        A format string to use instead of '[{0}: {1}]'
 
     extras_separator
-      What string to "join" multiple "extras" with.
+        What string to "join" multiple "extras" with.
 
     extras_prefix and extras_suffix
-      Strings which will be prepended and appended to the "extras"
-      string respectively. These will only be prepended if the
-      "extras" string is not empty.
+        Strings which will be prepended and appended to the "extras"
+        string respectively. These will only be prepended if the
+        "extras" string is not empty.
     """
 
-    def __init__(self,
-                 keywords=None,
-                 extras_template='[{0}: {1}]',
-                 extras_separator=' ',
-                 extras_prefix=' ',
-                 extras_suffix='',
-                 *args, **kwargs):
+    def __init__(
+        self,
+        keywords=None,
+        extras_template="[{0}: {1}]",
+        extras_separator=" ",
+        extras_prefix=" ",
+        extras_suffix="",
+        *args,
+        **kwargs
+    ):
         self.keywords = set() if keywords is None else keywords
         self.extras_template = extras_template
         self.extras_separator = extras_separator
@@ -107,16 +118,16 @@
         super(ExtrasFormatter, self).__init__(*args, **kwargs)
 
     def add_extras(self, record):
-        if not hasattr(record, '_daiquiri_extra_keys'):
-            record.extras = ''
+        if not hasattr(record, "_daiquiri_extra_keys"):
+            record.extras = ""
             return
 
         extras = self.extras_separator.join(
             self.extras_template.format(k, getattr(record, k))
             for k in record._daiquiri_extra_keys
-            if k != '_daiquiri_extra_keys' and k not in self.keywords
+            if k != "_daiquiri_extra_keys" and k not in self.keywords
         )
-        if extras != '':
+        if extras != "":
             extras = self.extras_prefix + extras + self.extras_suffix
         record.extras = extras
 
@@ -145,16 +156,14 @@
         super(DatadogFormatter, self).__init__(timestamp=True)
 
     def add_fields(self, log_record, record, message_dict):
-        super(DatadogFormatter, self).add_fields(
-            log_record, record, message_dict
-        )
+        super(DatadogFormatter, self).add_fields(log_record, record, 
message_dict)
         log_record["status"] = record.levelname.lower()
         log_record["logger"] = {
             "name": record.name,
         }
         if record.exc_info:
             log_record["error"] = {
-                "kind":  record.exc_info[0].__name__,
+                "kind": record.exc_info[0].__name__,
                 "stack": message_dict.get("stack_info"),
                 "message": message_dict.get("exc_info"),
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/handlers.py 
new/daiquiri-3.0.0/daiquiri/handlers.py
--- old/daiquiri-2.1.1/daiquiri/handlers.py     2020-03-09 10:10:46.000000000 
+0100
+++ new/daiquiri-3.0.0/daiquiri/handlers.py     2020-11-06 13:43:29.000000000 
+0100
@@ -71,22 +71,22 @@
         message = self.format(record)
 
         extras = {
-            'CODE_FILE': record.pathname,
-            'CODE_LINE': record.lineno,
-            'CODE_FUNC': record.funcName,
-            'THREAD_NAME': record.threadName,
-            'PROCESS_NAME': record.processName,
-            'LOGGER_NAME': record.name,
-            'LOGGER_LEVEL': record.levelname,
-            'SYSLOG_IDENTIFIER': self.program_name,
-            'PRIORITY': priority
+            "CODE_FILE": record.pathname,
+            "CODE_LINE": record.lineno,
+            "CODE_FUNC": record.funcName,
+            "THREAD_NAME": record.threadName,
+            "PROCESS_NAME": record.processName,
+            "LOGGER_NAME": record.name,
+            "LOGGER_LEVEL": record.levelname,
+            "SYSLOG_IDENTIFIER": self.program_name,
+            "PRIORITY": priority,
         }
 
         if record.exc_text:
-            extras['EXCEPTION_TEXT'] = record.exc_text
+            extras["EXCEPTION_TEXT"] = record.exc_text
 
         if record.exc_info:
-            extras['EXCEPTION_INFO'] = record.exc_info
+            extras["EXCEPTION_INFO"] = record.exc_info
 
         if hasattr(record, "_daiquiri_extra_keys"):
             for k in record._daiquiri_extra_keys:
@@ -122,3 +122,14 @@
 
     def makePickle(self, record):
         return self.format(record).encode(self.encoding) + b"\n"
+
+
+class PlainTextDatagramHandler(logging.handlers.DatagramHandler):
+    """Socket handler that uses format and encode the record."""
+
+    def __init__(self, hostname, port, encoding="utf-8"):
+        self.encoding = encoding
+        super(PlainTextDatagramHandler, self).__init__(hostname, port)
+
+    def makePickle(self, record):
+        return self.format(record).encode(self.encoding) + b"\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/output.py 
new/daiquiri-3.0.0/daiquiri/output.py
--- old/daiquiri-2.1.1/daiquiri/output.py       2020-01-16 11:05:47.000000000 
+0100
+++ new/daiquiri-3.0.0/daiquiri/output.py       2020-11-06 13:43:33.000000000 
+0100
@@ -16,6 +16,7 @@
 import numbers
 import os
 import sys
+
 try:
     import syslog
 except ImportError:
@@ -26,14 +27,14 @@
 
 
 def get_program_name():
+    """Return the name of the running program."""
     return os.path.basename(inspect.stack()[-1][1])
 
 
 class Output(object):
     """Generic log output."""
 
-    def __init__(self, handler, formatter=formatter.TEXT_FORMATTER,
-                 level=None):
+    def __init__(self, handler, formatter=formatter.TEXT_FORMATTER, 
level=None):
         self.handler = handler
         self.handler.setFormatter(formatter)
         if level is not None:
@@ -44,8 +45,9 @@
         logger.addHandler(self.handler)
 
 
-def _get_log_file_path(logfile=None, logdir=None, program_name=None,
-                       logfile_suffix=".log"):
+def _get_log_file_path(
+    logfile=None, logdir=None, program_name=None, logfile_suffix=".log"
+):
     ret_path = None
 
     if not logdir:
@@ -67,22 +69,31 @@
 class File(Output):
     """Ouput to a file."""
 
-    def __init__(self, filename=None, directory=None, suffix=".log",
-                 program_name=None, formatter=formatter.TEXT_FORMATTER,
-                 level=None):
+    def __init__(
+        self,
+        filename=None,
+        directory=None,
+        suffix=".log",
+        program_name=None,
+        formatter=formatter.TEXT_FORMATTER,
+        level=None,
+    ):
         """Log file output.
 
-        :param filename: The log file path to write to.
-        If directory is also specified, both will be combined.
-        :param directory: The log directory to write to.
-        If no filename is specified, the program name and suffix will be used
-        to contruct the full path relative to the directory.
-        :param suffix: The log file name suffix.
-        This will be only used if no filename has been provided.
+        :param filename: The log file path to write to. If directory is also
+                         specified, both will be combined.
+
+        :param directory: The log directory to write to. If no filename is
+                          specified, the program name and suffix will be used
+                          to contruct the full path relative to the directory.
+
+        :param suffix: The log file name suffix. This will be only used if no
+                       filename has been provided.
+
         :param program_name: Program name. Autodetected by default.
+
         """
-        logpath = _get_log_file_path(filename, directory,
-                                     program_name, suffix)
+        logpath = _get_log_file_path(filename, directory, program_name, suffix)
         handler = logging.handlers.WatchedFileHandler(logpath)
         super(File, self).__init__(handler, formatter, level)
 
@@ -90,28 +101,42 @@
 class RotatingFile(Output):
     """Output to a file, rotating after a certain size."""
 
-    def __init__(self, filename=None, directory=None, suffix='.log',
-                 program_name=None, formatter=formatter.TEXT_FORMATTER,
-                 level=None, max_size_bytes=0, backup_count=0):
+    def __init__(
+        self,
+        filename=None,
+        directory=None,
+        suffix=".log",
+        program_name=None,
+        formatter=formatter.TEXT_FORMATTER,
+        level=None,
+        max_size_bytes=0,
+        backup_count=0,
+    ):
         """Rotating log file output.
 
-        :param filename: The log file path to write to.
-        If directory is also specified, both will be combined.
-        :param directory: The log directory to write to.
-        If no filename is specified, the program name and suffix will be used
-        to contruct the full path relative to the directory.
-        :param suffix: The log file name suffix.
-        This will be only used if no filename has been provided.
+        :param filename: The log file path to write to. If directory is also
+                         specified, both will be combined.
+
+        :param directory: The log directory to write to. If no filename is
+                          specified, the program name and suffix will be used
+                          to contruct the full path relative to the directory.
+
+        :param suffix: The log file name suffix. This will be only used if no
+                       filename has been provided.
+
         :param program_name: Program name. Autodetected by default.
-        :param max_size_bytes: allow the file to rollover at a
-        predetermined size.
-        :param backup_count: the maximum number of files to rotate
-        logging output between.
+
+        :param max_size_bytes: Allow the file to rollover at a predetermined
+                               size.
+
+        :param backup_count: The maximum number of files to rotate logging
+                             output between.
+
         """
-        logpath = _get_log_file_path(filename, directory,
-                                     program_name, suffix)
+        logpath = _get_log_file_path(filename, directory, program_name, suffix)
         handler = logging.handlers.RotatingFileHandler(
-            logpath, maxBytes=max_size_bytes, backupCount=backup_count)
+            logpath, maxBytes=max_size_bytes, backupCount=backup_count
+        )
         super(RotatingFile, self).__init__(handler, formatter, level)
 
     def do_rollover(self):
@@ -122,32 +147,44 @@
 class TimedRotatingFile(Output):
     """Rotating log file output, triggered by a fixed interval."""
 
-    def __init__(self, filename=None, directory=None, suffix='.log',
-                 program_name=None, formatter=formatter.TEXT_FORMATTER,
-                 level=None, interval=datetime.timedelta(hours=24),
-                 backup_count=0):
+    def __init__(
+        self,
+        filename=None,
+        directory=None,
+        suffix=".log",
+        program_name=None,
+        formatter=formatter.TEXT_FORMATTER,
+        level=None,
+        interval=datetime.timedelta(hours=24),
+        backup_count=0,
+    ):
         """Rotating log file output, triggered by a fixed interval.
 
-        :param filename: The log file path to write to.
-        If directory is also specified, both will be combined.
-        :param directory: The log directory to write to.
-        If no filename is specified, the program name and suffix will be used
-        to contruct the full path relative to the directory.
-        :param suffix: The log file name suffix.
-        This will be only used if no filename has been provided.
+        :param filename: The log file path to write to. If directory is also
+                         specified, both will be combined.
+
+        :param directory: The log directory to write to. If no filename is
+                          specified, the program name and suffix will be used
+                          to contruct the full path relative to the directory.
+
+        :param suffix: The log file name suffix. This will be only used if no
+                       filename has been provided.
+
         :param program_name: Program name. Autodetected by default.
-        :param interval: datetime.timedelta instance representing
-        how often a new log file should be created.
-        :param backup_count: the maximum number of files to rotate
-        logging output between.
+
+        :param interval: datetime.timedelta instance representing how often a
+                         new log file should be created.
+
+        :param backup_count: The maximum number of files to rotate logging
+                             output between.
         """
-        logpath = _get_log_file_path(filename, directory,
-                                     program_name, suffix)
+        logpath = _get_log_file_path(filename, directory, program_name, suffix)
         handler = logging.handlers.TimedRotatingFileHandler(
             logpath,
-            when='S',
+            when="S",
             interval=self._timedelta_to_seconds(interval),
-            backupCount=backup_count)
+            backupCount=backup_count,
+        )
         super(TimedRotatingFile, self).__init__(handler, formatter, level)
 
     def do_rollover(self):
@@ -156,8 +193,7 @@
 
     @staticmethod
     def _timedelta_to_seconds(td):
-        """Convert a datetime.timedelta object into a seconds interval for
-        rotating file ouput.
+        """Convert a datetime.timedelta object into a seconds interval.
 
         :param td: datetime.timedelta
         :return: time in seconds
@@ -171,10 +207,12 @@
 class Stream(Output):
     """Generic stream output."""
 
-    def __init__(self, stream=sys.stderr, formatter=formatter.TEXT_FORMATTER,
-                 level=None):
-        super(Stream, self).__init__(handlers.TTYDetectorStreamHandler(stream),
-                                     formatter, level)
+    def __init__(
+        self, stream=sys.stderr, formatter=formatter.TEXT_FORMATTER, level=None
+    ):
+        super(Stream, self).__init__(
+            handlers.TTYDetectorStreamHandler(stream), formatter, level
+        )
 
 
 STDERR = Stream()
@@ -182,38 +220,65 @@
 
 
 class Journal(Output):
-    def __init__(self, program_name=None,
-                 formatter=formatter.TEXT_FORMATTER, level=None):
+    def __init__(
+        self, program_name=None, formatter=formatter.TEXT_FORMATTER, level=None
+    ):
         program_name = program_name or get_program_name
-        super(Journal, self).__init__(handlers.JournalHandler(program_name),
-                                      formatter, level)
+        super(Journal, self).__init__(
+            handlers.JournalHandler(program_name), formatter, level
+        )
 
 
 class Syslog(Output):
-    def __init__(self, program_name=None, facility="user",
-                 formatter=formatter.TEXT_FORMATTER, level=None):
+    def __init__(
+        self,
+        program_name=None,
+        facility="user",
+        formatter=formatter.TEXT_FORMATTER,
+        level=None,
+    ):
         if syslog is None:
             # FIXME(jd) raise something more specific
             raise RuntimeError("syslog is not available on this platform")
         super(Syslog, self).__init__(
             handlers.SyslogHandler(
                 program_name=program_name or get_program_name(),
-                facility=self._find_facility(facility)),
-            formatter, level)
+                facility=self._find_facility(facility),
+            ),
+            formatter,
+            level,
+        )
 
     @staticmethod
     def _find_facility(facility):
         # NOTE(jd): Check the validity of facilities at run time as they differ
         # depending on the OS and Python version being used.
-        valid_facilities = [f for f in
-                            ["LOG_KERN", "LOG_USER", "LOG_MAIL",
-                             "LOG_DAEMON", "LOG_AUTH", "LOG_SYSLOG",
-                             "LOG_LPR", "LOG_NEWS", "LOG_UUCP",
-                             "LOG_CRON", "LOG_AUTHPRIV", "LOG_FTP",
-                             "LOG_LOCAL0", "LOG_LOCAL1", "LOG_LOCAL2",
-                             "LOG_LOCAL3", "LOG_LOCAL4", "LOG_LOCAL5",
-                             "LOG_LOCAL6", "LOG_LOCAL7"]
-                            if getattr(syslog, f, None)]
+        valid_facilities = [
+            f
+            for f in [
+                "LOG_KERN",
+                "LOG_USER",
+                "LOG_MAIL",
+                "LOG_DAEMON",
+                "LOG_AUTH",
+                "LOG_SYSLOG",
+                "LOG_LPR",
+                "LOG_NEWS",
+                "LOG_UUCP",
+                "LOG_CRON",
+                "LOG_AUTHPRIV",
+                "LOG_FTP",
+                "LOG_LOCAL0",
+                "LOG_LOCAL1",
+                "LOG_LOCAL2",
+                "LOG_LOCAL3",
+                "LOG_LOCAL4",
+                "LOG_LOCAL5",
+                "LOG_LOCAL6",
+                "LOG_LOCAL7",
+            ]
+            if getattr(syslog, f, None)
+        ]
 
         facility = facility.upper()
 
@@ -221,29 +286,37 @@
             facility = "LOG_" + facility
 
         if facility not in valid_facilities:
-            raise TypeError('syslog facility must be one of: %s' %
-                            ', '.join("'%s'" % fac
-                                      for fac in valid_facilities))
+            raise TypeError(
+                "syslog facility must be one of: %s"
+                % ", ".join("'%s'" % fac for fac in valid_facilities)
+            )
 
         return getattr(syslog, facility)
 
 
 class Datadog(Output):
-    def __init__(self, hostname="127.0.0.1", port=10518,
-                 formatter=formatter.DATADOG_FORMATTER, level=None):
+    def __init__(
+        self,
+        hostname="127.0.0.1",
+        port=10518,
+        formatter=formatter.DATADOG_FORMATTER,
+        level=None,
+        handler_class=handlers.PlainTextSocketHandler,
+    ):
         super(Datadog, self).__init__(
-            handlers.PlainTextSocketHandler(hostname, port),
-            formatter=formatter, level=level,
+            handler_class(hostname, port),
+            formatter=formatter,
+            level=level,
         )
 
 
 preconfigured = {
-    'stderr': STDERR,
-    'stdout': STDOUT,
+    "stderr": STDERR,
+    "stdout": STDOUT,
 }
 
 if syslog is not None:
-    preconfigured['syslog'] = Syslog()
+    preconfigured["syslog"] = Syslog()
 
 if handlers.journal is not None:
-    preconfigured['journal'] = Journal()
+    preconfigured["journal"] = Journal()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/tests/test_daiquiri.py 
new/daiquiri-3.0.0/daiquiri/tests/test_daiquiri.py
--- old/daiquiri-2.1.1/daiquiri/tests/test_daiquiri.py  2019-08-06 
19:17:54.000000000 +0200
+++ new/daiquiri-3.0.0/daiquiri/tests/test_daiquiri.py  2020-11-06 
13:43:29.000000000 +0100
@@ -9,13 +9,12 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import io
 import json
 import logging
 import unittest
 import warnings
 
-import six.moves
-
 import daiquiri
 
 
@@ -31,72 +30,74 @@
         daiquiri.setup(program_name="foobar")
 
     def test_setup_json_formatter(self):
-        stream = six.moves.StringIO()
-        daiquiri.setup(outputs=(
-            daiquiri.output.Stream(
-                stream, formatter=daiquiri.formatter.JSON_FORMATTER),
-        ))
+        stream = io.StringIO()
+        daiquiri.setup(
+            outputs=(
+                daiquiri.output.Stream(
+                    stream, formatter=daiquiri.formatter.JSON_FORMATTER
+                ),
+            )
+        )
         daiquiri.getLogger(__name__).warning("foobar")
-        self.assertEqual({"message": "foobar"},
-                         json.loads(stream.getvalue()))
+        self.assertEqual({"message": "foobar"}, json.loads(stream.getvalue()))
 
     def test_setup_json_formatter_with_extras(self):
-        stream = six.moves.StringIO()
-        daiquiri.setup(outputs=(
-            daiquiri.output.Stream(
-                stream, formatter=daiquiri.formatter.JSON_FORMATTER),
-        ))
+        stream = io.StringIO()
+        daiquiri.setup(
+            outputs=(
+                daiquiri.output.Stream(
+                    stream, formatter=daiquiri.formatter.JSON_FORMATTER
+                ),
+            )
+        )
         daiquiri.getLogger(__name__).warning("foobar", foo="bar")
-        self.assertEqual({"message": "foobar", "foo": "bar"},
-                         json.loads(stream.getvalue()))
+        self.assertEqual(
+            {"message": "foobar", "foo": "bar"}, json.loads(stream.getvalue())
+        )
 
     def test_get_logger_set_level(self):
         logger = daiquiri.getLogger(__name__)
         logger.setLevel(logging.DEBUG)
 
     def test_capture_warnings(self):
-        stream = six.moves.StringIO()
-        daiquiri.setup(outputs=(
-            daiquiri.output.Stream(stream),
-        ))
+        stream = io.StringIO()
+        daiquiri.setup(outputs=(daiquiri.output.Stream(stream),))
         warnings.warn("omg!")
         line = stream.getvalue()
         self.assertIn("WARNING  py.warnings: ", line)
-        self.assertIn("daiquiri/tests/test_daiquiri.py:62: "
-                      "UserWarning: omg!\n  warnings.warn(\"omg!\")\n",
-                      line)
+        self.assertIn(
+            "daiquiri/tests/test_daiquiri.py:65: "
+            'UserWarning: omg!\n  warnings.warn("omg!")\n',
+            line,
+        )
 
     def test_no_capture_warnings(self):
-        stream = six.moves.StringIO()
-        daiquiri.setup(outputs=(
-            daiquiri.output.Stream(stream),
-        ), capture_warnings=False)
+        stream = io.StringIO()
+        daiquiri.setup(
+            outputs=(daiquiri.output.Stream(stream),), capture_warnings=False
+        )
         warnings.warn("omg!")
         self.assertEqual("", stream.getvalue())
 
     def test_set_default_log_levels(self):
-        daiquiri.set_default_log_levels((("amqp", "debug"),
-                                         ("urllib3", "warn")))
+        daiquiri.set_default_log_levels((("amqp", "debug"), ("urllib3", 
"warn")))
 
     def test_parse_and_set_default_log_levels(self):
-        daiquiri.parse_and_set_default_log_levels(
-            ("urllib3=warn", "foobar=debug"))
+        daiquiri.parse_and_set_default_log_levels(("urllib3=warn", 
"foobar=debug"))
 
     def test_string_as_setup_outputs_arg(self):
-        daiquiri.setup(outputs=('stderr', 'stdout'))
+        daiquiri.setup(outputs=("stderr", "stdout"))
 
         if daiquiri.handlers.syslog is not None:
-            daiquiri.setup(outputs=('syslog',))
+            daiquiri.setup(outputs=("syslog",))
 
         if daiquiri.handlers.journal is not None:
-            daiquiri.setup(outputs=('journal',))
+            daiquiri.setup(outputs=("journal",))
 
 
 def test_extra_with_two_loggers():
-    stream = six.moves.StringIO()
-    daiquiri.setup(outputs=(
-        daiquiri.output.Stream(stream),
-    ))
+    stream = io.StringIO()
+    daiquiri.setup(outputs=(daiquiri.output.Stream(stream),))
     log1 = daiquiri.getLogger("foobar")
     log1.error("argh")
     log2 = daiquiri.getLogger("foobar", key="value")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/tests/test_formatter.py 
new/daiquiri-3.0.0/daiquiri/tests/test_formatter.py
--- old/daiquiri-2.1.1/daiquiri/tests/test_formatter.py 2018-07-18 
17:33:34.000000000 +0200
+++ new/daiquiri-3.0.0/daiquiri/tests/test_formatter.py 2020-11-06 
13:43:29.000000000 +0100
@@ -9,20 +9,19 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import io
 import logging
 import unittest
 
-import six
-
 import daiquiri
 
 
 class TestColorExtrasFormatter(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
-        cls.logger = daiquiri.getLogger('my_module')
+        cls.logger = daiquiri.getLogger("my_module")
         cls.logger.setLevel(logging.INFO)
-        cls.stream = six.moves.StringIO()
+        cls.stream = io.StringIO()
         cls.handler = daiquiri.handlers.TTYDetectorStreamHandler(cls.stream)
         cls.logger.logger.addHandler(cls.handler)
         super(TestColorExtrasFormatter, cls).setUpClass()
@@ -32,56 +31,58 @@
         # getvalue() is the only way to see what's in the stream. However this
         # requires the stream to be reset every time.
         self.stream.close()
-        self.stream = six.moves.StringIO()
+        self.stream = io.StringIO()
         self.handler.stream = self.stream
         super(TestColorExtrasFormatter, self).setUp()
 
     def test_no_keywords(self):
-        format_string = '%(levelname)s %(name)s%(extras)s: %(message)s'
+        format_string = "%(levelname)s %(name)s%(extras)s: %(message)s"
         formatter = daiquiri.formatter.ColorExtrasFormatter(fmt=format_string)
         self.handler.setFormatter(formatter)
 
-        self.logger.info('test message')
-        self.assertEqual(self.stream.getvalue(),
-                         'INFO my_module: test message\n')
+        self.logger.info("test message")
+        self.assertEqual(self.stream.getvalue(), "INFO my_module: test 
message\n")
 
     def test_no_keywords_with_extras(self):
-        format_string = '%(levelname)s %(name)s%(extras)s: %(message)s'
+        format_string = "%(levelname)s %(name)s%(extras)s: %(message)s"
         formatter = daiquiri.formatter.ColorExtrasFormatter(fmt=format_string)
         self.handler.setFormatter(formatter)
 
-        self.logger.info('test message', test="a")
-        self.assertEqual(self.stream.getvalue(),
-                         'INFO my_module [test: a]: test message\n')
+        self.logger.info("test message", test="a")
+        self.assertEqual(
+            self.stream.getvalue(), "INFO my_module [test: a]: test message\n"
+        )
 
     def test_empty_keywords(self):
-        format_string = '%(levelname)s %(name)s%(extras)s: %(message)s'
-        formatter = daiquiri.formatter.ColorExtrasFormatter(fmt=format_string,
-                                                            keywords=[])
+        format_string = "%(levelname)s %(name)s%(extras)s: %(message)s"
+        formatter = daiquiri.formatter.ColorExtrasFormatter(
+            fmt=format_string, keywords=[]
+        )
         self.handler.setFormatter(formatter)
 
-        self.logger.info('test message', test="a")
-        self.assertEqual(self.stream.getvalue(),
-                         'INFO my_module [test: a]: test message\n')
+        self.logger.info("test message", test="a")
+        self.assertEqual(
+            self.stream.getvalue(), "INFO my_module [test: a]: test message\n"
+        )
 
     def test_keywords_no_extras(self):
-        format_string = ('%(levelname)s %(name)s'
-                         ' %(test)s%(extras)s: %(message)s')
-        formatter = daiquiri.formatter.ColorExtrasFormatter(fmt=format_string,
-                                                            keywords=["test"])
+        format_string = "%(levelname)s %(name)s" " %(test)s%(extras)s: 
%(message)s"
+        formatter = daiquiri.formatter.ColorExtrasFormatter(
+            fmt=format_string, keywords=["test"]
+        )
         self.handler.setFormatter(formatter)
 
-        self.logger.info('test message', test="a")
-        self.assertEqual(self.stream.getvalue(),
-                         'INFO my_module a: test message\n')
+        self.logger.info("test message", test="a")
+        self.assertEqual(self.stream.getvalue(), "INFO my_module a: test 
message\n")
 
     def test_keywords_with_extras(self):
-        format_string = ('%(levelname)s %(name)s'
-                         ' %(test)s%(extras)s: %(message)s')
-        formatter = daiquiri.formatter.ColorExtrasFormatter(fmt=format_string,
-                                                            keywords=["test"])
+        format_string = "%(levelname)s %(name)s" " %(test)s%(extras)s: 
%(message)s"
+        formatter = daiquiri.formatter.ColorExtrasFormatter(
+            fmt=format_string, keywords=["test"]
+        )
         self.handler.setFormatter(formatter)
 
-        self.logger.info('test message', test="a", test2="b")
-        self.assertEqual(self.stream.getvalue(),
-                         'INFO my_module a [test2: b]: test message\n')
+        self.logger.info("test message", test="a", test2="b")
+        self.assertEqual(
+            self.stream.getvalue(), "INFO my_module a [test2: b]: test 
message\n"
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri/tests/test_output.py 
new/daiquiri-3.0.0/daiquiri/tests/test_output.py
--- old/daiquiri-2.1.1/daiquiri/tests/test_output.py    2020-01-16 
11:05:47.000000000 +0100
+++ new/daiquiri-3.0.0/daiquiri/tests/test_output.py    2020-11-06 
13:43:29.000000000 +0100
@@ -14,8 +14,7 @@
 import syslog
 import unittest
 from datetime import timedelta
-
-import mock
+from unittest import mock
 
 import daiquiri
 from daiquiri import output
@@ -29,41 +28,41 @@
         return json.loads(other.decode()[:-1]) == self.expected
 
     def __repr__(self):
-        return "b'" + json.dumps(
-            self.expected, default=lambda x: "unserializable"
-        ) + "\\n'"
+        return (
+            "b'"
+            + json.dumps(self.expected, default=lambda x: "unserializable")
+            + "\\n'"
+        )
 
 
 class TestOutput(unittest.TestCase):
     def test_find_facility(self):
-        self.assertEqual(syslog.LOG_USER,
-                         output.Syslog._find_facility("user"))
-        self.assertEqual(syslog.LOG_LOCAL1,
-                         output.Syslog._find_facility("log_local1"))
-        self.assertEqual(syslog.LOG_LOCAL2,
-                         output.Syslog._find_facility("LOG_local2"))
-        self.assertEqual(syslog.LOG_LOCAL3,
-                         output.Syslog._find_facility("LOG_LOCAL3"))
-        self.assertEqual(syslog.LOG_LOCAL4,
-                         output.Syslog._find_facility("LOCaL4"))
+        self.assertEqual(syslog.LOG_USER, output.Syslog._find_facility("user"))
+        self.assertEqual(syslog.LOG_LOCAL1, 
output.Syslog._find_facility("log_local1"))
+        self.assertEqual(syslog.LOG_LOCAL2, 
output.Syslog._find_facility("LOG_local2"))
+        self.assertEqual(syslog.LOG_LOCAL3, 
output.Syslog._find_facility("LOG_LOCAL3"))
+        self.assertEqual(syslog.LOG_LOCAL4, 
output.Syslog._find_facility("LOCaL4"))
 
     def test_get_log_file_path(self):
-        self.assertEqual("foobar.log",
-                         output._get_log_file_path("foobar.log"))
-        self.assertEqual("/var/log/foo/foobar.log",
-                         output._get_log_file_path("foobar.log",
-                                                   logdir="/var/log/foo"))
-        self.assertEqual("/var/log/foobar.log",
-                         output._get_log_file_path(logdir="/var/log",
-                                                   program_name="foobar"))
-        self.assertEqual("/var/log/foobar.log",
-                         output._get_log_file_path(logdir="/var/log",
-                                                   program_name="foobar"))
-        self.assertEqual("/var/log/foobar.journal",
-                         output._get_log_file_path(
-                             logdir="/var/log",
-                             logfile_suffix=".journal",
-                             program_name="foobar"))
+        self.assertEqual("foobar.log", output._get_log_file_path("foobar.log"))
+        self.assertEqual(
+            "/var/log/foo/foobar.log",
+            output._get_log_file_path("foobar.log", logdir="/var/log/foo"),
+        )
+        self.assertEqual(
+            "/var/log/foobar.log",
+            output._get_log_file_path(logdir="/var/log", 
program_name="foobar"),
+        )
+        self.assertEqual(
+            "/var/log/foobar.log",
+            output._get_log_file_path(logdir="/var/log", 
program_name="foobar"),
+        )
+        self.assertEqual(
+            "/var/log/foobar.journal",
+            output._get_log_file_path(
+                logdir="/var/log", logfile_suffix=".journal", 
program_name="foobar"
+            ),
+        )
 
     def test_timedelta_seconds(self):
         fn = output.TimedRotatingFile._timedelta_to_seconds
@@ -74,26 +73,28 @@
             timedelta(minutes=60),
             timedelta(seconds=hour),
             hour,
-            float(hour)
+            float(hour),
         ]
         for t in one_hour:
             self.assertEqual(hour, fn(t))
 
         error_cases = [
-            'string',
-            ['some', 'list'],
-            ('some', 'tuple',),
-            ('tuple',),
-            {'dict': 'mapping'}
+            "string",
+            ["some", "list"],
+            (
+                "some",
+                "tuple",
+            ),
+            ("tuple",),
+            {"dict": "mapping"},
         ]
         for t in error_cases:
             self.assertRaises(AttributeError, fn, t)
 
     def test_datadog(self):
-        with mock.patch('socket.socket') as mock_socket:
+        with mock.patch("socket.socket") as mock_socket:
             socket_instance = mock_socket.return_value
-            daiquiri.setup(outputs=(daiquiri.output.Datadog(),),
-                           level=logging.DEBUG)
+            daiquiri.setup(outputs=(daiquiri.output.Datadog(),), 
level=logging.DEBUG)
             logger = daiquiri.getLogger()
             logger.error("foo", bar=1)
             logger.info("bar")
@@ -102,22 +103,44 @@
             except ZeroDivisionError:
                 logger = daiquiri.getLogger("saymyname")
                 logger.error("backtrace", exc_info=True)
-            socket_instance.connect.assert_called_once_with(
-                ("127.0.0.1", 10518)
+            socket_instance.connect.assert_called_once_with(("127.0.0.1", 
10518))
+            socket_instance.sendall.assert_has_calls(
+                [
+                    mock.call(
+                        DatadogMatcher(
+                            {
+                                "status": "error",
+                                "message": "foo",
+                                "bar": 1,
+                                "logger": {"name": "root"},
+                                "timestamp": mock.ANY,
+                            }
+                        )
+                    ),
+                    mock.call(
+                        DatadogMatcher(
+                            {
+                                "status": "info",
+                                "message": "bar",
+                                "logger": {"name": "root"},
+                                "timestamp": mock.ANY,
+                            }
+                        )
+                    ),
+                    mock.call(
+                        DatadogMatcher(
+                            {
+                                "status": "error",
+                                "message": "backtrace",
+                                "logger": {"name": "saymyname"},
+                                "timestamp": mock.ANY,
+                                "error": {
+                                    "kind": "ZeroDivisionError",
+                                    "stack": None,
+                                    "message": mock.ANY,
+                                },
+                            }
+                        )
+                    ),
+                ]
             )
-            socket_instance.sendall.assert_has_calls([
-                mock.call(DatadogMatcher({
-                    "status": "error", "message": "foo", "bar": 1,
-                    "logger": {"name": "root"}, "timestamp": mock.ANY,
-                })),
-                mock.call(DatadogMatcher({
-                    "status": "info", "message": "bar",
-                    "logger": {"name": "root"}, "timestamp": mock.ANY,
-                })),
-                mock.call(DatadogMatcher({
-                    "status": "error", "message": "backtrace",
-                    "logger": {"name": "saymyname"}, "timestamp": mock.ANY,
-                    "error": {"kind": "ZeroDivisionError", "stack": None,
-                              "message": mock.ANY}
-                })),
-            ])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri.egg-info/PKG-INFO 
new/daiquiri-3.0.0/daiquiri.egg-info/PKG-INFO
--- old/daiquiri-2.1.1/daiquiri.egg-info/PKG-INFO       2020-03-09 
10:12:39.000000000 +0100
+++ new/daiquiri-3.0.0/daiquiri.egg-info/PKG-INFO       2020-11-06 
13:46:12.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: daiquiri
-Version: 2.1.1
+Version: 3.0.0
 Summary: Library to configure Python logging easily
 Home-page: https://github.com/jd/daiquiri
 Author: Julien Danjou
@@ -31,11 +31,10 @@
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Provides-Extra: test
 Provides-Extra: systemd
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/daiquiri.egg-info/requires.txt 
new/daiquiri-3.0.0/daiquiri.egg-info/requires.txt
--- old/daiquiri-2.1.1/daiquiri.egg-info/requires.txt   2020-03-09 
10:12:39.000000000 +0100
+++ new/daiquiri-3.0.0/daiquiri.egg-info/requires.txt   2020-11-06 
13:46:12.000000000 +0100
@@ -5,5 +5,3 @@
 
 [test]
 pytest
-six
-mock
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/doc/source/conf.py 
new/daiquiri-3.0.0/doc/source/conf.py
--- old/daiquiri-2.1.1/doc/source/conf.py       2017-08-15 13:41:33.000000000 
+0200
+++ new/daiquiri-3.0.0/doc/source/conf.py       2020-11-06 13:43:29.000000000 
+0100
@@ -1,3 +1,3 @@
-master_doc = 'index'
+master_doc = "index"
 project = "Daiquiri"
-extensions = ['sphinx.ext.autodoc']
+extensions = ["sphinx.ext.autodoc"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/examples/advanced_extra.py 
new/daiquiri-3.0.0/examples/advanced_extra.py
--- old/daiquiri-2.1.1/examples/advanced_extra.py       2019-08-06 
18:06:27.000000000 +0200
+++ new/daiquiri-3.0.0/examples/advanced_extra.py       2020-11-06 
13:43:29.000000000 +0100
@@ -3,16 +3,25 @@
 import daiquiri
 import daiquiri.formatter
 
-daiquiri.setup(level=logging.INFO, outputs=[
-    daiquiri.output.Stream(formatter=daiquiri.formatter.ColorExtrasFormatter(
-        fmt=(daiquiri.formatter.DEFAULT_FORMAT +
-             " [%(subsystem)s is %(mood)s]" +
-             "%(extras)s"),
-        keywords=['mood', 'subsystem'],
-    ))])
+daiquiri.setup(
+    level=logging.INFO,
+    outputs=[
+        daiquiri.output.Stream(
+            formatter=daiquiri.formatter.ColorExtrasFormatter(
+                fmt=(
+                    daiquiri.formatter.DEFAULT_FORMAT
+                    + " [%(subsystem)s is %(mood)s]"
+                    + "%(extras)s"
+                ),
+                keywords=["mood", "subsystem"],
+            )
+        )
+    ],
+)
 
 logger = daiquiri.getLogger(__name__, subsystem="example")
-logger.info("It works and log to stderr by default with color!",
-            mood="happy",
-            arbitrary_context="included"
-            )
+logger.info(
+    "It works and log to stderr by default with color!",
+    mood="happy",
+    arbitrary_context="included",
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/examples/extra.py 
new/daiquiri-3.0.0/examples/extra.py
--- old/daiquiri-2.1.1/examples/extra.py        2017-08-31 10:11:39.000000000 
+0200
+++ new/daiquiri-3.0.0/examples/extra.py        2020-11-06 13:43:29.000000000 
+0100
@@ -3,12 +3,16 @@
 import daiquiri
 import daiquiri.formatter
 
-daiquiri.setup(level=logging.INFO, outputs=(
-    daiquiri.output.Stream(formatter=daiquiri.formatter.ColorFormatter(
-        fmt=(daiquiri.formatter.DEFAULT_FORMAT +
-             " [%(subsystem)s is %(mood)s]"))),
-    ))
+daiquiri.setup(
+    level=logging.INFO,
+    outputs=(
+        daiquiri.output.Stream(
+            formatter=daiquiri.formatter.ColorFormatter(
+                fmt=(daiquiri.formatter.DEFAULT_FORMAT + " [%(subsystem)s is 
%(mood)s]")
+            )
+        ),
+    ),
+)
 
 logger = daiquiri.getLogger(__name__, subsystem="example")
-logger.info("It works and log to stderr by default with color!",
-            mood="happy")
+logger.info("It works and log to stderr by default with color!", mood="happy")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/examples/files.py 
new/daiquiri-3.0.0/examples/files.py
--- old/daiquiri-2.1.1/examples/files.py        2017-08-31 10:12:17.000000000 
+0200
+++ new/daiquiri-3.0.0/examples/files.py        2020-11-06 13:43:29.000000000 
+0100
@@ -6,15 +6,14 @@
 daiquiri.setup(
     level=logging.DEBUG,
     outputs=(
-        daiquiri.output.File('errors.log', level=logging.ERROR),
+        daiquiri.output.File("errors.log", level=logging.ERROR),
         daiquiri.output.TimedRotatingFile(
-            'everything.log',
-            level=logging.DEBUG,
-            interval=datetime.timedelta(hours=1))
-    )
+            "everything.log", level=logging.DEBUG, 
interval=datetime.timedelta(hours=1)
+        ),
+    ),
 )
 
 logger = daiquiri.getLogger(__name__)
 
-logger.info('only to rotating file logger')
-logger.error('both log files, including errors only')
+logger.info("only to rotating file logger")
+logger.error("both log files, including errors only")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/examples/formatter.py 
new/daiquiri-3.0.0/examples/formatter.py
--- old/daiquiri-2.1.1/examples/formatter.py    2017-08-31 10:12:29.000000000 
+0200
+++ new/daiquiri-3.0.0/examples/formatter.py    2020-11-06 13:43:29.000000000 
+0100
@@ -3,11 +3,17 @@
 import daiquiri
 import daiquiri.formatter
 
-daiquiri.setup(level=logging.INFO, outputs=(
-    daiquiri.output.Stream(formatter=daiquiri.formatter.ColorFormatter(
-        fmt="%(asctime)s [PID %(process)d] [%(levelname)s] "
-        "%(name)s -> %(message)s")),
-    ))
+daiquiri.setup(
+    level=logging.INFO,
+    outputs=(
+        daiquiri.output.Stream(
+            formatter=daiquiri.formatter.ColorFormatter(
+                fmt="%(asctime)s [PID %(process)d] [%(levelname)s] "
+                "%(name)s -> %(message)s"
+            )
+        ),
+    ),
+)
 
 logger = daiquiri.getLogger(__name__)
 logger.info("It works with a custom format!")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/examples/output.py 
new/daiquiri-3.0.0/examples/output.py
--- old/daiquiri-2.1.1/examples/output.py       2017-08-31 10:12:09.000000000 
+0200
+++ new/daiquiri-3.0.0/examples/output.py       2020-11-06 13:43:29.000000000 
+0100
@@ -5,11 +5,13 @@
 
 # Log both to stdout and as JSON in a file called /dev/null. (Requires
 # `python-json-logger`)
-daiquiri.setup(level=logging.INFO, outputs=(
-    daiquiri.output.Stream(sys.stdout),
-    daiquiri.output.File("/dev/null",
-                         formatter=daiquiri.formatter.JSON_FORMATTER),
-    ))
+daiquiri.setup(
+    level=logging.INFO,
+    outputs=(
+        daiquiri.output.Stream(sys.stdout),
+        daiquiri.output.File("/dev/null", 
formatter=daiquiri.formatter.JSON_FORMATTER),
+    ),
+)
 
 logger = daiquiri.getLogger(__name__, subsystem="example")
 logger.info("It works and log to stdout and /dev/null with JSON")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/examples/stringnames.py 
new/daiquiri-3.0.0/examples/stringnames.py
--- old/daiquiri-2.1.1/examples/stringnames.py  2017-08-31 10:12:00.000000000 
+0200
+++ new/daiquiri-3.0.0/examples/stringnames.py  2020-11-06 13:43:29.000000000 
+0100
@@ -2,7 +2,7 @@
 
 import daiquiri
 
-daiquiri.setup(level=logging.INFO, outputs=('stdout', 'stderr'))
+daiquiri.setup(level=logging.INFO, outputs=("stdout", "stderr"))
 
 logger = daiquiri.getLogger(__name__)
 logger.info("It works and logs to both stdout and stderr!")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/setup.cfg new/daiquiri-3.0.0/setup.cfg
--- old/daiquiri-2.1.1/setup.cfg        2020-03-09 10:12:39.478208500 +0100
+++ new/daiquiri-3.0.0/setup.cfg        2020-11-06 13:46:12.687692000 +0100
@@ -12,12 +12,11 @@
        License :: OSI Approved :: Apache Software License
        Operating System :: POSIX :: Linux
        Programming Language :: Python
-       Programming Language :: Python :: 2
-       Programming Language :: Python :: 2.7
        Programming Language :: Python :: 3
        Programming Language :: Python :: 3.6
        Programming Language :: Python :: 3.7
        Programming Language :: Python :: 3.8
+       Programming Language :: Python :: 3.9
 
 [options]
 install_requires = 
@@ -28,14 +27,9 @@
 [options.extras_require]
 test = 
        pytest
-       six
-       mock
 systemd = 
        systemd-python>=234
 
-[wheel]
-universal = 1
-
 [egg_info]
 tag_build = 
 tag_date = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/setup.py new/daiquiri-3.0.0/setup.py
--- old/daiquiri-2.1.1/setup.py 2020-02-27 10:41:05.000000000 +0100
+++ new/daiquiri-3.0.0/setup.py 2020-11-06 13:43:29.000000000 +0100
@@ -2,6 +2,6 @@
 import setuptools
 
 setuptools.setup(
-    setup_requires=['setuptools_scm'],
+    setup_requires=["setuptools_scm"],
     use_scm_version=True,
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/daiquiri-2.1.1/tox.ini new/daiquiri-3.0.0/tox.ini
--- old/daiquiri-2.1.1/tox.ini  2020-02-27 10:41:05.000000000 +0100
+++ new/daiquiri-3.0.0/tox.ini  2020-11-06 13:43:33.000000000 +0100
@@ -1,5 +1,5 @@
 [tox]
-envlist = py27,py36,py37,py38,pep8,docs
+envlist = py36,py37,py38,py39,pep8,docs
 
 [testenv]
 whitelist_externals = sh
@@ -11,14 +11,25 @@
 
 [testenv:pep8]
 deps =
+    black
     flake8
     flake8-import-order
-commands = flake8
+    flake8-blind-except
+    flake8-builtins
+    flake8-docstrings
+    flake8-rst-docstrings
+    flake8-logging-format
+
+commands =
+    black --check .
+    flake8
 
 [flake8]
 show-source = True
 exclude=.git,.tox,dist,build,.eggs
 application-import-names=daiquiri
+# Black ignore those first fours
+ignore = E203,E501,W503,E231,A003,D101,D102,D103,D104,D105,D107,A003,D100
 
 [testenv:docs]
 deps = sphinx


Reply via email to