prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [Configuration file] keys are not used
  ##### Steps to reproduce the problem:
  
  1. Create a configuration file at .mitmproxy/config.yaml
  2. Set this configuration:
  mode: "transparent"
  showhost: true 
  3. Start mitmproxy using this command : "mitmproxy --conf config.yaml" (I'm on the .mitmproxy folder of course)
  The process is started but the traffic is not working
  4. Start mitmproxy using this command : "mitmproxy -T --host"
  The process is started and the traffic is working
  
  
  ##### Any other comments? What have you tried so far?
  
  I tried to use the ":" and "=" as separator for the YAML file but only the ":" is recognized apparently
  
  
  ##### System information
  I have the last release of mitmproxy (v2.0.2)
  
  Well I've just notice that there is a v3 release, maybe this could help me ?
  I prefer to create this ticket if someone else has the same issue :)
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mitmproxy/addons/script.py`
  Content:
  ```
  1 import os
  2 import importlib.util
  3 import importlib.machinery
  4 import time
  5 import sys
  6 import types
  7 import typing
  8 
  9 from mitmproxy import addonmanager
  10 from mitmproxy import exceptions
  11 from mitmproxy import flow
  12 from mitmproxy import command
  13 from mitmproxy import eventsequence
  14 from mitmproxy import ctx
  15 
  16 
  17 def load_script(path: str) -> types.ModuleType:
  18     fullname = "__mitmproxy_script__.{}".format(
  19         os.path.splitext(os.path.basename(path))[0]
  20     )
  21     # the fullname is not unique among scripts, so if there already is an existing script with said
  22     # fullname, remove it.
  23     sys.modules.pop(fullname, None)
  24     oldpath = sys.path
  25     sys.path.insert(0, os.path.dirname(path))
  26     try:
  27         loader = importlib.machinery.SourceFileLoader(fullname, path)
  28         spec = importlib.util.spec_from_loader(fullname, loader=loader)
  29         m = importlib.util.module_from_spec(spec)
  30         loader.exec_module(m)
  31         if not getattr(m, "name", None):
  32             m.name = path  # type: ignore
  33         return m
  34     finally:
  35         sys.path[:] = oldpath
  36 
  37 
  38 class Script:
  39     """
  40         An addon that manages a single script.
  41     """
  42     ReloadInterval = 2
  43 
  44     def __init__(self, path):
  45         self.name = "scriptmanager:" + path
  46         self.path = path
  47         self.fullpath = os.path.expanduser(path)
  48         self.ns = None
  49 
  50         self.last_load = 0
  51         self.last_mtime = 0
  52         if not os.path.isfile(self.fullpath):
  53             raise exceptions.OptionsError("No such script: %s" % path)
  54 
  55     @property
  56     def addons(self):
  57         return [self.ns] if self.ns else []
  58 
  59     def tick(self):
  60         if time.time() - self.last_load > self.ReloadInterval:
  61             try:
  62                 mtime = os.stat(self.fullpath).st_mtime
  63             except FileNotFoundError:
  64                 scripts = list(ctx.options.scripts)
  65                 scripts.remove(self.path)
  66                 ctx.options.update(scripts=scripts)
  67                 return
  68 
  69             if mtime > self.last_mtime:
  70                 ctx.log.info("Loading script: %s" % self.path)
  71                 if self.ns:
  72                     ctx.master.addons.remove(self.ns)
  73                 self.ns = None
  74                 with addonmanager.safecall():
  75                     ns = load_script(self.fullpath)
  76                     ctx.master.addons.register(ns)
  77                     self.ns = ns
  78                 if self.ns:
  79                     # We're already running, so we have to explicitly register and
  80                     # configure the addon
  81                     ctx.master.addons.invoke_addon(self.ns, "running")
  82                     ctx.master.addons.invoke_addon(
  83                         self.ns,
  84                         "configure",
  85                         ctx.options.keys()
  86                     )
  87                 self.last_load = time.time()
  88                 self.last_mtime = mtime
  89 
  90 
  91 class ScriptLoader:
  92     """
  93         An addon that manages loading scripts from options.
  94     """
  95     def __init__(self):
  96         self.is_running = False
  97         self.addons = []
  98 
  99     def running(self):
  100         self.is_running = True
  101 
  102     @command.command("script.run")
  103     def script_run(self, flows: typing.Sequence[flow.Flow], path: str) -> None:
  104         """
  105             Run a script on the specified flows. The script is loaded with
  106             default options, and all lifecycle events for each flow are
  107             simulated.
  108         """
  109         try:
  110             s = Script(path)
  111             l = addonmanager.Loader(ctx.master)
  112             ctx.master.addons.invoke_addon(s, "load", l)
  113             ctx.master.addons.invoke_addon(s, "configure", ctx.options.keys())
  114             # Script is loaded on the first tick
  115             ctx.master.addons.invoke_addon(s, "tick")
  116             for f in flows:
  117                 for evt, arg in eventsequence.iterate(f):
  118                     ctx.master.addons.invoke_addon(s, evt, arg)
  119         except exceptions.OptionsError as e:
  120             raise exceptions.CommandError("Error running script: %s" % e) from e
  121 
  122     def configure(self, updated):
  123         if "scripts" in updated:
  124             for s in ctx.options.scripts:
  125                 if ctx.options.scripts.count(s) > 1:
  126                     raise exceptions.OptionsError("Duplicate script: %s" % s)
  127 
  128             for a in self.addons[:]:
  129                 if a.path not in ctx.options.scripts:
  130                     ctx.log.info("Un-loading script: %s" % a.name)
  131                     ctx.master.addons.remove(a)
  132                     self.addons.remove(a)
  133 
  134             # The machinations below are to ensure that:
  135             #   - Scripts remain in the same order
  136             #   - Scripts are not initialized un-necessarily. If only a
  137             #   script's order in the script list has changed, it is just
  138             #   moved.
  139 
  140             current = {}
  141             for a in self.addons:
  142                 current[a.path] = a
  143 
  144             ordered = []
  145             newscripts = []
  146             for s in ctx.options.scripts:
  147                 if s in current:
  148                     ordered.append(current[s])
  149                 else:
  150                     sc = Script(s)
  151                     ordered.append(sc)
  152                     newscripts.append(sc)
  153 
  154             self.addons = ordered
  155 
  156             for s in newscripts:
  157                 ctx.master.addons.register(s)
  158                 if self.is_running:
  159                     # If we're already running, we configure and tell the addon
  160                     # we're up and running.
  161                     ctx.master.addons.invoke_addon(s, "running")
  162
  ```
  --- 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/mitmproxy/addons/script.py b/mitmproxy/addons/script.py
  --- a/mitmproxy/addons/script.py
  +++ b/mitmproxy/addons/script.py
  @@ -44,13 +44,15 @@
       def __init__(self, path):
           self.name = "scriptmanager:" + path
           self.path = path
  -        self.fullpath = os.path.expanduser(path)
  +        self.fullpath = os.path.expanduser(
  +            path.strip("'\" ")
  +        )
           self.ns = None
   
           self.last_load = 0
           self.last_mtime = 0
           if not os.path.isfile(self.fullpath):
  -            raise exceptions.OptionsError("No such script: %s" % path)
  +            raise exceptions.OptionsError('No such script: "%s"' % self.fullpath)
   
       @property
       def addons(self):
  
verification_info: {"golden_diff": "diff --git a/mitmproxy/addons/script.py b/mitmproxy/addons/script.py\n--- a/mitmproxy/addons/script.py\n+++ b/mitmproxy/addons/script.py\n@@ -44,13 +44,15 @@\n     def __init__(self, path):\n         self.name = \"scriptmanager:\" + path\n         self.path = path\n-        self.fullpath = os.path.expanduser(path)\n+        self.fullpath = os.path.expanduser(\n+            path.strip(\"'\\\" \")\n+        )\n         self.ns = None\n \n         self.last_load = 0\n         self.last_mtime = 0\n         if not os.path.isfile(self.fullpath):\n-            raise exceptions.OptionsError(\"No such script: %s\" % path)\n+            raise exceptions.OptionsError('No such script: \"%s\"' % self.fullpath)\n \n     @property\n     def addons(self):\n", "issue": "[Configuration file] keys are not used\n##### Steps to reproduce the problem:\r\n\r\n1. Create a configuration file at .mitmproxy/config.yaml\r\n2. Set this configuration:\r\nmode: \"transparent\"\r\nshowhost: true \r\n3. Start mitmproxy using this command : \"mitmproxy --conf config.yaml\" (I'm on the .mitmproxy folder of course)\r\nThe process is started but the traffic is not working\r\n4. Start mitmproxy using this command : \"mitmproxy -T --host\"\r\nThe process is started and the traffic is working\r\n\r\n\r\n##### Any other comments? What have you tried so far?\r\n\r\nI tried to use the \":\" and \"=\" as separator for the YAML file but only the \":\" is recognized apparently\r\n\r\n\r\n##### System information\r\nI have the last release of mitmproxy (v2.0.2)\r\n\r\nWell I've just notice that there is a v3 release, maybe this could help me ?\r\nI prefer to create this ticket if someone else has the same issue :)\n", "before_files": [{"content": "import os\nimport importlib.util\nimport importlib.machinery\nimport time\nimport sys\nimport types\nimport typing\n\nfrom mitmproxy import addonmanager\nfrom mitmproxy import exceptions\nfrom mitmproxy import flow\nfrom mitmproxy import command\nfrom mitmproxy import eventsequence\nfrom mitmproxy import ctx\n\n\ndef load_script(path: str) -> types.ModuleType:\n    fullname = \"__mitmproxy_script__.{}\".format(\n        os.path.splitext(os.path.basename(path))[0]\n    )\n    # the fullname is not unique among scripts, so if there already is an existing script with said\n    # fullname, remove it.\n    sys.modules.pop(fullname, None)\n    oldpath = sys.path\n    sys.path.insert(0, os.path.dirname(path))\n    try:\n        loader = importlib.machinery.SourceFileLoader(fullname, path)\n        spec = importlib.util.spec_from_loader(fullname, loader=loader)\n        m = importlib.util.module_from_spec(spec)\n        loader.exec_module(m)\n        if not getattr(m, \"name\", None):\n            m.name = path  # type: ignore\n        return m\n    finally:\n        sys.path[:] = oldpath\n\n\nclass Script:\n    \"\"\"\n        An addon that manages a single script.\n    \"\"\"\n    ReloadInterval = 2\n\n    def __init__(self, path):\n        self.name = \"scriptmanager:\" + path\n        self.path = path\n        self.fullpath = os.path.expanduser(path)\n        self.ns = None\n\n        self.last_load = 0\n        self.last_mtime = 0\n        if not os.path.isfile(self.fullpath):\n            raise exceptions.OptionsError(\"No such script: %s\" % path)\n\n    @property\n    def addons(self):\n        return [self.ns] if self.ns else []\n\n    def tick(self):\n        if time.time() - self.last_load > self.ReloadInterval:\n            try:\n                mtime = os.stat(self.fullpath).st_mtime\n            except FileNotFoundError:\n                scripts = list(ctx.options.scripts)\n                scripts.remove(self.path)\n                ctx.options.update(scripts=scripts)\n                return\n\n            if mtime > self.last_mtime:\n                ctx.log.info(\"Loading script: %s\" % self.path)\n                if self.ns:\n                    ctx.master.addons.remove(self.ns)\n                self.ns = None\n                with addonmanager.safecall():\n                    ns = load_script(self.fullpath)\n                    ctx.master.addons.register(ns)\n                    self.ns = ns\n                if self.ns:\n                    # We're already running, so we have to explicitly register and\n                    # configure the addon\n                    ctx.master.addons.invoke_addon(self.ns, \"running\")\n                    ctx.master.addons.invoke_addon(\n                        self.ns,\n                        \"configure\",\n                        ctx.options.keys()\n                    )\n                self.last_load = time.time()\n                self.last_mtime = mtime\n\n\nclass ScriptLoader:\n    \"\"\"\n        An addon that manages loading scripts from options.\n    \"\"\"\n    def __init__(self):\n        self.is_running = False\n        self.addons = []\n\n    def running(self):\n        self.is_running = True\n\n    @command.command(\"script.run\")\n    def script_run(self, flows: typing.Sequence[flow.Flow], path: str) -> None:\n        \"\"\"\n            Run a script on the specified flows. The script is loaded with\n            default options, and all lifecycle events for each flow are\n            simulated.\n        \"\"\"\n        try:\n            s = Script(path)\n            l = addonmanager.Loader(ctx.master)\n            ctx.master.addons.invoke_addon(s, \"load\", l)\n            ctx.master.addons.invoke_addon(s, \"configure\", ctx.options.keys())\n            # Script is loaded on the first tick\n            ctx.master.addons.invoke_addon(s, \"tick\")\n            for f in flows:\n                for evt, arg in eventsequence.iterate(f):\n                    ctx.master.addons.invoke_addon(s, evt, arg)\n        except exceptions.OptionsError as e:\n            raise exceptions.CommandError(\"Error running script: %s\" % e) from e\n\n    def configure(self, updated):\n        if \"scripts\" in updated:\n            for s in ctx.options.scripts:\n                if ctx.options.scripts.count(s) > 1:\n                    raise exceptions.OptionsError(\"Duplicate script: %s\" % s)\n\n            for a in self.addons[:]:\n                if a.path not in ctx.options.scripts:\n                    ctx.log.info(\"Un-loading script: %s\" % a.name)\n                    ctx.master.addons.remove(a)\n                    self.addons.remove(a)\n\n            # The machinations below are to ensure that:\n            #   - Scripts remain in the same order\n            #   - Scripts are not initialized un-necessarily. If only a\n            #   script's order in the script list has changed, it is just\n            #   moved.\n\n            current = {}\n            for a in self.addons:\n                current[a.path] = a\n\n            ordered = []\n            newscripts = []\n            for s in ctx.options.scripts:\n                if s in current:\n                    ordered.append(current[s])\n                else:\n                    sc = Script(s)\n                    ordered.append(sc)\n                    newscripts.append(sc)\n\n            self.addons = ordered\n\n            for s in newscripts:\n                ctx.master.addons.register(s)\n                if self.is_running:\n                    # If we're already running, we configure and tell the addon\n                    # we're up and running.\n                    ctx.master.addons.invoke_addon(s, \"running\")\n", "path": "mitmproxy/addons/script.py"}], "after_files": [{"content": "import os\nimport importlib.util\nimport importlib.machinery\nimport time\nimport sys\nimport types\nimport typing\n\nfrom mitmproxy import addonmanager\nfrom mitmproxy import exceptions\nfrom mitmproxy import flow\nfrom mitmproxy import command\nfrom mitmproxy import eventsequence\nfrom mitmproxy import ctx\n\n\ndef load_script(path: str) -> types.ModuleType:\n    fullname = \"__mitmproxy_script__.{}\".format(\n        os.path.splitext(os.path.basename(path))[0]\n    )\n    # the fullname is not unique among scripts, so if there already is an existing script with said\n    # fullname, remove it.\n    sys.modules.pop(fullname, None)\n    oldpath = sys.path\n    sys.path.insert(0, os.path.dirname(path))\n    try:\n        loader = importlib.machinery.SourceFileLoader(fullname, path)\n        spec = importlib.util.spec_from_loader(fullname, loader=loader)\n        m = importlib.util.module_from_spec(spec)\n        loader.exec_module(m)\n        if not getattr(m, \"name\", None):\n            m.name = path  # type: ignore\n        return m\n    finally:\n        sys.path[:] = oldpath\n\n\nclass Script:\n    \"\"\"\n        An addon that manages a single script.\n    \"\"\"\n    ReloadInterval = 2\n\n    def __init__(self, path):\n        self.name = \"scriptmanager:\" + path\n        self.path = path\n        self.fullpath = os.path.expanduser(\n            path.strip(\"'\\\" \")\n        )\n        self.ns = None\n\n        self.last_load = 0\n        self.last_mtime = 0\n        if not os.path.isfile(self.fullpath):\n            raise exceptions.OptionsError('No such script: \"%s\"' % self.fullpath)\n\n    @property\n    def addons(self):\n        return [self.ns] if self.ns else []\n\n    def tick(self):\n        if time.time() - self.last_load > self.ReloadInterval:\n            try:\n                mtime = os.stat(self.fullpath).st_mtime\n            except FileNotFoundError:\n                scripts = list(ctx.options.scripts)\n                scripts.remove(self.path)\n                ctx.options.update(scripts=scripts)\n                return\n\n            if mtime > self.last_mtime:\n                ctx.log.info(\"Loading script: %s\" % self.path)\n                if self.ns:\n                    ctx.master.addons.remove(self.ns)\n                self.ns = None\n                with addonmanager.safecall():\n                    ns = load_script(self.fullpath)\n                    ctx.master.addons.register(ns)\n                    self.ns = ns\n                if self.ns:\n                    # We're already running, so we have to explicitly register and\n                    # configure the addon\n                    ctx.master.addons.invoke_addon(self.ns, \"running\")\n                    ctx.master.addons.invoke_addon(\n                        self.ns,\n                        \"configure\",\n                        ctx.options.keys()\n                    )\n                self.last_load = time.time()\n                self.last_mtime = mtime\n\n\nclass ScriptLoader:\n    \"\"\"\n        An addon that manages loading scripts from options.\n    \"\"\"\n    def __init__(self):\n        self.is_running = False\n        self.addons = []\n\n    def running(self):\n        self.is_running = True\n\n    @command.command(\"script.run\")\n    def script_run(self, flows: typing.Sequence[flow.Flow], path: str) -> None:\n        \"\"\"\n            Run a script on the specified flows. The script is loaded with\n            default options, and all lifecycle events for each flow are\n            simulated.\n        \"\"\"\n        try:\n            s = Script(path)\n            l = addonmanager.Loader(ctx.master)\n            ctx.master.addons.invoke_addon(s, \"load\", l)\n            ctx.master.addons.invoke_addon(s, \"configure\", ctx.options.keys())\n            # Script is loaded on the first tick\n            ctx.master.addons.invoke_addon(s, \"tick\")\n            for f in flows:\n                for evt, arg in eventsequence.iterate(f):\n                    ctx.master.addons.invoke_addon(s, evt, arg)\n        except exceptions.OptionsError as e:\n            raise exceptions.CommandError(\"Error running script: %s\" % e) from e\n\n    def configure(self, updated):\n        if \"scripts\" in updated:\n            for s in ctx.options.scripts:\n                if ctx.options.scripts.count(s) > 1:\n                    raise exceptions.OptionsError(\"Duplicate script: %s\" % s)\n\n            for a in self.addons[:]:\n                if a.path not in ctx.options.scripts:\n                    ctx.log.info(\"Un-loading script: %s\" % a.name)\n                    ctx.master.addons.remove(a)\n                    self.addons.remove(a)\n\n            # The machinations below are to ensure that:\n            #   - Scripts remain in the same order\n            #   - Scripts are not initialized un-necessarily. If only a\n            #   script's order in the script list has changed, it is just\n            #   moved.\n\n            current = {}\n            for a in self.addons:\n                current[a.path] = a\n\n            ordered = []\n            newscripts = []\n            for s in ctx.options.scripts:\n                if s in current:\n                    ordered.append(current[s])\n                else:\n                    sc = Script(s)\n                    ordered.append(sc)\n                    newscripts.append(sc)\n\n            self.addons = ordered\n\n            for s in newscripts:\n                ctx.master.addons.register(s)\n                if self.is_running:\n                    # If we're already running, we configure and tell the addon\n                    # we're up and running.\n                    ctx.master.addons.invoke_addon(s, \"running\")\n", "path": "mitmproxy/addons/script.py"}]}