prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Container audit fails in 3.5
  The container audit will fail in version 3.5 due to a missing parameter in the constructor.
  
  https://community.privacyidea.org/t/logging-error-after-update-to-3-5/1811/2
  
  </issue>
  <code>
  [start of privacyidea/lib/auditmodules/containeraudit.py]
  1 # -*- coding: utf-8 -*-
  2 #
  3 #  2019-11-07 Cornelius Kölbel <cornelius.koelbel@netknights.it>
  4 #             initial code for writing audit information to a file
  5 #
  6 # This code is free software; you can redistribute it and/or
  7 # modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  8 # License as published by the Free Software Foundation; either
  9 # version 3 of the License, or any later version.
  10 #
  11 # This code is distributed in the hope that it will be useful,
  12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 # GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  15 #
  16 # You should have received a copy of the GNU Affero General Public
  17 # License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 #
  19 #
  20 __doc__ = """The Container Audit Module allows to write audit information to several different
  21 audit modules at the same time. E.g. it can write audit information to the SQL Audit Module and to the 
  22 Logger Audit Module. This way audit information can be saved in the SQL database and at the same time
  23 be passed to a file or external services via the Python logging facility. 
  24 
  25 The Container Audit Module is configured like this:
  26 
  27     PI_AUDIT_MODULE = 'privacyidea.lib.auditmodules.containeraudit'
  28     PI_AUDIT_CONTAINER_WRITE = ['privacyidea.lib.auditmodules.sqlaudit','privacyidea.lib.auditmodules.loggeraudit']
  29     PI_AUDIT_CONTAINER_READ = 'privacyidea.lib.auditmodules.sqlaudit'
  30 
  31 You also have to provide the configuration parameters for the referenced audit modules.
  32 
  33 """
  34 
  35 import logging
  36 from privacyidea.lib.auditmodules.base import (Audit as AuditBase)
  37 from privacyidea.lib.utils import get_module_class
  38 
  39 
  40 log = logging.getLogger(__name__)
  41 
  42 
  43 class Audit(AuditBase):
  44     """
  45     This is the ContainerAudit module, which writes the audit entries
  46     to a list of audit modules.
  47     """
  48 
  49     def __init__(self, config=None):
  50         super(Audit, self).__init__(config)
  51         self.name = "containeraudit"
  52         write_conf = self.config.get('PI_AUDIT_CONTAINER_WRITE')
  53         read_conf = self.config.get('PI_AUDIT_CONTAINER_READ')
  54         # Initialize all modules
  55         self.write_modules = [get_module_class(audit_module, "Audit", "log")(config) for audit_module in write_conf]
  56         self.read_module = get_module_class(read_conf, "Audit", "log")(config)
  57         if not self.read_module.is_readable:
  58             log.warning(u"The specified PI_AUDIT_CONTAINER_READ {0!s} is not readable.".format(self.read_module))
  59 
  60     @property
  61     def has_data(self):
  62         return any([x.has_data for x in self.write_modules])
  63 
  64     def log(self, param):
  65         """
  66         Call the log method for all writeable modules
  67         """
  68         for module in self.write_modules:
  69             module.log(param)
  70 
  71     def add_to_log(self, param, add_with_comma=False):
  72         """
  73         Call the add_to_log method for all writeable modules
  74         """
  75         for module in self.write_modules:
  76             module.add_to_log(param, add_with_comma)
  77 
  78     def add_policy(self, policyname):
  79         """
  80         Call the add_policy method for all writeable modules
  81         """
  82         for module in self.write_modules:
  83             module.add_policy(policyname)
  84 
  85     def search(self, search_dict, page_size=15, page=1, sortorder="asc",
  86                timelimit=None):
  87         """
  88         Call the search method for the one readable module
  89         """
  90         return self.read_module.search(search_dict, page_size=page_size, page=page,
  91                                        sortorder=sortorder, timelimit=timelimit)
  92 
  93     def get_count(self, search_dict, timedelta=None, success=None):
  94         """
  95         Call the count method for the one readable module
  96         """
  97         return self.read_module.get_count(search_dict, timedelta=timedelta, success=success)
  98 
  99     def csv_generator(self, param=None, user=None, timelimit=None):
  100         """
  101         Call the csv_generator method for the one readable module
  102         """
  103         return self.read_module.csv_generator(param=param, user=user,
  104                                               timelimit=timelimit)
  105 
  106     def get_total(self, param, AND=True, display_error=True, timelimit=None):
  107         """
  108         Call the total method for the one readable module
  109         """
  110         return self.read_module.get_total(param, AND=AND, display_error=display_error, timelimit=timelimit)
  111 
  112     def finalize_log(self):
  113         """
  114         Call the finalize method of all writeable audit modules
  115         """
  116         for module in self.write_modules:
  117             module.finalize_log()
  118
  [end of privacyidea/lib/auditmodules/containeraudit.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/privacyidea/lib/auditmodules/containeraudit.py b/privacyidea/lib/auditmodules/containeraudit.py
  --- a/privacyidea/lib/auditmodules/containeraudit.py
  +++ b/privacyidea/lib/auditmodules/containeraudit.py
  @@ -46,14 +46,15 @@
       to a list of audit modules.
       """
   
  -    def __init__(self, config=None):
  -        super(Audit, self).__init__(config)
  +    def __init__(self, config=None, startdate=None):
  +        super(Audit, self).__init__(config, startdate)
           self.name = "containeraudit"
           write_conf = self.config.get('PI_AUDIT_CONTAINER_WRITE')
           read_conf = self.config.get('PI_AUDIT_CONTAINER_READ')
           # Initialize all modules
  -        self.write_modules = [get_module_class(audit_module, "Audit", "log")(config) for audit_module in write_conf]
  -        self.read_module = get_module_class(read_conf, "Audit", "log")(config)
  +        self.write_modules = [get_module_class(audit_module, "Audit", "log")(config, startdate)
  +                              for audit_module in write_conf]
  +        self.read_module = get_module_class(read_conf, "Audit", "log")(config, startdate)
           if not self.read_module.is_readable:
               log.warning(u"The specified PI_AUDIT_CONTAINER_READ {0!s} is not readable.".format(self.read_module))
  
verification_info: {"golden_diff": "diff --git a/privacyidea/lib/auditmodules/containeraudit.py b/privacyidea/lib/auditmodules/containeraudit.py\n--- a/privacyidea/lib/auditmodules/containeraudit.py\n+++ b/privacyidea/lib/auditmodules/containeraudit.py\n@@ -46,14 +46,15 @@\n     to a list of audit modules.\n     \"\"\"\n \n-    def __init__(self, config=None):\n-        super(Audit, self).__init__(config)\n+    def __init__(self, config=None, startdate=None):\n+        super(Audit, self).__init__(config, startdate)\n         self.name = \"containeraudit\"\n         write_conf = self.config.get('PI_AUDIT_CONTAINER_WRITE')\n         read_conf = self.config.get('PI_AUDIT_CONTAINER_READ')\n         # Initialize all modules\n-        self.write_modules = [get_module_class(audit_module, \"Audit\", \"log\")(config) for audit_module in write_conf]\n-        self.read_module = get_module_class(read_conf, \"Audit\", \"log\")(config)\n+        self.write_modules = [get_module_class(audit_module, \"Audit\", \"log\")(config, startdate)\n+                              for audit_module in write_conf]\n+        self.read_module = get_module_class(read_conf, \"Audit\", \"log\")(config, startdate)\n         if not self.read_module.is_readable:\n             log.warning(u\"The specified PI_AUDIT_CONTAINER_READ {0!s} is not readable.\".format(self.read_module))\n", "issue": "Container audit fails in 3.5\nThe container audit will fail in version 3.5 due to a missing parameter in the constructor.\r\n\r\nhttps://community.privacyidea.org/t/logging-error-after-update-to-3-5/1811/2\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n#\n#  2019-11-07 Cornelius K\u00f6lbel <cornelius.koelbel@netknights.it>\n#             initial code for writing audit information to a file\n#\n# This code is free software; you can redistribute it and/or\n# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE\n# License as published by the Free Software Foundation; either\n# version 3 of the License, or any later version.\n#\n# This code is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU AFFERO GENERAL PUBLIC LICENSE for more details.\n#\n# You should have received a copy of the GNU Affero General Public\n# License along with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n#\n__doc__ = \"\"\"The Container Audit Module allows to write audit information to several different\naudit modules at the same time. E.g. it can write audit information to the SQL Audit Module and to the \nLogger Audit Module. This way audit information can be saved in the SQL database and at the same time\nbe passed to a file or external services via the Python logging facility. \n\nThe Container Audit Module is configured like this:\n\n    PI_AUDIT_MODULE = 'privacyidea.lib.auditmodules.containeraudit'\n    PI_AUDIT_CONTAINER_WRITE = ['privacyidea.lib.auditmodules.sqlaudit','privacyidea.lib.auditmodules.loggeraudit']\n    PI_AUDIT_CONTAINER_READ = 'privacyidea.lib.auditmodules.sqlaudit'\n\nYou also have to provide the configuration parameters for the referenced audit modules.\n\n\"\"\"\n\nimport logging\nfrom privacyidea.lib.auditmodules.base import (Audit as AuditBase)\nfrom privacyidea.lib.utils import get_module_class\n\n\nlog = logging.getLogger(__name__)\n\n\nclass Audit(AuditBase):\n    \"\"\"\n    This is the ContainerAudit module, which writes the audit entries\n    to a list of audit modules.\n    \"\"\"\n\n    def __init__(self, config=None):\n        super(Audit, self).__init__(config)\n        self.name = \"containeraudit\"\n        write_conf = self.config.get('PI_AUDIT_CONTAINER_WRITE')\n        read_conf = self.config.get('PI_AUDIT_CONTAINER_READ')\n        # Initialize all modules\n        self.write_modules = [get_module_class(audit_module, \"Audit\", \"log\")(config) for audit_module in write_conf]\n        self.read_module = get_module_class(read_conf, \"Audit\", \"log\")(config)\n        if not self.read_module.is_readable:\n            log.warning(u\"The specified PI_AUDIT_CONTAINER_READ {0!s} is not readable.\".format(self.read_module))\n\n    @property\n    def has_data(self):\n        return any([x.has_data for x in self.write_modules])\n\n    def log(self, param):\n        \"\"\"\n        Call the log method for all writeable modules\n        \"\"\"\n        for module in self.write_modules:\n            module.log(param)\n\n    def add_to_log(self, param, add_with_comma=False):\n        \"\"\"\n        Call the add_to_log method for all writeable modules\n        \"\"\"\n        for module in self.write_modules:\n            module.add_to_log(param, add_with_comma)\n\n    def add_policy(self, policyname):\n        \"\"\"\n        Call the add_policy method for all writeable modules\n        \"\"\"\n        for module in self.write_modules:\n            module.add_policy(policyname)\n\n    def search(self, search_dict, page_size=15, page=1, sortorder=\"asc\",\n               timelimit=None):\n        \"\"\"\n        Call the search method for the one readable module\n        \"\"\"\n        return self.read_module.search(search_dict, page_size=page_size, page=page,\n                                       sortorder=sortorder, timelimit=timelimit)\n\n    def get_count(self, search_dict, timedelta=None, success=None):\n        \"\"\"\n        Call the count method for the one readable module\n        \"\"\"\n        return self.read_module.get_count(search_dict, timedelta=timedelta, success=success)\n\n    def csv_generator(self, param=None, user=None, timelimit=None):\n        \"\"\"\n        Call the csv_generator method for the one readable module\n        \"\"\"\n        return self.read_module.csv_generator(param=param, user=user,\n                                              timelimit=timelimit)\n\n    def get_total(self, param, AND=True, display_error=True, timelimit=None):\n        \"\"\"\n        Call the total method for the one readable module\n        \"\"\"\n        return self.read_module.get_total(param, AND=AND, display_error=display_error, timelimit=timelimit)\n\n    def finalize_log(self):\n        \"\"\"\n        Call the finalize method of all writeable audit modules\n        \"\"\"\n        for module in self.write_modules:\n            module.finalize_log()\n", "path": "privacyidea/lib/auditmodules/containeraudit.py"}]}