prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Poetry does not gracefully shutdown on CTRL+C
  This is a bit critical, bad things can happen if LNbits is just killed without finishing off all routines.
  
  Poetry with `poetry run lnbits`:
  <img width="700" alt="image" src="https://user-images.githubusercontent.com/93376500/182562297-6850567b-6fb3-4003-ac9c-317d92392b04.png">
  
  Running lnbits using `./venv/bin/uvicorn lnbits.__main__:app`:
  <img width="671" alt="image" src="https://user-images.githubusercontent.com/93376500/182562341-b4d56bfa-bf4f-4981-84e6-06678923439f.png">
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lnbits/server.py`
  Content:
  ```
  1 import click
  2 import uvicorn
  3 
  4 
  5 @click.command()
  6 @click.option("--port", default="5000", help="Port to run LNBits on")
  7 @click.option("--host", default="127.0.0.1", help="Host to run LNBits on")
  8 def main(port, host):
  9     """Launched with `poetry run lnbits` at root level"""
  10     uvicorn.run("lnbits.__main__:app", port=port, host=host)
  11 
  12 
  13 if __name__ == "__main__":
  14     main()
  15 
  16 # def main():
  17 #    """Launched with `poetry run start` at root level"""
  18 #    uvicorn.run("lnbits.__main__:app")
  19
  ```
  
  Path: `build.py`
  Content:
  ```
  1 import warnings
  2 import subprocess
  3 import glob
  4 import os
  5 from os import path
  6 from typing import Any, List, NamedTuple, Optional
  7 from pathlib import Path
  8 
  9 LNBITS_PATH = path.dirname(path.realpath(__file__)) + "/lnbits"
  10 
  11 def get_js_vendored(prefer_minified: bool = False) -> List[str]:
  12     paths = get_vendored(".js", prefer_minified)
  13 
  14     def sorter(key: str):
  15         if "moment@" in key:
  16             return 1
  17         if "vue@" in key:
  18             return 2
  19         if "vue-router@" in key:
  20             return 3
  21         if "polyfills" in key:
  22             return 4
  23         return 9
  24 
  25     return sorted(paths, key=sorter)
  26 
  27 
  28 def get_css_vendored(prefer_minified: bool = False) -> List[str]:
  29     paths = get_vendored(".css", prefer_minified)
  30 
  31     def sorter(key: str):
  32         if "quasar@" in key:
  33             return 1
  34         if "vue@" in key:
  35             return 2
  36         if "chart.js@" in key:
  37             return 100
  38         return 9
  39 
  40     return sorted(paths, key=sorter)
  41 
  42 
  43 def get_vendored(ext: str, prefer_minified: bool = False) -> List[str]:
  44     paths: List[str] = []
  45     for path in glob.glob(
  46         os.path.join(LNBITS_PATH, "static/vendor/**"), recursive=True
  47     ):
  48         if path.endswith(".min" + ext):
  49             # path is minified
  50             unminified = path.replace(".min" + ext, ext)
  51             if prefer_minified:
  52                 paths.append(path)
  53                 if unminified in paths:
  54                     paths.remove(unminified)
  55             elif unminified not in paths:
  56                 paths.append(path)
  57 
  58         elif path.endswith(ext):
  59             # path is not minified
  60             minified = path.replace(ext, ".min" + ext)
  61             if not prefer_minified:
  62                 paths.append(path)
  63                 if minified in paths:
  64                     paths.remove(minified)
  65             elif minified not in paths:
  66                 paths.append(path)
  67 
  68     return sorted(paths)
  69 
  70 
  71 def url_for_vendored(abspath: str) -> str:
  72     return "/" + os.path.relpath(abspath, LNBITS_PATH)
  73 
  74 def transpile_scss():
  75     with warnings.catch_warnings():
  76         warnings.simplefilter("ignore")
  77         from scss.compiler import compile_string  # type: ignore
  78 
  79         with open(os.path.join(LNBITS_PATH, "static/scss/base.scss")) as scss:
  80             with open(os.path.join(LNBITS_PATH, "static/css/base.css"), "w") as css:
  81                 css.write(compile_string(scss.read()))
  82 
  83 def bundle_vendored():
  84     for getfiles, outputpath in [
  85         (get_js_vendored, os.path.join(LNBITS_PATH, "static/bundle.js")),
  86         (get_css_vendored, os.path.join(LNBITS_PATH, "static/bundle.css")),
  87     ]:
  88         output = ""
  89         for path in getfiles():
  90             with open(path) as f:
  91                 output += "/* " + url_for_vendored(path) + " */\n" + f.read() + ";\n"
  92         with open(outputpath, "w") as f:
  93             f.write(output)
  94 
  95 
  96 def build():
  97     transpile_scss()
  98     bundle_vendored()
  99 #    root = Path("lnbits/static/foo")
  100 #    root.mkdir(parents=True)
  101 #    root.joinpath("example.css").write_text("")
  102 
  103 if __name__ == "__main__":
  104    build()
  105 
  106 #def build(setup_kwargs):
  107 #    """Build """
  108 #    transpile_scss()
  109 #    bundle_vendored()
  110 #    subprocess.run(["ls", "-la", "./lnbits/static"])
  111
  ```
  --- 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/build.py b/build.py
  --- a/build.py
  +++ b/build.py
  @@ -8,6 +8,7 @@
   
   LNBITS_PATH = path.dirname(path.realpath(__file__)) + "/lnbits"
   
  +
   def get_js_vendored(prefer_minified: bool = False) -> List[str]:
       paths = get_vendored(".js", prefer_minified)
   
  @@ -71,6 +72,7 @@
   def url_for_vendored(abspath: str) -> str:
       return "/" + os.path.relpath(abspath, LNBITS_PATH)
   
  +
   def transpile_scss():
       with warnings.catch_warnings():
           warnings.simplefilter("ignore")
  @@ -80,6 +82,7 @@
               with open(os.path.join(LNBITS_PATH, "static/css/base.css"), "w") as css:
                   css.write(compile_string(scss.read()))
   
  +
   def bundle_vendored():
       for getfiles, outputpath in [
           (get_js_vendored, os.path.join(LNBITS_PATH, "static/bundle.js")),
  @@ -96,15 +99,7 @@
   def build():
       transpile_scss()
       bundle_vendored()
  -#    root = Path("lnbits/static/foo")
  -#    root.mkdir(parents=True)
  -#    root.joinpath("example.css").write_text("")
   
  -if __name__ == "__main__":
  -   build()
   
  -#def build(setup_kwargs):
  -#    """Build """
  -#    transpile_scss()
  -#    bundle_vendored()
  -#    subprocess.run(["ls", "-la", "./lnbits/static"])
  +if __name__ == "__main__":
  +    build()
  diff --git a/lnbits/server.py b/lnbits/server.py
  --- a/lnbits/server.py
  +++ b/lnbits/server.py
  @@ -1,18 +1,45 @@
  +import time
  +
   import click
   import uvicorn
   
  +from lnbits.settings import HOST, PORT
  +
   
  -@click.command()
  -@click.option("--port", default="5000", help="Port to run LNBits on")
  -@click.option("--host", default="127.0.0.1", help="Host to run LNBits on")
  -def main(port, host):
  +@click.command(
  +    context_settings=dict(
  +        ignore_unknown_options=True,
  +        allow_extra_args=True,
  +    )
  +)
  +@click.option("--port", default=PORT, help="Port to listen on")
  +@click.option("--host", default=HOST, help="Host to run LNBits on")
  +@click.option("--ssl-keyfile", default=None, help="Path to SSL keyfile")
  +@click.option("--ssl-certfile", default=None, help="Path to SSL certificate")
  +@click.pass_context
  +def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str):
       """Launched with `poetry run lnbits` at root level"""
  -    uvicorn.run("lnbits.__main__:app", port=port, host=host)
  +    # this beautiful beast parses all command line arguments and passes them to the uvicorn server
  +    d = dict(
  +        [
  +            (
  +                item[0].strip("--").replace("-", "_"),
  +                int(item[1]) if item[1].isdigit() else item[1],
  +            )
  +            for item in zip(*[iter(ctx.args)] * 2)
  +        ]
  +    )
  +    config = uvicorn.Config(
  +        "lnbits.__main__:app",
  +        port=port,
  +        host=host,
  +        ssl_keyfile=ssl_keyfile,
  +        ssl_certfile=ssl_certfile,
  +        **d
  +    )
  +    server = uvicorn.Server(config)
  +    server.run()
   
   
   if __name__ == "__main__":
       main()
  -
  -# def main():
  -#    """Launched with `poetry run start` at root level"""
  -#    uvicorn.run("lnbits.__main__:app")
  
verification_info: {"golden_diff": "diff --git a/build.py b/build.py\n--- a/build.py\n+++ b/build.py\n@@ -8,6 +8,7 @@\n \n LNBITS_PATH = path.dirname(path.realpath(__file__)) + \"/lnbits\"\n \n+\n def get_js_vendored(prefer_minified: bool = False) -> List[str]:\n     paths = get_vendored(\".js\", prefer_minified)\n \n@@ -71,6 +72,7 @@\n def url_for_vendored(abspath: str) -> str:\n     return \"/\" + os.path.relpath(abspath, LNBITS_PATH)\n \n+\n def transpile_scss():\n     with warnings.catch_warnings():\n         warnings.simplefilter(\"ignore\")\n@@ -80,6 +82,7 @@\n             with open(os.path.join(LNBITS_PATH, \"static/css/base.css\"), \"w\") as css:\n                 css.write(compile_string(scss.read()))\n \n+\n def bundle_vendored():\n     for getfiles, outputpath in [\n         (get_js_vendored, os.path.join(LNBITS_PATH, \"static/bundle.js\")),\n@@ -96,15 +99,7 @@\n def build():\n     transpile_scss()\n     bundle_vendored()\n-#    root = Path(\"lnbits/static/foo\")\n-#    root.mkdir(parents=True)\n-#    root.joinpath(\"example.css\").write_text(\"\")\n \n-if __name__ == \"__main__\":\n-   build()\n \n-#def build(setup_kwargs):\n-#    \"\"\"Build \"\"\"\n-#    transpile_scss()\n-#    bundle_vendored()\n-#    subprocess.run([\"ls\", \"-la\", \"./lnbits/static\"])\n+if __name__ == \"__main__\":\n+    build()\ndiff --git a/lnbits/server.py b/lnbits/server.py\n--- a/lnbits/server.py\n+++ b/lnbits/server.py\n@@ -1,18 +1,45 @@\n+import time\n+\n import click\n import uvicorn\n \n+from lnbits.settings import HOST, PORT\n+\n \n-@click.command()\n-@click.option(\"--port\", default=\"5000\", help=\"Port to run LNBits on\")\n-@click.option(\"--host\", default=\"127.0.0.1\", help=\"Host to run LNBits on\")\n-def main(port, host):\n+@click.command(\n+    context_settings=dict(\n+        ignore_unknown_options=True,\n+        allow_extra_args=True,\n+    )\n+)\n+@click.option(\"--port\", default=PORT, help=\"Port to listen on\")\n+@click.option(\"--host\", default=HOST, help=\"Host to run LNBits on\")\n+@click.option(\"--ssl-keyfile\", default=None, help=\"Path to SSL keyfile\")\n+@click.option(\"--ssl-certfile\", default=None, help=\"Path to SSL certificate\")\n+@click.pass_context\n+def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str):\n     \"\"\"Launched with `poetry run lnbits` at root level\"\"\"\n-    uvicorn.run(\"lnbits.__main__:app\", port=port, host=host)\n+    # this beautiful beast parses all command line arguments and passes them to the uvicorn server\n+    d = dict(\n+        [\n+            (\n+                item[0].strip(\"--\").replace(\"-\", \"_\"),\n+                int(item[1]) if item[1].isdigit() else item[1],\n+            )\n+            for item in zip(*[iter(ctx.args)] * 2)\n+        ]\n+    )\n+    config = uvicorn.Config(\n+        \"lnbits.__main__:app\",\n+        port=port,\n+        host=host,\n+        ssl_keyfile=ssl_keyfile,\n+        ssl_certfile=ssl_certfile,\n+        **d\n+    )\n+    server = uvicorn.Server(config)\n+    server.run()\n \n \n if __name__ == \"__main__\":\n     main()\n-\n-# def main():\n-#    \"\"\"Launched with `poetry run start` at root level\"\"\"\n-#    uvicorn.run(\"lnbits.__main__:app\")\n", "issue": "Poetry does not gracefully shutdown on CTRL+C\nThis is a bit critical, bad things can happen if LNbits is just killed without finishing off all routines.\r\n\r\nPoetry with `poetry run lnbits`:\r\n<img width=\"700\" alt=\"image\" src=\"https://user-images.githubusercontent.com/93376500/182562297-6850567b-6fb3-4003-ac9c-317d92392b04.png\">\r\n\r\nRunning lnbits using `./venv/bin/uvicorn lnbits.__main__:app`:\r\n<img width=\"671\" alt=\"image\" src=\"https://user-images.githubusercontent.com/93376500/182562341-b4d56bfa-bf4f-4981-84e6-06678923439f.png\">\r\n\n", "before_files": [{"content": "import click\nimport uvicorn\n\n\n@click.command()\n@click.option(\"--port\", default=\"5000\", help=\"Port to run LNBits on\")\n@click.option(\"--host\", default=\"127.0.0.1\", help=\"Host to run LNBits on\")\ndef main(port, host):\n    \"\"\"Launched with `poetry run lnbits` at root level\"\"\"\n    uvicorn.run(\"lnbits.__main__:app\", port=port, host=host)\n\n\nif __name__ == \"__main__\":\n    main()\n\n# def main():\n#    \"\"\"Launched with `poetry run start` at root level\"\"\"\n#    uvicorn.run(\"lnbits.__main__:app\")\n", "path": "lnbits/server.py"}, {"content": "import warnings\nimport subprocess\nimport glob\nimport os\nfrom os import path\nfrom typing import Any, List, NamedTuple, Optional\nfrom pathlib import Path\n\nLNBITS_PATH = path.dirname(path.realpath(__file__)) + \"/lnbits\"\n\ndef get_js_vendored(prefer_minified: bool = False) -> List[str]:\n    paths = get_vendored(\".js\", prefer_minified)\n\n    def sorter(key: str):\n        if \"moment@\" in key:\n            return 1\n        if \"vue@\" in key:\n            return 2\n        if \"vue-router@\" in key:\n            return 3\n        if \"polyfills\" in key:\n            return 4\n        return 9\n\n    return sorted(paths, key=sorter)\n\n\ndef get_css_vendored(prefer_minified: bool = False) -> List[str]:\n    paths = get_vendored(\".css\", prefer_minified)\n\n    def sorter(key: str):\n        if \"quasar@\" in key:\n            return 1\n        if \"vue@\" in key:\n            return 2\n        if \"chart.js@\" in key:\n            return 100\n        return 9\n\n    return sorted(paths, key=sorter)\n\n\ndef get_vendored(ext: str, prefer_minified: bool = False) -> List[str]:\n    paths: List[str] = []\n    for path in glob.glob(\n        os.path.join(LNBITS_PATH, \"static/vendor/**\"), recursive=True\n    ):\n        if path.endswith(\".min\" + ext):\n            # path is minified\n            unminified = path.replace(\".min\" + ext, ext)\n            if prefer_minified:\n                paths.append(path)\n                if unminified in paths:\n                    paths.remove(unminified)\n            elif unminified not in paths:\n                paths.append(path)\n\n        elif path.endswith(ext):\n            # path is not minified\n            minified = path.replace(ext, \".min\" + ext)\n            if not prefer_minified:\n                paths.append(path)\n                if minified in paths:\n                    paths.remove(minified)\n            elif minified not in paths:\n                paths.append(path)\n\n    return sorted(paths)\n\n\ndef url_for_vendored(abspath: str) -> str:\n    return \"/\" + os.path.relpath(abspath, LNBITS_PATH)\n\ndef transpile_scss():\n    with warnings.catch_warnings():\n        warnings.simplefilter(\"ignore\")\n        from scss.compiler import compile_string  # type: ignore\n\n        with open(os.path.join(LNBITS_PATH, \"static/scss/base.scss\")) as scss:\n            with open(os.path.join(LNBITS_PATH, \"static/css/base.css\"), \"w\") as css:\n                css.write(compile_string(scss.read()))\n\ndef bundle_vendored():\n    for getfiles, outputpath in [\n        (get_js_vendored, os.path.join(LNBITS_PATH, \"static/bundle.js\")),\n        (get_css_vendored, os.path.join(LNBITS_PATH, \"static/bundle.css\")),\n    ]:\n        output = \"\"\n        for path in getfiles():\n            with open(path) as f:\n                output += \"/* \" + url_for_vendored(path) + \" */\\n\" + f.read() + \";\\n\"\n        with open(outputpath, \"w\") as f:\n            f.write(output)\n\n\ndef build():\n    transpile_scss()\n    bundle_vendored()\n#    root = Path(\"lnbits/static/foo\")\n#    root.mkdir(parents=True)\n#    root.joinpath(\"example.css\").write_text(\"\")\n\nif __name__ == \"__main__\":\n   build()\n\n#def build(setup_kwargs):\n#    \"\"\"Build \"\"\"\n#    transpile_scss()\n#    bundle_vendored()\n#    subprocess.run([\"ls\", \"-la\", \"./lnbits/static\"])\n", "path": "build.py"}], "after_files": [{"content": "import time\n\nimport click\nimport uvicorn\n\nfrom lnbits.settings import HOST, PORT\n\n\n@click.command(\n    context_settings=dict(\n        ignore_unknown_options=True,\n        allow_extra_args=True,\n    )\n)\n@click.option(\"--port\", default=PORT, help=\"Port to listen on\")\n@click.option(\"--host\", default=HOST, help=\"Host to run LNBits on\")\n@click.option(\"--ssl-keyfile\", default=None, help=\"Path to SSL keyfile\")\n@click.option(\"--ssl-certfile\", default=None, help=\"Path to SSL certificate\")\n@click.pass_context\ndef main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str):\n    \"\"\"Launched with `poetry run lnbits` at root level\"\"\"\n    # this beautiful beast parses all command line arguments and passes them to the uvicorn server\n    d = dict(\n        [\n            (\n                item[0].strip(\"--\").replace(\"-\", \"_\"),\n                int(item[1]) if item[1].isdigit() else item[1],\n            )\n            for item in zip(*[iter(ctx.args)] * 2)\n        ]\n    )\n    config = uvicorn.Config(\n        \"lnbits.__main__:app\",\n        port=port,\n        host=host,\n        ssl_keyfile=ssl_keyfile,\n        ssl_certfile=ssl_certfile,\n        **d\n    )\n    server = uvicorn.Server(config)\n    server.run()\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "lnbits/server.py"}, {"content": "import warnings\nimport subprocess\nimport glob\nimport os\nfrom os import path\nfrom typing import Any, List, NamedTuple, Optional\nfrom pathlib import Path\n\nLNBITS_PATH = path.dirname(path.realpath(__file__)) + \"/lnbits\"\n\n\ndef get_js_vendored(prefer_minified: bool = False) -> List[str]:\n    paths = get_vendored(\".js\", prefer_minified)\n\n    def sorter(key: str):\n        if \"moment@\" in key:\n            return 1\n        if \"vue@\" in key:\n            return 2\n        if \"vue-router@\" in key:\n            return 3\n        if \"polyfills\" in key:\n            return 4\n        return 9\n\n    return sorted(paths, key=sorter)\n\n\ndef get_css_vendored(prefer_minified: bool = False) -> List[str]:\n    paths = get_vendored(\".css\", prefer_minified)\n\n    def sorter(key: str):\n        if \"quasar@\" in key:\n            return 1\n        if \"vue@\" in key:\n            return 2\n        if \"chart.js@\" in key:\n            return 100\n        return 9\n\n    return sorted(paths, key=sorter)\n\n\ndef get_vendored(ext: str, prefer_minified: bool = False) -> List[str]:\n    paths: List[str] = []\n    for path in glob.glob(\n        os.path.join(LNBITS_PATH, \"static/vendor/**\"), recursive=True\n    ):\n        if path.endswith(\".min\" + ext):\n            # path is minified\n            unminified = path.replace(\".min\" + ext, ext)\n            if prefer_minified:\n                paths.append(path)\n                if unminified in paths:\n                    paths.remove(unminified)\n            elif unminified not in paths:\n                paths.append(path)\n\n        elif path.endswith(ext):\n            # path is not minified\n            minified = path.replace(ext, \".min\" + ext)\n            if not prefer_minified:\n                paths.append(path)\n                if minified in paths:\n                    paths.remove(minified)\n            elif minified not in paths:\n                paths.append(path)\n\n    return sorted(paths)\n\n\ndef url_for_vendored(abspath: str) -> str:\n    return \"/\" + os.path.relpath(abspath, LNBITS_PATH)\n\n\ndef transpile_scss():\n    with warnings.catch_warnings():\n        warnings.simplefilter(\"ignore\")\n        from scss.compiler import compile_string  # type: ignore\n\n        with open(os.path.join(LNBITS_PATH, \"static/scss/base.scss\")) as scss:\n            with open(os.path.join(LNBITS_PATH, \"static/css/base.css\"), \"w\") as css:\n                css.write(compile_string(scss.read()))\n\n\ndef bundle_vendored():\n    for getfiles, outputpath in [\n        (get_js_vendored, os.path.join(LNBITS_PATH, \"static/bundle.js\")),\n        (get_css_vendored, os.path.join(LNBITS_PATH, \"static/bundle.css\")),\n    ]:\n        output = \"\"\n        for path in getfiles():\n            with open(path) as f:\n                output += \"/* \" + url_for_vendored(path) + \" */\\n\" + f.read() + \";\\n\"\n        with open(outputpath, \"w\") as f:\n            f.write(output)\n\n\ndef build():\n    transpile_scss()\n    bundle_vendored()\n\n\nif __name__ == \"__main__\":\n    build()\n", "path": "build.py"}]}