prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Test failure when using tox
  This is because tox use sqlite and has no user set
  
  ```
  ======================================================================
  ERROR: test_map_upgrade (modoboa.admin.tests.test_mapfiles.MapFilesTestCase)
  Check that map content is used.
  ----------------------------------------------------------------------
  Traceback (most recent call last):
    File "/home/gawel/bear/modoboa/.tox/py27/lib/python2.7/site-packages/modoboa/admin/tests/test_mapfiles.py", line 45, in test_map_upgrade
      self.assertEqual(mapcontent["user"], dbsettings["USER"])
  KeyError: 'user'
  
  ----------------------------------------------------------------------
  Ran 178 tests in 44.553s
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `modoboa/core/management/commands/generate_postfix_maps.py`
  Content:
  ```
  1 """Management command to generate/update postfix map files."""
  2 
  3 import copy
  4 import hashlib
  5 import os
  6 import sys
  7 
  8 from django.conf import settings
  9 from django.core.management.base import BaseCommand
  10 from django.template import Context, Template
  11 from django.utils import timezone
  12 
  13 import dj_database_url
  14 
  15 from ... import signals
  16 from ... import utils
  17 
  18 MAP_FILE_TEMPLATE = """# This file was generated on {{ date }} by running:
  19 # {{ commandline }}
  20 # DO NOT EDIT!
  21 """
  22 
  23 
  24 class Command(BaseCommand):
  25     """Command class."""
  26 
  27     help = "Generate/update postfix map files."
  28 
  29     def add_arguments(self, parser):
  30         """Add extra arguments."""
  31         parser.add_argument(
  32             "--dburl", help="Custom database url")
  33         parser.add_argument(
  34             "--destdir", default=".",
  35             help="Directory where files will be created")
  36         parser.add_argument(
  37             "--force-overwrite", action="store_true", default=False,
  38             help="Force overwrite of existing map files")
  39 
  40     def __load_checksums(self, destdir):
  41         """Load existing checksums if possible."""
  42         self.__checksums_file = os.path.join(
  43             destdir, "modoboa-postfix-maps.chk")
  44         self.__checksums = {}
  45         if not os.path.exists(self.__checksums_file):
  46             return
  47         with open(self.__checksums_file) as fp:
  48             for line in fp:
  49                 fname, dbtype, checksum = line.split(":")
  50                 self.__checksums[fname.strip()] = {
  51                     "dbtype": dbtype, "checksum": checksum.strip()
  52                 }
  53 
  54     def __register_map_files(self):
  55         """Load specified applications."""
  56         responses = signals.register_postfix_maps.send(sender=self.__class__)
  57         mapfiles = []
  58         for response in responses:
  59             mapfiles += response[1]
  60         return mapfiles
  61 
  62     def __check_file(self, path):
  63         """Check if map file has been modified."""
  64         fname = os.path.basename(path)
  65         condition = (
  66             not self.__checksums or
  67             fname not in self.__checksums)
  68         if condition:
  69             return True
  70         with open(path) as fp:
  71             checksum = hashlib.md5(fp.read()).hexdigest()
  72         return checksum == self.__checksums[fname]["checksum"]
  73 
  74     def get_template(self, dbtype):
  75         """Return map file template."""
  76         tplcontent = MAP_FILE_TEMPLATE
  77         if dbtype == "sqlite":
  78             tplcontent += """dbpath = {{ dbname }}
  79 query = {{ query|safe }}
  80 """
  81         else:
  82             tplcontent += """user = {{ dbuser }}
  83 password = {{ dbpass }}
  84 dbname = {{ dbname }}
  85 hosts = {{ dbhost }}
  86 query = {{ query|safe }}
  87 """
  88         return Template(tplcontent)
  89 
  90     def get_template_context(self, options):
  91         """Build the context used to render templates."""
  92         dburl = options.get("dburl")
  93         db_settings = (
  94             dj_database_url.config(default=dburl)
  95             if dburl else settings.DATABASES["default"])
  96         if "sqlite" in db_settings["ENGINE"]:
  97             dbtype = "sqlite"
  98         elif "psycopg2" in db_settings["ENGINE"]:
  99             dbtype = "postgres"
  100         else:
  101             dbtype = "mysql"
  102         commandline = "{} {}".format(
  103             os.path.basename(sys.argv[0]), " ".join(sys.argv[1:]))
  104         context = {
  105             "date": timezone.now(),
  106             "commandline": commandline,
  107             "dbtype": dbtype,
  108             "dbuser": db_settings["USER"],
  109             "dbpass": db_settings["PASSWORD"],
  110             "dbname": db_settings["NAME"],
  111             "dbhost": db_settings.get("HOST", "127.0.0.1"),
  112         }
  113         return context
  114 
  115     def __render_map_file(
  116             self, mapobject, destdir, context, force_overwrite=False):
  117         """Render a map file."""
  118         fullpath = os.path.join(destdir, mapobject.filename)
  119         if os.path.exists(fullpath) and not force_overwrite:
  120             if not self.__check_file(fullpath):
  121                 print(
  122                     "Cannot upgrade '{}' map because it has been modified."
  123                     .format(mapobject.filename))
  124                 return self.__checksums[mapobject.filename]
  125             mapcontent = utils.parse_map_file(fullpath)
  126             context = copy.deepcopy(context)
  127             context["dbtype"] = self.__checksums[mapobject.filename]["dbtype"]
  128             context["dbuser"] = mapcontent["user"]
  129             context["dbpass"] = mapcontent["password"]
  130             context["dbname"] = mapcontent["dbname"]
  131             context["dbhost"] = mapcontent["hosts"]
  132         content = self.get_template(context["dbtype"]).render(
  133             Context(
  134                 dict(context.items(),
  135                      query=getattr(mapobject, context["dbtype"]))
  136             )
  137         )
  138         fullpath = os.path.join(destdir, mapobject.filename)
  139         with open(fullpath, "w") as fp:
  140             fp.write(content)
  141         return hashlib.md5(content).hexdigest()
  142 
  143     def handle(self, *args, **options):
  144         """Command entry point."""
  145         mapfiles = self.__register_map_files()
  146         destdir = os.path.realpath(options["destdir"])
  147         try:
  148             os.mkdir(destdir)
  149         except OSError:
  150             pass
  151         self.__load_checksums(destdir)
  152         context = self.get_template_context(options)
  153         checksums = {}
  154         for mapobject in mapfiles:
  155             checksum = self.__render_map_file(
  156                 mapobject, destdir, context,
  157                 force_overwrite=options["force_overwrite"])
  158             checksums[mapobject.filename] = checksum
  159         with open(self.__checksums_file, "w") as fp:
  160             for fname, checksum in checksums.items():
  161                 fp.write("{}:{}:{}\n".format(
  162                     fname, context["dbtype"], checksum))
  163
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/modoboa/core/management/commands/generate_postfix_maps.py b/modoboa/core/management/commands/generate_postfix_maps.py
  --- a/modoboa/core/management/commands/generate_postfix_maps.py
  +++ b/modoboa/core/management/commands/generate_postfix_maps.py
  @@ -125,10 +125,13 @@
               mapcontent = utils.parse_map_file(fullpath)
               context = copy.deepcopy(context)
               context["dbtype"] = self.__checksums[mapobject.filename]["dbtype"]
  -            context["dbuser"] = mapcontent["user"]
  -            context["dbpass"] = mapcontent["password"]
  -            context["dbname"] = mapcontent["dbname"]
  -            context["dbhost"] = mapcontent["hosts"]
  +            if context["dbtype"] == "sqlite":
  +                context["dbname"] = mapcontent["dbpath"]
  +            else:
  +                context["dbuser"] = mapcontent["user"]
  +                context["dbpass"] = mapcontent["password"]
  +                context["dbname"] = mapcontent["dbname"]
  +                context["dbhost"] = mapcontent["hosts"]
           content = self.get_template(context["dbtype"]).render(
               Context(
                   dict(context.items(),
  
verification_info: {"golden_diff": "diff --git a/modoboa/core/management/commands/generate_postfix_maps.py b/modoboa/core/management/commands/generate_postfix_maps.py\n--- a/modoboa/core/management/commands/generate_postfix_maps.py\n+++ b/modoboa/core/management/commands/generate_postfix_maps.py\n@@ -125,10 +125,13 @@\n             mapcontent = utils.parse_map_file(fullpath)\n             context = copy.deepcopy(context)\n             context[\"dbtype\"] = self.__checksums[mapobject.filename][\"dbtype\"]\n-            context[\"dbuser\"] = mapcontent[\"user\"]\n-            context[\"dbpass\"] = mapcontent[\"password\"]\n-            context[\"dbname\"] = mapcontent[\"dbname\"]\n-            context[\"dbhost\"] = mapcontent[\"hosts\"]\n+            if context[\"dbtype\"] == \"sqlite\":\n+                context[\"dbname\"] = mapcontent[\"dbpath\"]\n+            else:\n+                context[\"dbuser\"] = mapcontent[\"user\"]\n+                context[\"dbpass\"] = mapcontent[\"password\"]\n+                context[\"dbname\"] = mapcontent[\"dbname\"]\n+                context[\"dbhost\"] = mapcontent[\"hosts\"]\n         content = self.get_template(context[\"dbtype\"]).render(\n             Context(\n                 dict(context.items(),\n", "issue": "Test failure when using tox\nThis is because tox use sqlite and has no user set\n\n```\n======================================================================\nERROR: test_map_upgrade (modoboa.admin.tests.test_mapfiles.MapFilesTestCase)\nCheck that map content is used.\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"/home/gawel/bear/modoboa/.tox/py27/lib/python2.7/site-packages/modoboa/admin/tests/test_mapfiles.py\", line 45, in test_map_upgrade\n    self.assertEqual(mapcontent[\"user\"], dbsettings[\"USER\"])\nKeyError: 'user'\n\n----------------------------------------------------------------------\nRan 178 tests in 44.553s\n```\n\n", "before_files": [{"content": "\"\"\"Management command to generate/update postfix map files.\"\"\"\n\nimport copy\nimport hashlib\nimport os\nimport sys\n\nfrom django.conf import settings\nfrom django.core.management.base import BaseCommand\nfrom django.template import Context, Template\nfrom django.utils import timezone\n\nimport dj_database_url\n\nfrom ... import signals\nfrom ... import utils\n\nMAP_FILE_TEMPLATE = \"\"\"# This file was generated on {{ date }} by running:\n# {{ commandline }}\n# DO NOT EDIT!\n\"\"\"\n\n\nclass Command(BaseCommand):\n    \"\"\"Command class.\"\"\"\n\n    help = \"Generate/update postfix map files.\"\n\n    def add_arguments(self, parser):\n        \"\"\"Add extra arguments.\"\"\"\n        parser.add_argument(\n            \"--dburl\", help=\"Custom database url\")\n        parser.add_argument(\n            \"--destdir\", default=\".\",\n            help=\"Directory where files will be created\")\n        parser.add_argument(\n            \"--force-overwrite\", action=\"store_true\", default=False,\n            help=\"Force overwrite of existing map files\")\n\n    def __load_checksums(self, destdir):\n        \"\"\"Load existing checksums if possible.\"\"\"\n        self.__checksums_file = os.path.join(\n            destdir, \"modoboa-postfix-maps.chk\")\n        self.__checksums = {}\n        if not os.path.exists(self.__checksums_file):\n            return\n        with open(self.__checksums_file) as fp:\n            for line in fp:\n                fname, dbtype, checksum = line.split(\":\")\n                self.__checksums[fname.strip()] = {\n                    \"dbtype\": dbtype, \"checksum\": checksum.strip()\n                }\n\n    def __register_map_files(self):\n        \"\"\"Load specified applications.\"\"\"\n        responses = signals.register_postfix_maps.send(sender=self.__class__)\n        mapfiles = []\n        for response in responses:\n            mapfiles += response[1]\n        return mapfiles\n\n    def __check_file(self, path):\n        \"\"\"Check if map file has been modified.\"\"\"\n        fname = os.path.basename(path)\n        condition = (\n            not self.__checksums or\n            fname not in self.__checksums)\n        if condition:\n            return True\n        with open(path) as fp:\n            checksum = hashlib.md5(fp.read()).hexdigest()\n        return checksum == self.__checksums[fname][\"checksum\"]\n\n    def get_template(self, dbtype):\n        \"\"\"Return map file template.\"\"\"\n        tplcontent = MAP_FILE_TEMPLATE\n        if dbtype == \"sqlite\":\n            tplcontent += \"\"\"dbpath = {{ dbname }}\nquery = {{ query|safe }}\n\"\"\"\n        else:\n            tplcontent += \"\"\"user = {{ dbuser }}\npassword = {{ dbpass }}\ndbname = {{ dbname }}\nhosts = {{ dbhost }}\nquery = {{ query|safe }}\n\"\"\"\n        return Template(tplcontent)\n\n    def get_template_context(self, options):\n        \"\"\"Build the context used to render templates.\"\"\"\n        dburl = options.get(\"dburl\")\n        db_settings = (\n            dj_database_url.config(default=dburl)\n            if dburl else settings.DATABASES[\"default\"])\n        if \"sqlite\" in db_settings[\"ENGINE\"]:\n            dbtype = \"sqlite\"\n        elif \"psycopg2\" in db_settings[\"ENGINE\"]:\n            dbtype = \"postgres\"\n        else:\n            dbtype = \"mysql\"\n        commandline = \"{} {}\".format(\n            os.path.basename(sys.argv[0]), \" \".join(sys.argv[1:]))\n        context = {\n            \"date\": timezone.now(),\n            \"commandline\": commandline,\n            \"dbtype\": dbtype,\n            \"dbuser\": db_settings[\"USER\"],\n            \"dbpass\": db_settings[\"PASSWORD\"],\n            \"dbname\": db_settings[\"NAME\"],\n            \"dbhost\": db_settings.get(\"HOST\", \"127.0.0.1\"),\n        }\n        return context\n\n    def __render_map_file(\n            self, mapobject, destdir, context, force_overwrite=False):\n        \"\"\"Render a map file.\"\"\"\n        fullpath = os.path.join(destdir, mapobject.filename)\n        if os.path.exists(fullpath) and not force_overwrite:\n            if not self.__check_file(fullpath):\n                print(\n                    \"Cannot upgrade '{}' map because it has been modified.\"\n                    .format(mapobject.filename))\n                return self.__checksums[mapobject.filename]\n            mapcontent = utils.parse_map_file(fullpath)\n            context = copy.deepcopy(context)\n            context[\"dbtype\"] = self.__checksums[mapobject.filename][\"dbtype\"]\n            context[\"dbuser\"] = mapcontent[\"user\"]\n            context[\"dbpass\"] = mapcontent[\"password\"]\n            context[\"dbname\"] = mapcontent[\"dbname\"]\n            context[\"dbhost\"] = mapcontent[\"hosts\"]\n        content = self.get_template(context[\"dbtype\"]).render(\n            Context(\n                dict(context.items(),\n                     query=getattr(mapobject, context[\"dbtype\"]))\n            )\n        )\n        fullpath = os.path.join(destdir, mapobject.filename)\n        with open(fullpath, \"w\") as fp:\n            fp.write(content)\n        return hashlib.md5(content).hexdigest()\n\n    def handle(self, *args, **options):\n        \"\"\"Command entry point.\"\"\"\n        mapfiles = self.__register_map_files()\n        destdir = os.path.realpath(options[\"destdir\"])\n        try:\n            os.mkdir(destdir)\n        except OSError:\n            pass\n        self.__load_checksums(destdir)\n        context = self.get_template_context(options)\n        checksums = {}\n        for mapobject in mapfiles:\n            checksum = self.__render_map_file(\n                mapobject, destdir, context,\n                force_overwrite=options[\"force_overwrite\"])\n            checksums[mapobject.filename] = checksum\n        with open(self.__checksums_file, \"w\") as fp:\n            for fname, checksum in checksums.items():\n                fp.write(\"{}:{}:{}\\n\".format(\n                    fname, context[\"dbtype\"], checksum))\n", "path": "modoboa/core/management/commands/generate_postfix_maps.py"}], "after_files": [{"content": "\"\"\"Management command to generate/update postfix map files.\"\"\"\n\nimport copy\nimport hashlib\nimport os\nimport sys\n\nfrom django.conf import settings\nfrom django.core.management.base import BaseCommand\nfrom django.template import Context, Template\nfrom django.utils import timezone\n\nimport dj_database_url\n\nfrom ... import signals\nfrom ... import utils\n\nMAP_FILE_TEMPLATE = \"\"\"# This file was generated on {{ date }} by running:\n# {{ commandline }}\n# DO NOT EDIT!\n\"\"\"\n\n\nclass Command(BaseCommand):\n    \"\"\"Command class.\"\"\"\n\n    help = \"Generate/update postfix map files.\"\n\n    def add_arguments(self, parser):\n        \"\"\"Add extra arguments.\"\"\"\n        parser.add_argument(\n            \"--dburl\", help=\"Custom database url\")\n        parser.add_argument(\n            \"--destdir\", default=\".\",\n            help=\"Directory where files will be created\")\n        parser.add_argument(\n            \"--force-overwrite\", action=\"store_true\", default=False,\n            help=\"Force overwrite of existing map files\")\n\n    def __load_checksums(self, destdir):\n        \"\"\"Load existing checksums if possible.\"\"\"\n        self.__checksums_file = os.path.join(\n            destdir, \"modoboa-postfix-maps.chk\")\n        self.__checksums = {}\n        if not os.path.exists(self.__checksums_file):\n            return\n        with open(self.__checksums_file) as fp:\n            for line in fp:\n                fname, dbtype, checksum = line.split(\":\")\n                self.__checksums[fname.strip()] = {\n                    \"dbtype\": dbtype, \"checksum\": checksum.strip()\n                }\n\n    def __register_map_files(self):\n        \"\"\"Load specified applications.\"\"\"\n        responses = signals.register_postfix_maps.send(sender=self.__class__)\n        mapfiles = []\n        for response in responses:\n            mapfiles += response[1]\n        return mapfiles\n\n    def __check_file(self, path):\n        \"\"\"Check if map file has been modified.\"\"\"\n        fname = os.path.basename(path)\n        condition = (\n            not self.__checksums or\n            fname not in self.__checksums)\n        if condition:\n            return True\n        with open(path) as fp:\n            checksum = hashlib.md5(fp.read()).hexdigest()\n        return checksum == self.__checksums[fname][\"checksum\"]\n\n    def get_template(self, dbtype):\n        \"\"\"Return map file template.\"\"\"\n        tplcontent = MAP_FILE_TEMPLATE\n        if dbtype == \"sqlite\":\n            tplcontent += \"\"\"dbpath = {{ dbname }}\nquery = {{ query|safe }}\n\"\"\"\n        else:\n            tplcontent += \"\"\"user = {{ dbuser }}\npassword = {{ dbpass }}\ndbname = {{ dbname }}\nhosts = {{ dbhost }}\nquery = {{ query|safe }}\n\"\"\"\n        return Template(tplcontent)\n\n    def get_template_context(self, options):\n        \"\"\"Build the context used to render templates.\"\"\"\n        dburl = options.get(\"dburl\")\n        db_settings = (\n            dj_database_url.config(default=dburl)\n            if dburl else settings.DATABASES[\"default\"])\n        if \"sqlite\" in db_settings[\"ENGINE\"]:\n            dbtype = \"sqlite\"\n        elif \"psycopg2\" in db_settings[\"ENGINE\"]:\n            dbtype = \"postgres\"\n        else:\n            dbtype = \"mysql\"\n        commandline = \"{} {}\".format(\n            os.path.basename(sys.argv[0]), \" \".join(sys.argv[1:]))\n        context = {\n            \"date\": timezone.now(),\n            \"commandline\": commandline,\n            \"dbtype\": dbtype,\n            \"dbuser\": db_settings[\"USER\"],\n            \"dbpass\": db_settings[\"PASSWORD\"],\n            \"dbname\": db_settings[\"NAME\"],\n            \"dbhost\": db_settings.get(\"HOST\", \"127.0.0.1\"),\n        }\n        return context\n\n    def __render_map_file(\n            self, mapobject, destdir, context, force_overwrite=False):\n        \"\"\"Render a map file.\"\"\"\n        fullpath = os.path.join(destdir, mapobject.filename)\n        if os.path.exists(fullpath) and not force_overwrite:\n            if not self.__check_file(fullpath):\n                print(\n                    \"Cannot upgrade '{}' map because it has been modified.\"\n                    .format(mapobject.filename))\n                return self.__checksums[mapobject.filename]\n            mapcontent = utils.parse_map_file(fullpath)\n            context = copy.deepcopy(context)\n            context[\"dbtype\"] = self.__checksums[mapobject.filename][\"dbtype\"]\n            if context[\"dbtype\"] == \"sqlite\":\n                context[\"dbname\"] = mapcontent[\"dbpath\"]\n            else:\n                context[\"dbuser\"] = mapcontent[\"user\"]\n                context[\"dbpass\"] = mapcontent[\"password\"]\n                context[\"dbname\"] = mapcontent[\"dbname\"]\n                context[\"dbhost\"] = mapcontent[\"hosts\"]\n        content = self.get_template(context[\"dbtype\"]).render(\n            Context(\n                dict(context.items(),\n                     query=getattr(mapobject, context[\"dbtype\"]))\n            )\n        )\n        fullpath = os.path.join(destdir, mapobject.filename)\n        with open(fullpath, \"w\") as fp:\n            fp.write(content)\n        return hashlib.md5(content).hexdigest()\n\n    def handle(self, *args, **options):\n        \"\"\"Command entry point.\"\"\"\n        mapfiles = self.__register_map_files()\n        destdir = os.path.realpath(options[\"destdir\"])\n        try:\n            os.mkdir(destdir)\n        except OSError:\n            pass\n        self.__load_checksums(destdir)\n        context = self.get_template_context(options)\n        checksums = {}\n        for mapobject in mapfiles:\n            checksum = self.__render_map_file(\n                mapobject, destdir, context,\n                force_overwrite=options[\"force_overwrite\"])\n            checksums[mapobject.filename] = checksum\n        with open(self.__checksums_file, \"w\") as fp:\n            for fname, checksum in checksums.items():\n                fp.write(\"{}:{}:{}\\n\".format(\n                    fname, context[\"dbtype\"], checksum))\n", "path": "modoboa/core/management/commands/generate_postfix_maps.py"}]}