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()

```

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):

{"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"}]}