We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Improve reading of version file in Welcome View
* use caching because file is read every time user requests main page
* wrap in try-except (missing release notice should not break the main page)


FYI: @jh-RLI 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `base/views.py`
Content:
```
1 import json
2 import os
3 import re
4 
5 import markdown2
6 from django.core.mail import send_mail
7 from django.shortcuts import render
8 from django.views.generic import View
9 
10 try:
11     import oeplatform.securitysettings as sec
12 except Exception:
13     import logging
14 
15     logging.error("No securitysettings found. Triggerd in base/views.py")
16 
17 from base.forms import ContactForm
18 
19 # Create your views here.
20 
21 SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
22 
23 
24 class Welcome(View):
25     def get(self, request):
26         os.path.dirname(os.path.realpath(__file__))
27         version_expr = r"^(?P<major>\d+)\.(?P<minor>\d+)+\.(?P<patch>\d+)$"
28         markdowner = markdown2.Markdown()
29         with open(os.path.join(SITE_ROOT, "..", "VERSION")) as version_file:
30             match = re.match(version_expr, version_file.read())
31             major, minor, patch = match.groups()
32         with open(
33             os.path.join(
34                 SITE_ROOT,
35                 "..",
36                 "versions/changelogs/%s_%s_%s.md" % (major, minor, patch),
37             )
38         ) as change_file:
39             changes = markdowner.convert(
40                 "\n".join(line for line in change_file.readlines())
41             )
42         return render(
43             request,
44             "base/index.html",
45             {"version": "%s.%s.%s" % (major, minor, patch), "changes": changes},
46         )
47 
48 
49 def get_logs(request):
50     version_expr = r"^(?P<major>\d+)_(?P<major>\d+)+_(?P<major>\d+)\.md$"
51     logs = {}
52     for file in os.listdir("../versions/changelogs"):
53         match = re.match(version_expr, file)
54         markdowner = markdown2.Markdown()
55         if match:
56             major, minor, patch = match.groups()
57             with open("versions/changelogs" + file) as f:
58                 logs[(major, minor, patch)] = markdowner.convert(
59                     "\n".join(line for line in f.readlines())
60                 )
61     return logs
62 
63 
64 def redir(request, target):
65     return render(request, "base/{target}.html".format(target=target), {})
66 
67 
68 class ContactView(View):
69     error_css_class = "error"
70     required_css_class = "required"
71 
72     def post(self, request):
73         form = ContactForm(data=request.POST)
74         if form.is_valid():
75             receps = sec.CONTACT_ADDRESSES.get(
76                 request.POST["contact_category"], "technical"
77             )
78             send_mail(
79                 request.POST.get("contact_topic"),
80                 f"{request.POST.get('contact_name')} "
81                 + f"({request.POST.get('contact_email')}) wrote: \n"
82                 + request.POST.get("content"),
83                 sec.DEFAULT_FROM_EMAIL,
84                 receps,
85                 fail_silently=False,
86             )
87             return render(
88                 request, "base/contact.html", {"form": ContactForm(), "success": True}
89             )
90         else:
91             return render(
92                 request, "base/contact.html", {"form": form, "success": False}
93             )
94 
95     def get(self, request):
96         return render(
97             request, "base/contact.html", {"form": ContactForm(), "success": False}
98         )
99 
100 
101 def robot(request):
102     return render(request, "base/robots.txt", {}, content_type="text/plain")
103 
104 
105 def handler500(request):
106     response = render(request, "base/500.html", {})
107     response.status_code = 500
108     return response
109 
110 
111 def handler404(request, exception):
112     response = render(request, "base/404.html", {})
113     response.status_code = 404
114     return response
115 
116 
117 def get_json_content(path, json_id=None):
118     """Parse all jsons from given path and return as
119         list or return a single parsed json by id ->
120         The json must have a field called id.
121 
122     Args:
123         path (string): path to directory like 'static/project_pages_content/'
124         json_id (string, optional): ID value that must match the value of json[id].
125             Defaults to None.
126 
127     Returns:
128         list[object]: List of all deserialized json files in path
129         or
130         object: single json python object
131     """
132 
133     if path is not None:
134         all_jsons = []
135         for _json in os.listdir(path=path):
136             with open(os.path.join(path, _json), "r", encoding="utf-8") as json_content:
137                 content = json.load(json_content)
138                 all_jsons.append(content)
139 
140         if json_id is None:
141             return all_jsons
142         else:
143             content_by_id = [
144                 i for i in all_jsons if json_id == i["id"] and "template" != i["id"]
145             ]
146             return content_by_id[0]
147     # TODO: catch the exception if path is none
148     else:
149         return {
150             "error": "Path cant be None. Please provide the path to '/static/project_detail_pages_content/' . You can create a new Project by adding an JSON file like the '/static/project_detail_pages_content/PROJECT_TEMPLATE.json'."  # noqa
151         }
152 
153 
154 class AboutPage(View):
155     # docstring
156     projects_content_static = "project_detail_pages_content"
157     projects_content_path = os.path.join(sec.STATIC_ROOT, projects_content_static)
158 
159     def get(self, request, projects_content_path=projects_content_path):
160         projects = get_json_content(path=projects_content_path)
161 
162         return render(request, "base/about.html", {"projects": projects})
163 
164 
165 class AboutProjectDetail(AboutPage):
166     # docstring
167 
168     def get(self, request, project_id):
169         project = get_json_content(path=self.projects_content_path, json_id=project_id)
170 
171         return render(request, "base/project-detail.html", {"project": project})
172
```
--- 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/base/views.py b/base/views.py
--- a/base/views.py
+++ b/base/views.py
@@ -1,6 +1,7 @@
 import json
 import os
 import re
+from functools import lru_cache
 
 import markdown2
 from django.core.mail import send_mail
@@ -21,11 +22,24 @@
 SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
 
 
-class Welcome(View):
-    def get(self, request):
-        os.path.dirname(os.path.realpath(__file__))
-        version_expr = r"^(?P<major>\d+)\.(?P<minor>\d+)+\.(?P<patch>\d+)$"
-        markdowner = markdown2.Markdown()
+@lru_cache(maxsize=None)
+def read_version_changes():
+    """read version and changes from changelog markdown
+
+    We use cache so it can stay in process memory and we dont have to read files
+    in every request. this only changes on a new release anyway, in which case
+    the process is restarted.
+
+    Returns:
+       dict: {"version": (major, minor, patch), "changes": changes}
+    """
+    os.path.dirname(os.path.realpath(__file__))
+    version_expr = r"^(?P<major>\d+)\.(?P<minor>\d+)+\.(?P<patch>\d+)$"
+    markdowner = markdown2.Markdown()
+    import logging
+
+    logging.error("READING")
+    try:
         with open(os.path.join(SITE_ROOT, "..", "VERSION")) as version_file:
             match = re.match(version_expr, version_file.read())
             major, minor, patch = match.groups()
@@ -39,11 +53,16 @@
             changes = markdowner.convert(
                 "\n".join(line for line in change_file.readlines())
             )
-        return render(
-            request,
-            "base/index.html",
-            {"version": "%s.%s.%s" % (major, minor, patch), "changes": changes},
-        )
+    except Exception:
+        # probably because change_file is missing
+        major, minor, patch, changes = "", "", "", ""
+    return {"version": (major, minor, patch), "changes": changes}
+
+
+class Welcome(View):
+    def get(self, request):
+        context = read_version_changes()
+        return render(request, "base/index.html", context)
 
 
 def get_logs(request):

{"golden_diff": "diff --git a/base/views.py b/base/views.py\n--- a/base/views.py\n+++ b/base/views.py\n@@ -1,6 +1,7 @@\n import json\n import os\n import re\n+from functools import lru_cache\n \n import markdown2\n from django.core.mail import send_mail\n@@ -21,11 +22,24 @@\n SITE_ROOT = os.path.dirname(os.path.realpath(__file__))\n \n \n-class Welcome(View):\n-    def get(self, request):\n-        os.path.dirname(os.path.realpath(__file__))\n-        version_expr = r\"^(?P<major>\\d+)\\.(?P<minor>\\d+)+\\.(?P<patch>\\d+)$\"\n-        markdowner = markdown2.Markdown()\n+@lru_cache(maxsize=None)\n+def read_version_changes():\n+    \"\"\"read version and changes from changelog markdown\n+\n+    We use cache so it can stay in process memory and we dont have to read files\n+    in every request. this only changes on a new release anyway, in which case\n+    the process is restarted.\n+\n+    Returns:\n+       dict: {\"version\": (major, minor, patch), \"changes\": changes}\n+    \"\"\"\n+    os.path.dirname(os.path.realpath(__file__))\n+    version_expr = r\"^(?P<major>\\d+)\\.(?P<minor>\\d+)+\\.(?P<patch>\\d+)$\"\n+    markdowner = markdown2.Markdown()\n+    import logging\n+\n+    logging.error(\"READING\")\n+    try:\n         with open(os.path.join(SITE_ROOT, \"..\", \"VERSION\")) as version_file:\n             match = re.match(version_expr, version_file.read())\n             major, minor, patch = match.groups()\n@@ -39,11 +53,16 @@\n             changes = markdowner.convert(\n                 \"\\n\".join(line for line in change_file.readlines())\n             )\n-        return render(\n-            request,\n-            \"base/index.html\",\n-            {\"version\": \"%s.%s.%s\" % (major, minor, patch), \"changes\": changes},\n-        )\n+    except Exception:\n+        # probably because change_file is missing\n+        major, minor, patch, changes = \"\", \"\", \"\", \"\"\n+    return {\"version\": (major, minor, patch), \"changes\": changes}\n+\n+\n+class Welcome(View):\n+    def get(self, request):\n+        context = read_version_changes()\n+        return render(request, \"base/index.html\", context)\n \n \n def get_logs(request):\n", "issue": "Improve reading of version file in Welcome View\n* use caching because file is read every time user requests main page\r\n* wrap in try-except (missing release notice should not break the main page)\r\n\r\n\r\nFYI: @jh-RLI \n", "before_files": [{"content": "import json\nimport os\nimport re\n\nimport markdown2\nfrom django.core.mail import send_mail\nfrom django.shortcuts import render\nfrom django.views.generic import View\n\ntry:\n    import oeplatform.securitysettings as sec\nexcept Exception:\n    import logging\n\n    logging.error(\"No securitysettings found. Triggerd in base/views.py\")\n\nfrom base.forms import ContactForm\n\n# Create your views here.\n\nSITE_ROOT = os.path.dirname(os.path.realpath(__file__))\n\n\nclass Welcome(View):\n    def get(self, request):\n        os.path.dirname(os.path.realpath(__file__))\n        version_expr = r\"^(?P<major>\\d+)\\.(?P<minor>\\d+)+\\.(?P<patch>\\d+)$\"\n        markdowner = markdown2.Markdown()\n        with open(os.path.join(SITE_ROOT, \"..\", \"VERSION\")) as version_file:\n            match = re.match(version_expr, version_file.read())\n            major, minor, patch = match.groups()\n        with open(\n            os.path.join(\n                SITE_ROOT,\n                \"..\",\n                \"versions/changelogs/%s_%s_%s.md\" % (major, minor, patch),\n            )\n        ) as change_file:\n            changes = markdowner.convert(\n                \"\\n\".join(line for line in change_file.readlines())\n            )\n        return render(\n            request,\n            \"base/index.html\",\n            {\"version\": \"%s.%s.%s\" % (major, minor, patch), \"changes\": changes},\n        )\n\n\ndef get_logs(request):\n    version_expr = r\"^(?P<major>\\d+)_(?P<major>\\d+)+_(?P<major>\\d+)\\.md$\"\n    logs = {}\n    for file in os.listdir(\"../versions/changelogs\"):\n        match = re.match(version_expr, file)\n        markdowner = markdown2.Markdown()\n        if match:\n            major, minor, patch = match.groups()\n            with open(\"versions/changelogs\" + file) as f:\n                logs[(major, minor, patch)] = markdowner.convert(\n                    \"\\n\".join(line for line in f.readlines())\n                )\n    return logs\n\n\ndef redir(request, target):\n    return render(request, \"base/{target}.html\".format(target=target), {})\n\n\nclass ContactView(View):\n    error_css_class = \"error\"\n    required_css_class = \"required\"\n\n    def post(self, request):\n        form = ContactForm(data=request.POST)\n        if form.is_valid():\n            receps = sec.CONTACT_ADDRESSES.get(\n                request.POST[\"contact_category\"], \"technical\"\n            )\n            send_mail(\n                request.POST.get(\"contact_topic\"),\n                f\"{request.POST.get('contact_name')} \"\n                + f\"({request.POST.get('contact_email')}) wrote: \\n\"\n                + request.POST.get(\"content\"),\n                sec.DEFAULT_FROM_EMAIL,\n                receps,\n                fail_silently=False,\n            )\n            return render(\n                request, \"base/contact.html\", {\"form\": ContactForm(), \"success\": True}\n            )\n        else:\n            return render(\n                request, \"base/contact.html\", {\"form\": form, \"success\": False}\n            )\n\n    def get(self, request):\n        return render(\n            request, \"base/contact.html\", {\"form\": ContactForm(), \"success\": False}\n        )\n\n\ndef robot(request):\n    return render(request, \"base/robots.txt\", {}, content_type=\"text/plain\")\n\n\ndef handler500(request):\n    response = render(request, \"base/500.html\", {})\n    response.status_code = 500\n    return response\n\n\ndef handler404(request, exception):\n    response = render(request, \"base/404.html\", {})\n    response.status_code = 404\n    return response\n\n\ndef get_json_content(path, json_id=None):\n    \"\"\"Parse all jsons from given path and return as\n        list or return a single parsed json by id ->\n        The json must have a field called id.\n\n    Args:\n        path (string): path to directory like 'static/project_pages_content/'\n        json_id (string, optional): ID value that must match the value of json[id].\n            Defaults to None.\n\n    Returns:\n        list[object]: List of all deserialized json files in path\n        or\n        object: single json python object\n    \"\"\"\n\n    if path is not None:\n        all_jsons = []\n        for _json in os.listdir(path=path):\n            with open(os.path.join(path, _json), \"r\", encoding=\"utf-8\") as json_content:\n                content = json.load(json_content)\n                all_jsons.append(content)\n\n        if json_id is None:\n            return all_jsons\n        else:\n            content_by_id = [\n                i for i in all_jsons if json_id == i[\"id\"] and \"template\" != i[\"id\"]\n            ]\n            return content_by_id[0]\n    # TODO: catch the exception if path is none\n    else:\n        return {\n            \"error\": \"Path cant be None. Please provide the path to '/static/project_detail_pages_content/' . You can create a new Project by adding an JSON file like the '/static/project_detail_pages_content/PROJECT_TEMPLATE.json'.\"  # noqa\n        }\n\n\nclass AboutPage(View):\n    # docstring\n    projects_content_static = \"project_detail_pages_content\"\n    projects_content_path = os.path.join(sec.STATIC_ROOT, projects_content_static)\n\n    def get(self, request, projects_content_path=projects_content_path):\n        projects = get_json_content(path=projects_content_path)\n\n        return render(request, \"base/about.html\", {\"projects\": projects})\n\n\nclass AboutProjectDetail(AboutPage):\n    # docstring\n\n    def get(self, request, project_id):\n        project = get_json_content(path=self.projects_content_path, json_id=project_id)\n\n        return render(request, \"base/project-detail.html\", {\"project\": project})\n", "path": "base/views.py"}], "after_files": [{"content": "import json\nimport os\nimport re\nfrom functools import lru_cache\n\nimport markdown2\nfrom django.core.mail import send_mail\nfrom django.shortcuts import render\nfrom django.views.generic import View\n\ntry:\n    import oeplatform.securitysettings as sec\nexcept Exception:\n    import logging\n\n    logging.error(\"No securitysettings found. Triggerd in base/views.py\")\n\nfrom base.forms import ContactForm\n\n# Create your views here.\n\nSITE_ROOT = os.path.dirname(os.path.realpath(__file__))\n\n\n@lru_cache(maxsize=None)\ndef read_version_changes():\n    \"\"\"read version and changes from changelog markdown\n\n    We use cache so it can stay in process memory and we dont have to read files\n    in every request. this only changes on a new release anyway, in which case\n    the process is restarted.\n\n    Returns:\n       dict: {\"version\": (major, minor, patch), \"changes\": changes}\n    \"\"\"\n    os.path.dirname(os.path.realpath(__file__))\n    version_expr = r\"^(?P<major>\\d+)\\.(?P<minor>\\d+)+\\.(?P<patch>\\d+)$\"\n    markdowner = markdown2.Markdown()\n    import logging\n\n    logging.error(\"READING\")\n    try:\n        with open(os.path.join(SITE_ROOT, \"..\", \"VERSION\")) as version_file:\n            match = re.match(version_expr, version_file.read())\n            major, minor, patch = match.groups()\n        with open(\n            os.path.join(\n                SITE_ROOT,\n                \"..\",\n                \"versions/changelogs/%s_%s_%s.md\" % (major, minor, patch),\n            )\n        ) as change_file:\n            changes = markdowner.convert(\n                \"\\n\".join(line for line in change_file.readlines())\n            )\n    except Exception:\n        # probably because change_file is missing\n        major, minor, patch, changes = \"\", \"\", \"\", \"\"\n    return {\"version\": (major, minor, patch), \"changes\": changes}\n\n\nclass Welcome(View):\n    def get(self, request):\n        context = read_version_changes()\n        return render(request, \"base/index.html\", context)\n\n\ndef get_logs(request):\n    version_expr = r\"^(?P<major>\\d+)_(?P<major>\\d+)+_(?P<major>\\d+)\\.md$\"\n    logs = {}\n    for file in os.listdir(\"../versions/changelogs\"):\n        match = re.match(version_expr, file)\n        markdowner = markdown2.Markdown()\n        if match:\n            major, minor, patch = match.groups()\n            with open(\"versions/changelogs\" + file) as f:\n                logs[(major, minor, patch)] = markdowner.convert(\n                    \"\\n\".join(line for line in f.readlines())\n                )\n    return logs\n\n\ndef redir(request, target):\n    return render(request, \"base/{target}.html\".format(target=target), {})\n\n\nclass ContactView(View):\n    error_css_class = \"error\"\n    required_css_class = \"required\"\n\n    def post(self, request):\n        form = ContactForm(data=request.POST)\n        if form.is_valid():\n            receps = sec.CONTACT_ADDRESSES.get(\n                request.POST[\"contact_category\"], \"technical\"\n            )\n            send_mail(\n                request.POST.get(\"contact_topic\"),\n                f\"{request.POST.get('contact_name')} \"\n                + f\"({request.POST.get('contact_email')}) wrote: \\n\"\n                + request.POST.get(\"content\"),\n                sec.DEFAULT_FROM_EMAIL,\n                receps,\n                fail_silently=False,\n            )\n            return render(\n                request, \"base/contact.html\", {\"form\": ContactForm(), \"success\": True}\n            )\n        else:\n            return render(\n                request, \"base/contact.html\", {\"form\": form, \"success\": False}\n            )\n\n    def get(self, request):\n        return render(\n            request, \"base/contact.html\", {\"form\": ContactForm(), \"success\": False}\n        )\n\n\ndef robot(request):\n    return render(request, \"base/robots.txt\", {}, content_type=\"text/plain\")\n\n\ndef handler500(request):\n    response = render(request, \"base/500.html\", {})\n    response.status_code = 500\n    return response\n\n\ndef handler404(request, exception):\n    response = render(request, \"base/404.html\", {})\n    response.status_code = 404\n    return response\n\n\ndef get_json_content(path, json_id=None):\n    \"\"\"Parse all jsons from given path and return as\n        list or return a single parsed json by id ->\n        The json must have a field called id.\n\n    Args:\n        path (string): path to directory like 'static/project_pages_content/'\n        json_id (string, optional): ID value that must match the value of json[id].\n            Defaults to None.\n\n    Returns:\n        list[object]: List of all deserialized json files in path\n        or\n        object: single json python object\n    \"\"\"\n\n    if path is not None:\n        all_jsons = []\n        for _json in os.listdir(path=path):\n            with open(os.path.join(path, _json), \"r\", encoding=\"utf-8\") as json_content:\n                content = json.load(json_content)\n                all_jsons.append(content)\n\n        if json_id is None:\n            return all_jsons\n        else:\n            content_by_id = [\n                i for i in all_jsons if json_id == i[\"id\"] and \"template\" != i[\"id\"]\n            ]\n            return content_by_id[0]\n    # TODO: catch the exception if path is none\n    else:\n        return {\n            \"error\": \"Path cant be None. Please provide the path to '/static/project_detail_pages_content/' . You can create a new Project by adding an JSON file like the '/static/project_detail_pages_content/PROJECT_TEMPLATE.json'.\"  # noqa\n        }\n\n\nclass AboutPage(View):\n    # docstring\n    projects_content_static = \"project_detail_pages_content\"\n    projects_content_path = os.path.join(sec.STATIC_ROOT, projects_content_static)\n\n    def get(self, request, projects_content_path=projects_content_path):\n        projects = get_json_content(path=projects_content_path)\n\n        return render(request, \"base/about.html\", {\"projects\": projects})\n\n\nclass AboutProjectDetail(AboutPage):\n    # docstring\n\n    def get(self, request, project_id):\n        project = get_json_content(path=self.projects_content_path, json_id=project_id)\n\n        return render(request, \"base/project-detail.html\", {\"project\": project})\n", "path": "base/views.py"}]}