We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
update perseus to use new build config scheme

### Observed behavior

follow-up from #5864, need to update perseus to use new buildconfig.  Currently builds but does not run.


### Errors and logs

Currently getting:

```
ERROR    Internal Server Error: /en/user/
Traceback (most recent call last):
  File "/Users/d/Projects/le/kolibri/kolibri/core/webpack/hooks.py", line 111, in _stats_file_content
    with io.open(self._stats_file, mode="r", encoding="utf-8") as f:
FileNotFoundError: [Errno 2] No such file or directory: '/Users/d/Projects/le/kolibri/.venv/lib/python3.7/site-packages/kolibri_exercise_perseus_plugin/build/_stats.json'
```



### Context

current 0.13.0 develop branch


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `packages/kolibri-tools/lib/webpack_json.py`
Content:
```
1 import argparse
2 import importlib
3 import json
4 import logging
5 import os
6 import sys
7 import tempfile
8 
9 from pkg_resources import DistributionNotFound
10 from pkg_resources import get_distribution
11 from pkg_resources import resource_exists
12 from pkg_resources import resource_filename
13 from pkg_resources import resource_isdir
14 from pkg_resources import resource_listdir
15 
16 logger = logging.getLogger("webpack_json")
17 logger.setLevel(level=logging.INFO)
18 
19 BUILD_CONFIG = "buildConfig.js"
20 
21 
22 def load_plugins_from_file(file_path):
23     try:
24         import requests
25     except ImportError:
26         requests = None
27     # We have been passed a URL, not a local file path
28     if file_path.startswith("http"):
29         if requests is None:
30             raise ImportError("Requests is required to import plugins from urls")
31         print(
32             "Downloading plugins manifest from {file_path}".format(file_path=file_path)
33         )
34         _, path = tempfile.mkstemp(suffix=".txt", text=True)
35         with open(path, "w") as f:
36             r = requests.get(file_path)
37             f.write(r.content)
38         file_path = path
39     with open(file_path, "r") as f:
40         return [plugin.strip() for plugin in f.readlines() if plugin.strip()]
41 
42 
43 def expand_glob(build_item):
44     plugins = []
45     # Do a very simple check here, only deal with a single * at the end of something!
46     if (
47         len([item for item in build_item.split(".") if item == "*"]) > 1
48         or build_item.endswith("**")
49         or build_item == "*"
50         or not build_item.endswith("*")
51     ):
52         logging.error("Too many * paths, only use one per module spec")
53         return plugins
54     parent_module_path = ".".join(
55         [item for item in build_item.split(".") if item and item != "*"]
56     )
57     try:
58         for file in resource_listdir(parent_module_path, "."):
59             if resource_isdir(parent_module_path, file):
60                 try:
61                     child_module_path = parent_module_path + "." + file
62                     plugin = plugin_data(child_module_path)
63                     if plugin is not None:
64                         plugins.append(plugin)
65                 except ImportError:
66                     continue
67     except OSError:
68         pass
69     return plugins
70 
71 
72 def plugin_data(module_path):
73     try:
74         if resource_exists(module_path, BUILD_CONFIG):
75             plugin_path = os.path.dirname(resource_filename(module_path, BUILD_CONFIG))
76             try:
77                 version = get_distribution(module_path).version
78             except (DistributionNotFound, AttributeError):
79                 try:
80                     module = importlib.import_module(module_path)
81                     version = module.__version__
82                 except (ImportError, AttributeError):
83                     import kolibri
84 
85                     version = kolibri.__version__
86             if module_path.startswith("kolibri."):
87                 import kolibri
88 
89                 locale_data_folder = os.path.join(
90                     os.path.dirname(kolibri.__file__), "locale", "en", "LC_MESSAGES"
91                 )
92             # Is an external plugin, do otherwise!
93             else:
94                 locale_data_folder = os.path.join(
95                     plugin_path, "locale", "en", "LC_MESSAGES"
96                 )
97             return {
98                 "locale_data_folder": locale_data_folder,
99                 "plugin_path": plugin_path,
100                 "version": version,
101             }
102     # Python 3.{4,5,6} raises a NotImplementedError for an empty directory
103     # Python 3.7 raises a TypeError for an empty directory
104     except (NotImplementedError, TypeError):
105         pass
106     raise ImportError("No frontend build assets")
107 
108 
109 def initialize_plugins(build_list):
110     plugins = []
111     for build_item in build_list:
112         if "*" in build_item:
113             plugins += expand_glob(build_item)
114         elif build_item:
115             # No '*' in the module path, so just add it naively
116             plugin = plugin_data(build_item)
117             if plugin is not None:
118                 plugins.append(plugin)
119     return plugins
120 
121 
122 def main():
123     parser = argparse.ArgumentParser()
124 
125     parser.add_argument(
126         "--plugin_file",
127         help="the filepath to which you'd like to run plugins from",
128         type=str,
129         default=None,
130     )
131     parser.add_argument(
132         "--plugins",
133         help="provide a space separated list of plugins you'd like to run",
134         type=str,
135         nargs="*",
136         default=None,
137     )
138     parser.add_argument(
139         "--plugin_path",
140         help="provide a path to add to the Python path to enable import of the plugins",
141         type=str,
142         default=os.getcwd(),
143     )
144     parser.add_argument(
145         "-o", "--output_file", type=str, default=None, dest="output_file"
146     )
147     parser.add_argument("-v", "--verbose", default=False, action="store_true")
148     args = parser.parse_args()
149     build_list = []
150 
151     if args.verbose:
152         logger.setLevel(logging.DEBUG)
153 
154     plugin_path = os.path.realpath(args.plugin_path)
155 
156     # Add our plugin_path to the path
157     sys.path.append(plugin_path)
158 
159     # Put environment variable setting first to allow customized builds within buildkite through env vars
160     if "BUILD_TIME_PLUGINS" in os.environ and os.environ["BUILD_TIME_PLUGINS"]:
161         build_list = load_plugins_from_file(os.environ["BUILD_TIME_PLUGINS"])
162     elif args.plugin_file:
163         build_list = load_plugins_from_file(args.plugin_file)
164     elif args.plugins:
165         build_list = args.plugins
166 
167     logger.info("Gathering relevant modules from {}".format(build_list))
168 
169     result = initialize_plugins(build_list)
170 
171     if args.output_file:
172         logger.info("Writing webpack_json output to {}".format(args.output_file))
173         with open(args.output_file, "w") as f:
174             json.dump(result, f)
175     else:
176         logger.info("No output file argument; writing webpack_json output to stdout.")
177         logger.info(json.dumps(result))
178 
179     # Remove the plugin_path from the path to clean up
180     sys.path.remove(plugin_path)
181 
182 
183 if __name__ == "__main__":
184     main()
185
```
--- 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/packages/kolibri-tools/lib/webpack_json.py b/packages/kolibri-tools/lib/webpack_json.py
--- a/packages/kolibri-tools/lib/webpack_json.py
+++ b/packages/kolibri-tools/lib/webpack_json.py
@@ -15,6 +15,9 @@
 
 logger = logging.getLogger("webpack_json")
 logger.setLevel(level=logging.INFO)
+handler = logging.StreamHandler()
+handler.setLevel(logging.INFO)
+logger.addHandler(handler)
 
 BUILD_CONFIG = "buildConfig.js"

{"golden_diff": "diff --git a/packages/kolibri-tools/lib/webpack_json.py b/packages/kolibri-tools/lib/webpack_json.py\n--- a/packages/kolibri-tools/lib/webpack_json.py\n+++ b/packages/kolibri-tools/lib/webpack_json.py\n@@ -15,6 +15,9 @@\n \n logger = logging.getLogger(\"webpack_json\")\n logger.setLevel(level=logging.INFO)\n+handler = logging.StreamHandler()\n+handler.setLevel(logging.INFO)\n+logger.addHandler(handler)\n \n BUILD_CONFIG = \"buildConfig.js\"\n", "issue": "update perseus to use new build config scheme\n\r\n### Observed behavior\r\n\r\nfollow-up from #5864, need to update perseus to use new buildconfig.  Currently builds but does not run.\r\n\r\n\r\n### Errors and logs\r\n\r\nCurrently getting:\r\n\r\n```\r\nERROR    Internal Server Error: /en/user/\r\nTraceback (most recent call last):\r\n  File \"/Users/d/Projects/le/kolibri/kolibri/core/webpack/hooks.py\", line 111, in _stats_file_content\r\n    with io.open(self._stats_file, mode=\"r\", encoding=\"utf-8\") as f:\r\nFileNotFoundError: [Errno 2] No such file or directory: '/Users/d/Projects/le/kolibri/.venv/lib/python3.7/site-packages/kolibri_exercise_perseus_plugin/build/_stats.json'\r\n```\r\n\r\n\r\n\r\n### Context\r\n\r\ncurrent 0.13.0 develop branch\r\n\n", "before_files": [{"content": "import argparse\nimport importlib\nimport json\nimport logging\nimport os\nimport sys\nimport tempfile\n\nfrom pkg_resources import DistributionNotFound\nfrom pkg_resources import get_distribution\nfrom pkg_resources import resource_exists\nfrom pkg_resources import resource_filename\nfrom pkg_resources import resource_isdir\nfrom pkg_resources import resource_listdir\n\nlogger = logging.getLogger(\"webpack_json\")\nlogger.setLevel(level=logging.INFO)\n\nBUILD_CONFIG = \"buildConfig.js\"\n\n\ndef load_plugins_from_file(file_path):\n    try:\n        import requests\n    except ImportError:\n        requests = None\n    # We have been passed a URL, not a local file path\n    if file_path.startswith(\"http\"):\n        if requests is None:\n            raise ImportError(\"Requests is required to import plugins from urls\")\n        print(\n            \"Downloading plugins manifest from {file_path}\".format(file_path=file_path)\n        )\n        _, path = tempfile.mkstemp(suffix=\".txt\", text=True)\n        with open(path, \"w\") as f:\n            r = requests.get(file_path)\n            f.write(r.content)\n        file_path = path\n    with open(file_path, \"r\") as f:\n        return [plugin.strip() for plugin in f.readlines() if plugin.strip()]\n\n\ndef expand_glob(build_item):\n    plugins = []\n    # Do a very simple check here, only deal with a single * at the end of something!\n    if (\n        len([item for item in build_item.split(\".\") if item == \"*\"]) > 1\n        or build_item.endswith(\"**\")\n        or build_item == \"*\"\n        or not build_item.endswith(\"*\")\n    ):\n        logging.error(\"Too many * paths, only use one per module spec\")\n        return plugins\n    parent_module_path = \".\".join(\n        [item for item in build_item.split(\".\") if item and item != \"*\"]\n    )\n    try:\n        for file in resource_listdir(parent_module_path, \".\"):\n            if resource_isdir(parent_module_path, file):\n                try:\n                    child_module_path = parent_module_path + \".\" + file\n                    plugin = plugin_data(child_module_path)\n                    if plugin is not None:\n                        plugins.append(plugin)\n                except ImportError:\n                    continue\n    except OSError:\n        pass\n    return plugins\n\n\ndef plugin_data(module_path):\n    try:\n        if resource_exists(module_path, BUILD_CONFIG):\n            plugin_path = os.path.dirname(resource_filename(module_path, BUILD_CONFIG))\n            try:\n                version = get_distribution(module_path).version\n            except (DistributionNotFound, AttributeError):\n                try:\n                    module = importlib.import_module(module_path)\n                    version = module.__version__\n                except (ImportError, AttributeError):\n                    import kolibri\n\n                    version = kolibri.__version__\n            if module_path.startswith(\"kolibri.\"):\n                import kolibri\n\n                locale_data_folder = os.path.join(\n                    os.path.dirname(kolibri.__file__), \"locale\", \"en\", \"LC_MESSAGES\"\n                )\n            # Is an external plugin, do otherwise!\n            else:\n                locale_data_folder = os.path.join(\n                    plugin_path, \"locale\", \"en\", \"LC_MESSAGES\"\n                )\n            return {\n                \"locale_data_folder\": locale_data_folder,\n                \"plugin_path\": plugin_path,\n                \"version\": version,\n            }\n    # Python 3.{4,5,6} raises a NotImplementedError for an empty directory\n    # Python 3.7 raises a TypeError for an empty directory\n    except (NotImplementedError, TypeError):\n        pass\n    raise ImportError(\"No frontend build assets\")\n\n\ndef initialize_plugins(build_list):\n    plugins = []\n    for build_item in build_list:\n        if \"*\" in build_item:\n            plugins += expand_glob(build_item)\n        elif build_item:\n            # No '*' in the module path, so just add it naively\n            plugin = plugin_data(build_item)\n            if plugin is not None:\n                plugins.append(plugin)\n    return plugins\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n\n    parser.add_argument(\n        \"--plugin_file\",\n        help=\"the filepath to which you'd like to run plugins from\",\n        type=str,\n        default=None,\n    )\n    parser.add_argument(\n        \"--plugins\",\n        help=\"provide a space separated list of plugins you'd like to run\",\n        type=str,\n        nargs=\"*\",\n        default=None,\n    )\n    parser.add_argument(\n        \"--plugin_path\",\n        help=\"provide a path to add to the Python path to enable import of the plugins\",\n        type=str,\n        default=os.getcwd(),\n    )\n    parser.add_argument(\n        \"-o\", \"--output_file\", type=str, default=None, dest=\"output_file\"\n    )\n    parser.add_argument(\"-v\", \"--verbose\", default=False, action=\"store_true\")\n    args = parser.parse_args()\n    build_list = []\n\n    if args.verbose:\n        logger.setLevel(logging.DEBUG)\n\n    plugin_path = os.path.realpath(args.plugin_path)\n\n    # Add our plugin_path to the path\n    sys.path.append(plugin_path)\n\n    # Put environment variable setting first to allow customized builds within buildkite through env vars\n    if \"BUILD_TIME_PLUGINS\" in os.environ and os.environ[\"BUILD_TIME_PLUGINS\"]:\n        build_list = load_plugins_from_file(os.environ[\"BUILD_TIME_PLUGINS\"])\n    elif args.plugin_file:\n        build_list = load_plugins_from_file(args.plugin_file)\n    elif args.plugins:\n        build_list = args.plugins\n\n    logger.info(\"Gathering relevant modules from {}\".format(build_list))\n\n    result = initialize_plugins(build_list)\n\n    if args.output_file:\n        logger.info(\"Writing webpack_json output to {}\".format(args.output_file))\n        with open(args.output_file, \"w\") as f:\n            json.dump(result, f)\n    else:\n        logger.info(\"No output file argument; writing webpack_json output to stdout.\")\n        logger.info(json.dumps(result))\n\n    # Remove the plugin_path from the path to clean up\n    sys.path.remove(plugin_path)\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "packages/kolibri-tools/lib/webpack_json.py"}], "after_files": [{"content": "import argparse\nimport importlib\nimport json\nimport logging\nimport os\nimport sys\nimport tempfile\n\nfrom pkg_resources import DistributionNotFound\nfrom pkg_resources import get_distribution\nfrom pkg_resources import resource_exists\nfrom pkg_resources import resource_filename\nfrom pkg_resources import resource_isdir\nfrom pkg_resources import resource_listdir\n\nlogger = logging.getLogger(\"webpack_json\")\nlogger.setLevel(level=logging.INFO)\nhandler = logging.StreamHandler()\nhandler.setLevel(logging.INFO)\nlogger.addHandler(handler)\n\nBUILD_CONFIG = \"buildConfig.js\"\n\n\ndef load_plugins_from_file(file_path):\n    try:\n        import requests\n    except ImportError:\n        requests = None\n    # We have been passed a URL, not a local file path\n    if file_path.startswith(\"http\"):\n        if requests is None:\n            raise ImportError(\"Requests is required to import plugins from urls\")\n        print(\n            \"Downloading plugins manifest from {file_path}\".format(file_path=file_path)\n        )\n        _, path = tempfile.mkstemp(suffix=\".txt\", text=True)\n        with open(path, \"w\") as f:\n            r = requests.get(file_path)\n            f.write(r.content)\n        file_path = path\n    with open(file_path, \"r\") as f:\n        return [plugin.strip() for plugin in f.readlines() if plugin.strip()]\n\n\ndef expand_glob(build_item):\n    plugins = []\n    # Do a very simple check here, only deal with a single * at the end of something!\n    if (\n        len([item for item in build_item.split(\".\") if item == \"*\"]) > 1\n        or build_item.endswith(\"**\")\n        or build_item == \"*\"\n        or not build_item.endswith(\"*\")\n    ):\n        logging.error(\"Too many * paths, only use one per module spec\")\n        return plugins\n    parent_module_path = \".\".join(\n        [item for item in build_item.split(\".\") if item and item != \"*\"]\n    )\n    try:\n        for file in resource_listdir(parent_module_path, \".\"):\n            if resource_isdir(parent_module_path, file):\n                try:\n                    child_module_path = parent_module_path + \".\" + file\n                    plugin = plugin_data(child_module_path)\n                    if plugin is not None:\n                        plugins.append(plugin)\n                except ImportError:\n                    continue\n    except OSError:\n        pass\n    return plugins\n\n\ndef plugin_data(module_path):\n    try:\n        if resource_exists(module_path, BUILD_CONFIG):\n            plugin_path = os.path.dirname(resource_filename(module_path, BUILD_CONFIG))\n            try:\n                version = get_distribution(module_path).version\n            except (DistributionNotFound, AttributeError):\n                try:\n                    module = importlib.import_module(module_path)\n                    version = module.__version__\n                except (ImportError, AttributeError):\n                    import kolibri\n\n                    version = kolibri.__version__\n            if module_path.startswith(\"kolibri.\"):\n                import kolibri\n\n                locale_data_folder = os.path.join(\n                    os.path.dirname(kolibri.__file__), \"locale\", \"en\", \"LC_MESSAGES\"\n                )\n            # Is an external plugin, do otherwise!\n            else:\n                locale_data_folder = os.path.join(\n                    plugin_path, \"locale\", \"en\", \"LC_MESSAGES\"\n                )\n            return {\n                \"locale_data_folder\": locale_data_folder,\n                \"plugin_path\": plugin_path,\n                \"version\": version,\n            }\n    # Python 3.{4,5,6} raises a NotImplementedError for an empty directory\n    # Python 3.7 raises a TypeError for an empty directory\n    except (NotImplementedError, TypeError):\n        pass\n    raise ImportError(\"No frontend build assets\")\n\n\ndef initialize_plugins(build_list):\n    plugins = []\n    for build_item in build_list:\n        if \"*\" in build_item:\n            plugins += expand_glob(build_item)\n        elif build_item:\n            # No '*' in the module path, so just add it naively\n            plugin = plugin_data(build_item)\n            if plugin is not None:\n                plugins.append(plugin)\n    return plugins\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n\n    parser.add_argument(\n        \"--plugin_file\",\n        help=\"the filepath to which you'd like to run plugins from\",\n        type=str,\n        default=None,\n    )\n    parser.add_argument(\n        \"--plugins\",\n        help=\"provide a space separated list of plugins you'd like to run\",\n        type=str,\n        nargs=\"*\",\n        default=None,\n    )\n    parser.add_argument(\n        \"--plugin_path\",\n        help=\"provide a path to add to the Python path to enable import of the plugins\",\n        type=str,\n        default=os.getcwd(),\n    )\n    parser.add_argument(\n        \"-o\", \"--output_file\", type=str, default=None, dest=\"output_file\"\n    )\n    parser.add_argument(\"-v\", \"--verbose\", default=False, action=\"store_true\")\n    args = parser.parse_args()\n    build_list = []\n\n    if args.verbose:\n        logger.setLevel(logging.DEBUG)\n\n    plugin_path = os.path.realpath(args.plugin_path)\n\n    # Add our plugin_path to the path\n    sys.path.append(plugin_path)\n\n    # Put environment variable setting first to allow customized builds within buildkite through env vars\n    if \"BUILD_TIME_PLUGINS\" in os.environ and os.environ[\"BUILD_TIME_PLUGINS\"]:\n        build_list = load_plugins_from_file(os.environ[\"BUILD_TIME_PLUGINS\"])\n    elif args.plugin_file:\n        build_list = load_plugins_from_file(args.plugin_file)\n    elif args.plugins:\n        build_list = args.plugins\n\n    logger.info(\"Gathering relevant modules from {}\".format(build_list))\n\n    result = initialize_plugins(build_list)\n\n    if args.output_file:\n        logger.info(\"Writing webpack_json output to {}\".format(args.output_file))\n        with open(args.output_file, \"w\") as f:\n            json.dump(result, f)\n    else:\n        logger.info(\"No output file argument; writing webpack_json output to stdout.\")\n        logger.info(json.dumps(result))\n\n    # Remove the plugin_path from the path to clean up\n    sys.path.remove(plugin_path)\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "packages/kolibri-tools/lib/webpack_json.py"}]}