We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Crash when using --reload and SSL certificate
Using the example code
```python
async def app(scope, receive, send):
    assert scope['type'] == 'http'

    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ],
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })
```

with a certificate created by `mkcert` in the current directory, and running 
`uvicorn ssl:app --reload --ssl-keyfile=./uvicorn.localhost-key.pem --ssl-certfile=./uvicorn.localhost.pem` results in the following error:

<details>
<summary>Stacktrace</summary>

```
INFO: Uvicorn running on https://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [31388]
Traceback (most recent call last):
  File "/tmp/tmp.zVyoktn22U/.venv/bin/uvicorn", line 11, in <module>
    load_entry_point('uvicorn==0.7.0', 'console_scripts', 'uvicorn')()
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/uvicorn/main.py", line 256, in main
    run(**kwargs)
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/uvicorn/main.py", line 271, in run
    supervisor.run(server.run, sockets=[socket])
  File "/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/uvicorn/supervisors/statreload.py", line 34, in run
    process.start()
  File "/usr/lib/python3.7/multiprocessing/process.py", line 112, in start
    self._popen = self._Popen(self)
  File "/usr/lib/python3.7/multiprocessing/context.py", line 284, in _Popen
    return Popen(process_obj)
  File "/usr/lib/python3.7/multiprocessing/popen_spawn_posix.py", line 32, in __init__
    super().__init__(process_obj)
  File "/usr/lib/python3.7/multiprocessing/popen_fork.py", line 20, in __init__
    self._launch(process_obj)
  File "/usr/lib/python3.7/multiprocessing/popen_spawn_posix.py", line 47, in _launch
    reduction.dump(process_obj, fp)
  File "/usr/lib/python3.7/multiprocessing/reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle SSLContext objects
```
</details>

*Environment:*
`python -V`: Python 3.7.3
`uvicorn`: 0.7.0
`uname -a`: `Linux architect 5.0.9-arch1-1-ARCH #1 SMP PREEMPT Sat Apr 20 15:00:46 UTC 2019 x86_64 GNU/Linux`

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `uvicorn/config.py`
Content:
```
1 import asyncio
2 import inspect
3 import logging
4 import socket
5 import ssl
6 import sys
7 from typing import List, Tuple
8 
9 from uvicorn.importer import ImportFromStringError, import_from_string
10 from uvicorn.middleware.asgi2 import ASGI2Middleware
11 from uvicorn.middleware.debug import DebugMiddleware
12 from uvicorn.middleware.message_logger import MessageLoggerMiddleware
13 from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
14 from uvicorn.middleware.wsgi import WSGIMiddleware
15 
16 LOG_LEVELS = {
17     "critical": logging.CRITICAL,
18     "error": logging.ERROR,
19     "warning": logging.WARNING,
20     "info": logging.INFO,
21     "debug": logging.DEBUG,
22 }
23 HTTP_PROTOCOLS = {
24     "auto": "uvicorn.protocols.http.auto:AutoHTTPProtocol",
25     "h11": "uvicorn.protocols.http.h11_impl:H11Protocol",
26     "httptools": "uvicorn.protocols.http.httptools_impl:HttpToolsProtocol",
27 }
28 WS_PROTOCOLS = {
29     "none": None,
30     "auto": "uvicorn.protocols.websockets.auto:AutoWebSocketsProtocol",
31     "websockets": "uvicorn.protocols.websockets.websockets_impl:WebSocketProtocol",
32     "wsproto": "uvicorn.protocols.websockets.wsproto_impl:WSProtocol",
33 }
34 LIFESPAN = {
35     "auto": "uvicorn.lifespan.on:LifespanOn",
36     "on": "uvicorn.lifespan.on:LifespanOn",
37     "off": "uvicorn.lifespan.off:LifespanOff",
38 }
39 LOOP_SETUPS = {
40     "auto": "uvicorn.loops.auto:auto_loop_setup",
41     "asyncio": "uvicorn.loops.asyncio:asyncio_setup",
42     "uvloop": "uvicorn.loops.uvloop:uvloop_setup",
43 }
44 INTERFACES = ["auto", "asgi3", "asgi2", "wsgi"]
45 
46 # Fallback to 'ssl.PROTOCOL_SSLv23' in order to support Python < 3.5.3.
47 SSL_PROTOCOL_VERSION = getattr(ssl, "PROTOCOL_TLS", ssl.PROTOCOL_SSLv23)
48 
49 
50 def get_logger(log_level):
51     if isinstance(log_level, str):
52         log_level = LOG_LEVELS[log_level]
53     logging.basicConfig(format="%(levelname)s: %(message)s", level=log_level)
54     logger = logging.getLogger("uvicorn")
55     logger.setLevel(log_level)
56     return logger
57 
58 
59 def create_ssl_context(certfile, keyfile, ssl_version, cert_reqs, ca_certs, ciphers):
60     ctx = ssl.SSLContext(ssl_version)
61     ctx.load_cert_chain(certfile, keyfile)
62     ctx.verify_mode = cert_reqs
63     if ca_certs:
64         ctx.load_verify_locations(ca_certs)
65     if ciphers:
66         ctx.set_ciphers(ciphers)
67     return ctx
68 
69 
70 class Config:
71     def __init__(
72         self,
73         app,
74         host="127.0.0.1",
75         port=8000,
76         uds=None,
77         fd=None,
78         loop="auto",
79         http="auto",
80         ws="auto",
81         lifespan="auto",
82         log_level="info",
83         logger=None,
84         access_log=True,
85         interface="auto",
86         debug=False,
87         reload=False,
88         reload_dirs=None,
89         workers=1,
90         proxy_headers=False,
91         root_path="",
92         limit_concurrency=None,
93         limit_max_requests=None,
94         timeout_keep_alive=5,
95         timeout_notify=30,
96         callback_notify=None,
97         ssl_keyfile=None,
98         ssl_certfile=None,
99         ssl_version=SSL_PROTOCOL_VERSION,
100         ssl_cert_reqs=ssl.CERT_NONE,
101         ssl_ca_certs=None,
102         ssl_ciphers="TLSv1",
103         headers=None,
104     ):
105         self.app = app
106         self.host = host
107         self.port = port
108         self.uds = uds
109         self.fd = fd
110         self.loop = loop
111         self.http = http
112         self.ws = ws
113         self.lifespan = lifespan
114         self.log_level = log_level
115         self.logger = logger
116         self.access_log = access_log
117         self.interface = interface
118         self.debug = debug
119         self.reload = reload
120         self.workers = workers
121         self.proxy_headers = proxy_headers
122         self.root_path = root_path
123         self.limit_concurrency = limit_concurrency
124         self.limit_max_requests = limit_max_requests
125         self.timeout_keep_alive = timeout_keep_alive
126         self.timeout_notify = timeout_notify
127         self.callback_notify = callback_notify
128         self.ssl_keyfile = ssl_keyfile
129         self.ssl_certfile = ssl_certfile
130         self.ssl_version = ssl_version
131         self.ssl_cert_reqs = ssl_cert_reqs
132         self.ssl_ca_certs = ssl_ca_certs
133         self.ssl_ciphers = ssl_ciphers
134         self.headers = headers if headers else []  # type: List[str]
135         self.encoded_headers = None  # type: List[Tuple[bytes, bytes]]
136 
137         if self.ssl_keyfile or self.ssl_certfile:
138             self.ssl = create_ssl_context(
139                 keyfile=self.ssl_keyfile,
140                 certfile=self.ssl_certfile,
141                 ssl_version=self.ssl_version,
142                 cert_reqs=self.ssl_cert_reqs,
143                 ca_certs=self.ssl_ca_certs,
144                 ciphers=self.ssl_ciphers,
145             )
146         else:
147             self.ssl = None
148 
149         if reload_dirs is None:
150             self.reload_dirs = sys.path
151         else:
152             self.reload_dirs = reload_dirs
153 
154         self.loaded = False
155 
156     def load(self):
157         assert not self.loaded
158 
159         encoded_headers = [
160             (key.lower().encode("latin1"), value.encode("latin1"))
161             for key, value in self.headers
162         ]
163         self.encoded_headers = (
164             encoded_headers
165             if b"server" in dict(encoded_headers)
166             else [(b"server", b"uvicorn")] + encoded_headers
167         )  # type: List[Tuple[bytes, bytes]]
168 
169         if isinstance(self.http, str):
170             self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http])
171         else:
172             self.http_protocol_class = self.http
173 
174         if isinstance(self.ws, str):
175             self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws])
176         else:
177             self.ws_protocol_class = self.ws
178 
179         self.lifespan_class = import_from_string(LIFESPAN[self.lifespan])
180 
181         try:
182             self.loaded_app = import_from_string(self.app)
183         except ImportFromStringError as exc:
184             self.logger_instance.error("Error loading ASGI app. %s" % exc)
185             sys.exit(1)
186 
187         if self.interface == "auto":
188             if inspect.isclass(self.loaded_app):
189                 use_asgi_3 = hasattr(self.loaded_app, "__await__")
190             elif inspect.isfunction(self.loaded_app):
191                 use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app)
192             else:
193                 call = getattr(self.loaded_app, "__call__", None)
194                 use_asgi_3 = asyncio.iscoroutinefunction(call)
195             self.interface = "asgi3" if use_asgi_3 else "asgi2"
196 
197         if self.interface == "wsgi":
198             self.loaded_app = WSGIMiddleware(self.loaded_app)
199             self.ws_protocol_class = None
200         elif self.interface == "asgi2":
201             self.loaded_app = ASGI2Middleware(self.loaded_app)
202 
203         if self.debug:
204             self.loaded_app = DebugMiddleware(self.loaded_app)
205         if self.logger_instance.level <= logging.DEBUG:
206             self.loaded_app = MessageLoggerMiddleware(self.loaded_app)
207         if self.proxy_headers:
208             self.loaded_app = ProxyHeadersMiddleware(self.loaded_app)
209 
210         self.loaded = True
211 
212     def setup_event_loop(self):
213         loop_setup = import_from_string(LOOP_SETUPS[self.loop])
214         loop_setup()
215 
216     def bind_socket(self):
217         sock = socket.socket()
218         sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
219         sock.bind((self.host, self.port))
220         sock.set_inheritable(True)
221         message = "Uvicorn running on %s://%s:%d (Press CTRL+C to quit)"
222         protocol_name = "https" if self.ssl else "http"
223         self.logger_instance.info(message % (protocol_name, self.host, self.port))
224         return sock
225 
226     @property
227     def logger_instance(self):
228         if self.logger is not None:
229             return self.logger
230         return get_logger(self.log_level)
231
```
--- 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/uvicorn/config.py b/uvicorn/config.py
--- a/uvicorn/config.py
+++ b/uvicorn/config.py
@@ -134,6 +134,16 @@
         self.headers = headers if headers else []  # type: List[str]
         self.encoded_headers = None  # type: List[Tuple[bytes, bytes]]
 
+        if reload_dirs is None:
+            self.reload_dirs = sys.path
+        else:
+            self.reload_dirs = reload_dirs
+
+        self.loaded = False
+
+    def load(self):
+        assert not self.loaded
+
         if self.ssl_keyfile or self.ssl_certfile:
             self.ssl = create_ssl_context(
                 keyfile=self.ssl_keyfile,
@@ -146,16 +156,6 @@
         else:
             self.ssl = None
 
-        if reload_dirs is None:
-            self.reload_dirs = sys.path
-        else:
-            self.reload_dirs = reload_dirs
-
-        self.loaded = False
-
-    def load(self):
-        assert not self.loaded
-
         encoded_headers = [
             (key.lower().encode("latin1"), value.encode("latin1"))
             for key, value in self.headers

{"golden_diff": "diff --git a/uvicorn/config.py b/uvicorn/config.py\n--- a/uvicorn/config.py\n+++ b/uvicorn/config.py\n@@ -134,6 +134,16 @@\n         self.headers = headers if headers else []  # type: List[str]\n         self.encoded_headers = None  # type: List[Tuple[bytes, bytes]]\n \n+        if reload_dirs is None:\n+            self.reload_dirs = sys.path\n+        else:\n+            self.reload_dirs = reload_dirs\n+\n+        self.loaded = False\n+\n+    def load(self):\n+        assert not self.loaded\n+\n         if self.ssl_keyfile or self.ssl_certfile:\n             self.ssl = create_ssl_context(\n                 keyfile=self.ssl_keyfile,\n@@ -146,16 +156,6 @@\n         else:\n             self.ssl = None\n \n-        if reload_dirs is None:\n-            self.reload_dirs = sys.path\n-        else:\n-            self.reload_dirs = reload_dirs\n-\n-        self.loaded = False\n-\n-    def load(self):\n-        assert not self.loaded\n-\n         encoded_headers = [\n             (key.lower().encode(\"latin1\"), value.encode(\"latin1\"))\n             for key, value in self.headers\n", "issue": "Crash when using --reload and SSL certificate\nUsing the example code\r\n```python\r\nasync def app(scope, receive, send):\r\n    assert scope['type'] == 'http'\r\n\r\n    await send({\r\n        'type': 'http.response.start',\r\n        'status': 200,\r\n        'headers': [\r\n            [b'content-type', b'text/plain'],\r\n        ],\r\n    })\r\n    await send({\r\n        'type': 'http.response.body',\r\n        'body': b'Hello, world!',\r\n    })\r\n```\r\n\r\nwith a certificate created by `mkcert` in the current directory, and running \r\n`uvicorn ssl:app --reload --ssl-keyfile=./uvicorn.localhost-key.pem --ssl-certfile=./uvicorn.localhost.pem` results in the following error:\r\n\r\n<details>\r\n<summary>Stacktrace</summary>\r\n\r\n```\r\nINFO: Uvicorn running on https://127.0.0.1:8000 (Press CTRL+C to quit)\r\nINFO: Started reloader process [31388]\r\nTraceback (most recent call last):\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/bin/uvicorn\", line 11, in <module>\r\n    load_entry_point('uvicorn==0.7.0', 'console_scripts', 'uvicorn')()\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py\", line 764, in __call__\r\n    return self.main(*args, **kwargs)\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py\", line 717, in main\r\n    rv = self.invoke(ctx)\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py\", line 956, in invoke\r\n    return ctx.invoke(self.callback, **ctx.params)\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/click/core.py\", line 555, in invoke\r\n    return callback(*args, **kwargs)\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/uvicorn/main.py\", line 256, in main\r\n    run(**kwargs)\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/uvicorn/main.py\", line 271, in run\r\n    supervisor.run(server.run, sockets=[socket])\r\n  File \"/tmp/tmp.zVyoktn22U/.venv/lib/python3.7/site-packages/uvicorn/supervisors/statreload.py\", line 34, in run\r\n    process.start()\r\n  File \"/usr/lib/python3.7/multiprocessing/process.py\", line 112, in start\r\n    self._popen = self._Popen(self)\r\n  File \"/usr/lib/python3.7/multiprocessing/context.py\", line 284, in _Popen\r\n    return Popen(process_obj)\r\n  File \"/usr/lib/python3.7/multiprocessing/popen_spawn_posix.py\", line 32, in __init__\r\n    super().__init__(process_obj)\r\n  File \"/usr/lib/python3.7/multiprocessing/popen_fork.py\", line 20, in __init__\r\n    self._launch(process_obj)\r\n  File \"/usr/lib/python3.7/multiprocessing/popen_spawn_posix.py\", line 47, in _launch\r\n    reduction.dump(process_obj, fp)\r\n  File \"/usr/lib/python3.7/multiprocessing/reduction.py\", line 60, in dump\r\n    ForkingPickler(file, protocol).dump(obj)\r\nTypeError: can't pickle SSLContext objects\r\n```\r\n</details>\r\n\r\n*Environment:*\r\n`python -V`: Python 3.7.3\r\n`uvicorn`: 0.7.0\r\n`uname -a`: `Linux architect 5.0.9-arch1-1-ARCH #1 SMP PREEMPT Sat Apr 20 15:00:46 UTC 2019 x86_64 GNU/Linux`\n", "before_files": [{"content": "import asyncio\nimport inspect\nimport logging\nimport socket\nimport ssl\nimport sys\nfrom typing import List, Tuple\n\nfrom uvicorn.importer import ImportFromStringError, import_from_string\nfrom uvicorn.middleware.asgi2 import ASGI2Middleware\nfrom uvicorn.middleware.debug import DebugMiddleware\nfrom uvicorn.middleware.message_logger import MessageLoggerMiddleware\nfrom uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware\nfrom uvicorn.middleware.wsgi import WSGIMiddleware\n\nLOG_LEVELS = {\n    \"critical\": logging.CRITICAL,\n    \"error\": logging.ERROR,\n    \"warning\": logging.WARNING,\n    \"info\": logging.INFO,\n    \"debug\": logging.DEBUG,\n}\nHTTP_PROTOCOLS = {\n    \"auto\": \"uvicorn.protocols.http.auto:AutoHTTPProtocol\",\n    \"h11\": \"uvicorn.protocols.http.h11_impl:H11Protocol\",\n    \"httptools\": \"uvicorn.protocols.http.httptools_impl:HttpToolsProtocol\",\n}\nWS_PROTOCOLS = {\n    \"none\": None,\n    \"auto\": \"uvicorn.protocols.websockets.auto:AutoWebSocketsProtocol\",\n    \"websockets\": \"uvicorn.protocols.websockets.websockets_impl:WebSocketProtocol\",\n    \"wsproto\": \"uvicorn.protocols.websockets.wsproto_impl:WSProtocol\",\n}\nLIFESPAN = {\n    \"auto\": \"uvicorn.lifespan.on:LifespanOn\",\n    \"on\": \"uvicorn.lifespan.on:LifespanOn\",\n    \"off\": \"uvicorn.lifespan.off:LifespanOff\",\n}\nLOOP_SETUPS = {\n    \"auto\": \"uvicorn.loops.auto:auto_loop_setup\",\n    \"asyncio\": \"uvicorn.loops.asyncio:asyncio_setup\",\n    \"uvloop\": \"uvicorn.loops.uvloop:uvloop_setup\",\n}\nINTERFACES = [\"auto\", \"asgi3\", \"asgi2\", \"wsgi\"]\n\n# Fallback to 'ssl.PROTOCOL_SSLv23' in order to support Python < 3.5.3.\nSSL_PROTOCOL_VERSION = getattr(ssl, \"PROTOCOL_TLS\", ssl.PROTOCOL_SSLv23)\n\n\ndef get_logger(log_level):\n    if isinstance(log_level, str):\n        log_level = LOG_LEVELS[log_level]\n    logging.basicConfig(format=\"%(levelname)s: %(message)s\", level=log_level)\n    logger = logging.getLogger(\"uvicorn\")\n    logger.setLevel(log_level)\n    return logger\n\n\ndef create_ssl_context(certfile, keyfile, ssl_version, cert_reqs, ca_certs, ciphers):\n    ctx = ssl.SSLContext(ssl_version)\n    ctx.load_cert_chain(certfile, keyfile)\n    ctx.verify_mode = cert_reqs\n    if ca_certs:\n        ctx.load_verify_locations(ca_certs)\n    if ciphers:\n        ctx.set_ciphers(ciphers)\n    return ctx\n\n\nclass Config:\n    def __init__(\n        self,\n        app,\n        host=\"127.0.0.1\",\n        port=8000,\n        uds=None,\n        fd=None,\n        loop=\"auto\",\n        http=\"auto\",\n        ws=\"auto\",\n        lifespan=\"auto\",\n        log_level=\"info\",\n        logger=None,\n        access_log=True,\n        interface=\"auto\",\n        debug=False,\n        reload=False,\n        reload_dirs=None,\n        workers=1,\n        proxy_headers=False,\n        root_path=\"\",\n        limit_concurrency=None,\n        limit_max_requests=None,\n        timeout_keep_alive=5,\n        timeout_notify=30,\n        callback_notify=None,\n        ssl_keyfile=None,\n        ssl_certfile=None,\n        ssl_version=SSL_PROTOCOL_VERSION,\n        ssl_cert_reqs=ssl.CERT_NONE,\n        ssl_ca_certs=None,\n        ssl_ciphers=\"TLSv1\",\n        headers=None,\n    ):\n        self.app = app\n        self.host = host\n        self.port = port\n        self.uds = uds\n        self.fd = fd\n        self.loop = loop\n        self.http = http\n        self.ws = ws\n        self.lifespan = lifespan\n        self.log_level = log_level\n        self.logger = logger\n        self.access_log = access_log\n        self.interface = interface\n        self.debug = debug\n        self.reload = reload\n        self.workers = workers\n        self.proxy_headers = proxy_headers\n        self.root_path = root_path\n        self.limit_concurrency = limit_concurrency\n        self.limit_max_requests = limit_max_requests\n        self.timeout_keep_alive = timeout_keep_alive\n        self.timeout_notify = timeout_notify\n        self.callback_notify = callback_notify\n        self.ssl_keyfile = ssl_keyfile\n        self.ssl_certfile = ssl_certfile\n        self.ssl_version = ssl_version\n        self.ssl_cert_reqs = ssl_cert_reqs\n        self.ssl_ca_certs = ssl_ca_certs\n        self.ssl_ciphers = ssl_ciphers\n        self.headers = headers if headers else []  # type: List[str]\n        self.encoded_headers = None  # type: List[Tuple[bytes, bytes]]\n\n        if self.ssl_keyfile or self.ssl_certfile:\n            self.ssl = create_ssl_context(\n                keyfile=self.ssl_keyfile,\n                certfile=self.ssl_certfile,\n                ssl_version=self.ssl_version,\n                cert_reqs=self.ssl_cert_reqs,\n                ca_certs=self.ssl_ca_certs,\n                ciphers=self.ssl_ciphers,\n            )\n        else:\n            self.ssl = None\n\n        if reload_dirs is None:\n            self.reload_dirs = sys.path\n        else:\n            self.reload_dirs = reload_dirs\n\n        self.loaded = False\n\n    def load(self):\n        assert not self.loaded\n\n        encoded_headers = [\n            (key.lower().encode(\"latin1\"), value.encode(\"latin1\"))\n            for key, value in self.headers\n        ]\n        self.encoded_headers = (\n            encoded_headers\n            if b\"server\" in dict(encoded_headers)\n            else [(b\"server\", b\"uvicorn\")] + encoded_headers\n        )  # type: List[Tuple[bytes, bytes]]\n\n        if isinstance(self.http, str):\n            self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http])\n        else:\n            self.http_protocol_class = self.http\n\n        if isinstance(self.ws, str):\n            self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws])\n        else:\n            self.ws_protocol_class = self.ws\n\n        self.lifespan_class = import_from_string(LIFESPAN[self.lifespan])\n\n        try:\n            self.loaded_app = import_from_string(self.app)\n        except ImportFromStringError as exc:\n            self.logger_instance.error(\"Error loading ASGI app. %s\" % exc)\n            sys.exit(1)\n\n        if self.interface == \"auto\":\n            if inspect.isclass(self.loaded_app):\n                use_asgi_3 = hasattr(self.loaded_app, \"__await__\")\n            elif inspect.isfunction(self.loaded_app):\n                use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app)\n            else:\n                call = getattr(self.loaded_app, \"__call__\", None)\n                use_asgi_3 = asyncio.iscoroutinefunction(call)\n            self.interface = \"asgi3\" if use_asgi_3 else \"asgi2\"\n\n        if self.interface == \"wsgi\":\n            self.loaded_app = WSGIMiddleware(self.loaded_app)\n            self.ws_protocol_class = None\n        elif self.interface == \"asgi2\":\n            self.loaded_app = ASGI2Middleware(self.loaded_app)\n\n        if self.debug:\n            self.loaded_app = DebugMiddleware(self.loaded_app)\n        if self.logger_instance.level <= logging.DEBUG:\n            self.loaded_app = MessageLoggerMiddleware(self.loaded_app)\n        if self.proxy_headers:\n            self.loaded_app = ProxyHeadersMiddleware(self.loaded_app)\n\n        self.loaded = True\n\n    def setup_event_loop(self):\n        loop_setup = import_from_string(LOOP_SETUPS[self.loop])\n        loop_setup()\n\n    def bind_socket(self):\n        sock = socket.socket()\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind((self.host, self.port))\n        sock.set_inheritable(True)\n        message = \"Uvicorn running on %s://%s:%d (Press CTRL+C to quit)\"\n        protocol_name = \"https\" if self.ssl else \"http\"\n        self.logger_instance.info(message % (protocol_name, self.host, self.port))\n        return sock\n\n    @property\n    def logger_instance(self):\n        if self.logger is not None:\n            return self.logger\n        return get_logger(self.log_level)\n", "path": "uvicorn/config.py"}], "after_files": [{"content": "import asyncio\nimport inspect\nimport logging\nimport socket\nimport ssl\nimport sys\nfrom typing import List, Tuple\n\nfrom uvicorn.importer import ImportFromStringError, import_from_string\nfrom uvicorn.middleware.asgi2 import ASGI2Middleware\nfrom uvicorn.middleware.debug import DebugMiddleware\nfrom uvicorn.middleware.message_logger import MessageLoggerMiddleware\nfrom uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware\nfrom uvicorn.middleware.wsgi import WSGIMiddleware\n\nLOG_LEVELS = {\n    \"critical\": logging.CRITICAL,\n    \"error\": logging.ERROR,\n    \"warning\": logging.WARNING,\n    \"info\": logging.INFO,\n    \"debug\": logging.DEBUG,\n}\nHTTP_PROTOCOLS = {\n    \"auto\": \"uvicorn.protocols.http.auto:AutoHTTPProtocol\",\n    \"h11\": \"uvicorn.protocols.http.h11_impl:H11Protocol\",\n    \"httptools\": \"uvicorn.protocols.http.httptools_impl:HttpToolsProtocol\",\n}\nWS_PROTOCOLS = {\n    \"none\": None,\n    \"auto\": \"uvicorn.protocols.websockets.auto:AutoWebSocketsProtocol\",\n    \"websockets\": \"uvicorn.protocols.websockets.websockets_impl:WebSocketProtocol\",\n    \"wsproto\": \"uvicorn.protocols.websockets.wsproto_impl:WSProtocol\",\n}\nLIFESPAN = {\n    \"auto\": \"uvicorn.lifespan.on:LifespanOn\",\n    \"on\": \"uvicorn.lifespan.on:LifespanOn\",\n    \"off\": \"uvicorn.lifespan.off:LifespanOff\",\n}\nLOOP_SETUPS = {\n    \"auto\": \"uvicorn.loops.auto:auto_loop_setup\",\n    \"asyncio\": \"uvicorn.loops.asyncio:asyncio_setup\",\n    \"uvloop\": \"uvicorn.loops.uvloop:uvloop_setup\",\n}\nINTERFACES = [\"auto\", \"asgi3\", \"asgi2\", \"wsgi\"]\n\n# Fallback to 'ssl.PROTOCOL_SSLv23' in order to support Python < 3.5.3.\nSSL_PROTOCOL_VERSION = getattr(ssl, \"PROTOCOL_TLS\", ssl.PROTOCOL_SSLv23)\n\n\ndef get_logger(log_level):\n    if isinstance(log_level, str):\n        log_level = LOG_LEVELS[log_level]\n    logging.basicConfig(format=\"%(levelname)s: %(message)s\", level=log_level)\n    logger = logging.getLogger(\"uvicorn\")\n    logger.setLevel(log_level)\n    return logger\n\n\ndef create_ssl_context(certfile, keyfile, ssl_version, cert_reqs, ca_certs, ciphers):\n    ctx = ssl.SSLContext(ssl_version)\n    ctx.load_cert_chain(certfile, keyfile)\n    ctx.verify_mode = cert_reqs\n    if ca_certs:\n        ctx.load_verify_locations(ca_certs)\n    if ciphers:\n        ctx.set_ciphers(ciphers)\n    return ctx\n\n\nclass Config:\n    def __init__(\n        self,\n        app,\n        host=\"127.0.0.1\",\n        port=8000,\n        uds=None,\n        fd=None,\n        loop=\"auto\",\n        http=\"auto\",\n        ws=\"auto\",\n        lifespan=\"auto\",\n        log_level=\"info\",\n        logger=None,\n        access_log=True,\n        interface=\"auto\",\n        debug=False,\n        reload=False,\n        reload_dirs=None,\n        workers=1,\n        proxy_headers=False,\n        root_path=\"\",\n        limit_concurrency=None,\n        limit_max_requests=None,\n        timeout_keep_alive=5,\n        timeout_notify=30,\n        callback_notify=None,\n        ssl_keyfile=None,\n        ssl_certfile=None,\n        ssl_version=SSL_PROTOCOL_VERSION,\n        ssl_cert_reqs=ssl.CERT_NONE,\n        ssl_ca_certs=None,\n        ssl_ciphers=\"TLSv1\",\n        headers=None,\n    ):\n        self.app = app\n        self.host = host\n        self.port = port\n        self.uds = uds\n        self.fd = fd\n        self.loop = loop\n        self.http = http\n        self.ws = ws\n        self.lifespan = lifespan\n        self.log_level = log_level\n        self.logger = logger\n        self.access_log = access_log\n        self.interface = interface\n        self.debug = debug\n        self.reload = reload\n        self.workers = workers\n        self.proxy_headers = proxy_headers\n        self.root_path = root_path\n        self.limit_concurrency = limit_concurrency\n        self.limit_max_requests = limit_max_requests\n        self.timeout_keep_alive = timeout_keep_alive\n        self.timeout_notify = timeout_notify\n        self.callback_notify = callback_notify\n        self.ssl_keyfile = ssl_keyfile\n        self.ssl_certfile = ssl_certfile\n        self.ssl_version = ssl_version\n        self.ssl_cert_reqs = ssl_cert_reqs\n        self.ssl_ca_certs = ssl_ca_certs\n        self.ssl_ciphers = ssl_ciphers\n        self.headers = headers if headers else []  # type: List[str]\n        self.encoded_headers = None  # type: List[Tuple[bytes, bytes]]\n\n        if reload_dirs is None:\n            self.reload_dirs = sys.path\n        else:\n            self.reload_dirs = reload_dirs\n\n        self.loaded = False\n\n    def load(self):\n        assert not self.loaded\n\n        if self.ssl_keyfile or self.ssl_certfile:\n            self.ssl = create_ssl_context(\n                keyfile=self.ssl_keyfile,\n                certfile=self.ssl_certfile,\n                ssl_version=self.ssl_version,\n                cert_reqs=self.ssl_cert_reqs,\n                ca_certs=self.ssl_ca_certs,\n                ciphers=self.ssl_ciphers,\n            )\n        else:\n            self.ssl = None\n\n        encoded_headers = [\n            (key.lower().encode(\"latin1\"), value.encode(\"latin1\"))\n            for key, value in self.headers\n        ]\n        self.encoded_headers = (\n            encoded_headers\n            if b\"server\" in dict(encoded_headers)\n            else [(b\"server\", b\"uvicorn\")] + encoded_headers\n        )  # type: List[Tuple[bytes, bytes]]\n\n        if isinstance(self.http, str):\n            self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http])\n        else:\n            self.http_protocol_class = self.http\n\n        if isinstance(self.ws, str):\n            self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws])\n        else:\n            self.ws_protocol_class = self.ws\n\n        self.lifespan_class = import_from_string(LIFESPAN[self.lifespan])\n\n        try:\n            self.loaded_app = import_from_string(self.app)\n        except ImportFromStringError as exc:\n            self.logger_instance.error(\"Error loading ASGI app. %s\" % exc)\n            sys.exit(1)\n\n        if self.interface == \"auto\":\n            if inspect.isclass(self.loaded_app):\n                use_asgi_3 = hasattr(self.loaded_app, \"__await__\")\n            elif inspect.isfunction(self.loaded_app):\n                use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app)\n            else:\n                call = getattr(self.loaded_app, \"__call__\", None)\n                use_asgi_3 = asyncio.iscoroutinefunction(call)\n            self.interface = \"asgi3\" if use_asgi_3 else \"asgi2\"\n\n        if self.interface == \"wsgi\":\n            self.loaded_app = WSGIMiddleware(self.loaded_app)\n            self.ws_protocol_class = None\n        elif self.interface == \"asgi2\":\n            self.loaded_app = ASGI2Middleware(self.loaded_app)\n\n        if self.debug:\n            self.loaded_app = DebugMiddleware(self.loaded_app)\n        if self.logger_instance.level <= logging.DEBUG:\n            self.loaded_app = MessageLoggerMiddleware(self.loaded_app)\n        if self.proxy_headers:\n            self.loaded_app = ProxyHeadersMiddleware(self.loaded_app)\n\n        self.loaded = True\n\n    def setup_event_loop(self):\n        loop_setup = import_from_string(LOOP_SETUPS[self.loop])\n        loop_setup()\n\n    def bind_socket(self):\n        sock = socket.socket()\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind((self.host, self.port))\n        sock.set_inheritable(True)\n        message = \"Uvicorn running on %s://%s:%d (Press CTRL+C to quit)\"\n        protocol_name = \"https\" if self.ssl else \"http\"\n        self.logger_instance.info(message % (protocol_name, self.host, self.port))\n        return sock\n\n    @property\n    def logger_instance(self):\n        if self.logger is not None:\n            return self.logger\n        return get_logger(self.log_level)\n", "path": "uvicorn/config.py"}]}