prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Enable ePUB plugin to run by default
  
  ### Observed behavior
  
  ePUB plugin is not enabled by default, and it prevents from importing & viewing ePUB files, until the command `kolibri plugin kolibri.plugins.document_epub_render enable` is run.
  
  ### User-facing consequences
  Inability to view and import ePUB files.
  
  
  ### Context
  dev environment, tried on `develop` and `0.11.a7` branches
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `kolibri/utils/conf.py`
  Content:
  ```
  1 """
  2 Kolibri configuration data
  3 ==========================
  4 
  5 .. warning::
  6     Do not load any django.conf.settings stuff here. This configuration data
  7     precedes loading of settings, it is not part of the settings stack.
  8 
  9 TODO: We need to figure out our conf API. Do we store in ini/json/yaml?
  10 
  11  * How do we retrieve config data?
  12  * When should configuration files be loaded and written?
  13 
  14 This module should be easier to document, for instance by having VARIABLES
  15 instead of a dict.
  16 
  17 """
  18 from __future__ import absolute_import
  19 from __future__ import print_function
  20 from __future__ import unicode_literals
  21 
  22 import json
  23 import logging
  24 import os
  25 
  26 from .compat import module_exists
  27 from .options import read_options_file
  28 
  29 logger = logging.getLogger(__name__)
  30 
  31 # use default OS encoding
  32 with open(os.path.join(os.path.dirname(__file__), 'KOLIBRI_CORE_JS_NAME')) as f:
  33     KOLIBRI_CORE_JS_NAME = f.read().strip()
  34 
  35 #: Absolute path of the main user data directory.
  36 #: Will be created automatically if it doesn't exist.
  37 KOLIBRI_HOME = os.path.abspath(os.path.expanduser(os.environ["KOLIBRI_HOME"]))
  38 
  39 # Creating KOLIBRI_HOME atm. has to happen here as for instance utils.cli is not
  40 # called through py.test. This file is the first basic entry point of
  41 # Kolibri, although utils.cli may or may not precede it.
  42 if not os.path.exists(KOLIBRI_HOME):
  43     parent = os.path.dirname(KOLIBRI_HOME)
  44     if not os.path.exists(parent):
  45         raise RuntimeError("The parent of your KOLIBRI_HOME does not exist: {}".format(parent))
  46     os.mkdir(KOLIBRI_HOME)
  47 
  48 #: Set defaults before updating the dict
  49 config = {}
  50 
  51 try:
  52     # The default list for this is populated from build_tools/default_plugins.txt
  53     # in the root of the Kolibri repository. The default list is identical to the list below,
  54     # except that the style_guide plugin is not enabled in production builds.
  55     # Caveat: this list may have been changed at build time to specify a different list of plugins.
  56     from .build_config.default_plugins import plugins
  57     DEFAULT_PLUGINS = plugins
  58 except ImportError:
  59     DEFAULT_PLUGINS = [
  60         "kolibri.plugins.facility_management",
  61         "kolibri.plugins.device_management",
  62         "kolibri.plugins.learn",
  63         "kolibri.plugins.document_pdf_render",
  64         "kolibri.plugins.html5_app_renderer",
  65         "kolibri.plugins.media_player",
  66         "kolibri.plugins.setup_wizard",
  67         "kolibri.plugins.coach",
  68         "kolibri.plugins.user",
  69         "kolibri_exercise_perseus_plugin",
  70         "kolibri.plugins.style_guide",
  71     ]
  72 
  73 #: Everything in this list is added to django.conf.settings.INSTALLED_APPS
  74 config['INSTALLED_APPS'] = DEFAULT_PLUGINS
  75 
  76 #: Well-known plugin names that are automatically searched for and enabled on
  77 #: first-run.
  78 config['AUTO_SEARCH_PLUGINS'] = []
  79 
  80 #: If a config file does not exist, we assume it's the first run
  81 config['FIRST_RUN'] = True
  82 
  83 conf_file = os.path.join(KOLIBRI_HOME, "kolibri_settings.json")
  84 
  85 
  86 def update(new_values):
  87     """
  88     Updates current configuration with ``new_values``. Does not save to file.
  89     """
  90     config.update(new_values)
  91 
  92 
  93 def save(first_run=False):
  94     """Saves the current state of the configuration"""
  95     config['FIRST_RUN'] = first_run
  96     # use default OS encoding
  97     with open(conf_file, 'w') as kolibri_conf_file:
  98         json.dump(config, kolibri_conf_file, indent=2, sort_keys=True)
  99 
  100 
  101 if not os.path.isfile(conf_file):
  102     logger.info("Initialize kolibri_settings.json..")
  103     save(True)
  104 else:
  105     # Open up the config file and overwrite defaults
  106     # use default OS encoding
  107     with open(conf_file, 'r') as kolibri_conf_file:
  108         config.update(json.load(kolibri_conf_file))
  109 
  110 
  111 def autoremove_unavailable_plugins():
  112     """
  113     Sanitize INSTALLED_APPS - something that should be done separately for all
  114     build in plugins, but we should not auto-remove plugins that are actually
  115     configured by the user or some other kind of hard dependency that should
  116     make execution stop if not loadable.
  117     """
  118     global config
  119     changed = False
  120     # Iterate over a copy of the list so that it is not modified during the loop
  121     for module_path in config['INSTALLED_APPS'][:]:
  122         if not module_exists(module_path):
  123             config['INSTALLED_APPS'].remove(module_path)
  124             logger.error(
  125                 (
  126                     "Plugin {mod} not found and disabled. To re-enable it, run:\n"
  127                     "   $ kolibri plugin {mod} enable"
  128                 ).format(mod=module_path)
  129             )
  130             changed = True
  131     if changed:
  132         save()
  133 
  134 
  135 def enable_default_plugins():
  136     """
  137     Enable new plugins that have been added between versions
  138     This will have the undesired side effect of reactivating
  139     default plugins that have been explicitly disabled by a user.
  140     However, until we add disabled plugins to a blacklist, this is
  141     unavoidable.
  142     """
  143     global config
  144     changed = False
  145     for module_path in DEFAULT_PLUGINS:
  146         if module_path not in config['INSTALLED_APPS']:
  147             config['INSTALLED_APPS'].append(module_path)
  148             logger.warning(
  149                 (
  150                     "Default plugin {mod} not found in configuration. To re-disable it, run:\n"
  151                     "   $ kolibri plugin {mod} disable"
  152                 ).format(mod=module_path)
  153             )
  154             changed = True
  155 
  156     if changed:
  157         save()
  158 
  159 
  160 # read the config file options in here so they can be accessed from a standard location
  161 OPTIONS = read_options_file(KOLIBRI_HOME)
  162
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/kolibri/utils/conf.py b/kolibri/utils/conf.py
  --- a/kolibri/utils/conf.py
  +++ b/kolibri/utils/conf.py
  @@ -68,6 +68,7 @@
           "kolibri.plugins.user",
           "kolibri_exercise_perseus_plugin",
           "kolibri.plugins.style_guide",
  +        "kolibri.plugins.document_epub_render",
       ]
   
   #: Everything in this list is added to django.conf.settings.INSTALLED_APPS
  
verification_info: {"golden_diff": "diff --git a/kolibri/utils/conf.py b/kolibri/utils/conf.py\n--- a/kolibri/utils/conf.py\n+++ b/kolibri/utils/conf.py\n@@ -68,6 +68,7 @@\n         \"kolibri.plugins.user\",\n         \"kolibri_exercise_perseus_plugin\",\n         \"kolibri.plugins.style_guide\",\n+        \"kolibri.plugins.document_epub_render\",\n     ]\n \n #: Everything in this list is added to django.conf.settings.INSTALLED_APPS\n", "issue": "Enable ePUB plugin to run by default\n\r\n### Observed behavior\r\n\r\nePUB plugin is not enabled by default, and it prevents from importing & viewing ePUB files, until the command `kolibri plugin kolibri.plugins.document_epub_render enable` is run.\r\n\r\n### User-facing consequences\r\nInability to view and import ePUB files.\r\n\r\n\r\n### Context\r\ndev environment, tried on `develop` and `0.11.a7` branches\r\n\n", "before_files": [{"content": "\"\"\"\nKolibri configuration data\n==========================\n\n.. warning::\n    Do not load any django.conf.settings stuff here. This configuration data\n    precedes loading of settings, it is not part of the settings stack.\n\nTODO: We need to figure out our conf API. Do we store in ini/json/yaml?\n\n * How do we retrieve config data?\n * When should configuration files be loaded and written?\n\nThis module should be easier to document, for instance by having VARIABLES\ninstead of a dict.\n\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport json\nimport logging\nimport os\n\nfrom .compat import module_exists\nfrom .options import read_options_file\n\nlogger = logging.getLogger(__name__)\n\n# use default OS encoding\nwith open(os.path.join(os.path.dirname(__file__), 'KOLIBRI_CORE_JS_NAME')) as f:\n    KOLIBRI_CORE_JS_NAME = f.read().strip()\n\n#: Absolute path of the main user data directory.\n#: Will be created automatically if it doesn't exist.\nKOLIBRI_HOME = os.path.abspath(os.path.expanduser(os.environ[\"KOLIBRI_HOME\"]))\n\n# Creating KOLIBRI_HOME atm. has to happen here as for instance utils.cli is not\n# called through py.test. This file is the first basic entry point of\n# Kolibri, although utils.cli may or may not precede it.\nif not os.path.exists(KOLIBRI_HOME):\n    parent = os.path.dirname(KOLIBRI_HOME)\n    if not os.path.exists(parent):\n        raise RuntimeError(\"The parent of your KOLIBRI_HOME does not exist: {}\".format(parent))\n    os.mkdir(KOLIBRI_HOME)\n\n#: Set defaults before updating the dict\nconfig = {}\n\ntry:\n    # The default list for this is populated from build_tools/default_plugins.txt\n    # in the root of the Kolibri repository. The default list is identical to the list below,\n    # except that the style_guide plugin is not enabled in production builds.\n    # Caveat: this list may have been changed at build time to specify a different list of plugins.\n    from .build_config.default_plugins import plugins\n    DEFAULT_PLUGINS = plugins\nexcept ImportError:\n    DEFAULT_PLUGINS = [\n        \"kolibri.plugins.facility_management\",\n        \"kolibri.plugins.device_management\",\n        \"kolibri.plugins.learn\",\n        \"kolibri.plugins.document_pdf_render\",\n        \"kolibri.plugins.html5_app_renderer\",\n        \"kolibri.plugins.media_player\",\n        \"kolibri.plugins.setup_wizard\",\n        \"kolibri.plugins.coach\",\n        \"kolibri.plugins.user\",\n        \"kolibri_exercise_perseus_plugin\",\n        \"kolibri.plugins.style_guide\",\n    ]\n\n#: Everything in this list is added to django.conf.settings.INSTALLED_APPS\nconfig['INSTALLED_APPS'] = DEFAULT_PLUGINS\n\n#: Well-known plugin names that are automatically searched for and enabled on\n#: first-run.\nconfig['AUTO_SEARCH_PLUGINS'] = []\n\n#: If a config file does not exist, we assume it's the first run\nconfig['FIRST_RUN'] = True\n\nconf_file = os.path.join(KOLIBRI_HOME, \"kolibri_settings.json\")\n\n\ndef update(new_values):\n    \"\"\"\n    Updates current configuration with ``new_values``. Does not save to file.\n    \"\"\"\n    config.update(new_values)\n\n\ndef save(first_run=False):\n    \"\"\"Saves the current state of the configuration\"\"\"\n    config['FIRST_RUN'] = first_run\n    # use default OS encoding\n    with open(conf_file, 'w') as kolibri_conf_file:\n        json.dump(config, kolibri_conf_file, indent=2, sort_keys=True)\n\n\nif not os.path.isfile(conf_file):\n    logger.info(\"Initialize kolibri_settings.json..\")\n    save(True)\nelse:\n    # Open up the config file and overwrite defaults\n    # use default OS encoding\n    with open(conf_file, 'r') as kolibri_conf_file:\n        config.update(json.load(kolibri_conf_file))\n\n\ndef autoremove_unavailable_plugins():\n    \"\"\"\n    Sanitize INSTALLED_APPS - something that should be done separately for all\n    build in plugins, but we should not auto-remove plugins that are actually\n    configured by the user or some other kind of hard dependency that should\n    make execution stop if not loadable.\n    \"\"\"\n    global config\n    changed = False\n    # Iterate over a copy of the list so that it is not modified during the loop\n    for module_path in config['INSTALLED_APPS'][:]:\n        if not module_exists(module_path):\n            config['INSTALLED_APPS'].remove(module_path)\n            logger.error(\n                (\n                    \"Plugin {mod} not found and disabled. To re-enable it, run:\\n\"\n                    \"   $ kolibri plugin {mod} enable\"\n                ).format(mod=module_path)\n            )\n            changed = True\n    if changed:\n        save()\n\n\ndef enable_default_plugins():\n    \"\"\"\n    Enable new plugins that have been added between versions\n    This will have the undesired side effect of reactivating\n    default plugins that have been explicitly disabled by a user.\n    However, until we add disabled plugins to a blacklist, this is\n    unavoidable.\n    \"\"\"\n    global config\n    changed = False\n    for module_path in DEFAULT_PLUGINS:\n        if module_path not in config['INSTALLED_APPS']:\n            config['INSTALLED_APPS'].append(module_path)\n            logger.warning(\n                (\n                    \"Default plugin {mod} not found in configuration. To re-disable it, run:\\n\"\n                    \"   $ kolibri plugin {mod} disable\"\n                ).format(mod=module_path)\n            )\n            changed = True\n\n    if changed:\n        save()\n\n\n# read the config file options in here so they can be accessed from a standard location\nOPTIONS = read_options_file(KOLIBRI_HOME)\n", "path": "kolibri/utils/conf.py"}], "after_files": [{"content": "\"\"\"\nKolibri configuration data\n==========================\n\n.. warning::\n    Do not load any django.conf.settings stuff here. This configuration data\n    precedes loading of settings, it is not part of the settings stack.\n\nTODO: We need to figure out our conf API. Do we store in ini/json/yaml?\n\n * How do we retrieve config data?\n * When should configuration files be loaded and written?\n\nThis module should be easier to document, for instance by having VARIABLES\ninstead of a dict.\n\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport json\nimport logging\nimport os\n\nfrom .compat import module_exists\nfrom .options import read_options_file\n\nlogger = logging.getLogger(__name__)\n\n# use default OS encoding\nwith open(os.path.join(os.path.dirname(__file__), 'KOLIBRI_CORE_JS_NAME')) as f:\n    KOLIBRI_CORE_JS_NAME = f.read().strip()\n\n#: Absolute path of the main user data directory.\n#: Will be created automatically if it doesn't exist.\nKOLIBRI_HOME = os.path.abspath(os.path.expanduser(os.environ[\"KOLIBRI_HOME\"]))\n\n# Creating KOLIBRI_HOME atm. has to happen here as for instance utils.cli is not\n# called through py.test. This file is the first basic entry point of\n# Kolibri, although utils.cli may or may not precede it.\nif not os.path.exists(KOLIBRI_HOME):\n    parent = os.path.dirname(KOLIBRI_HOME)\n    if not os.path.exists(parent):\n        raise RuntimeError(\"The parent of your KOLIBRI_HOME does not exist: {}\".format(parent))\n    os.mkdir(KOLIBRI_HOME)\n\n#: Set defaults before updating the dict\nconfig = {}\n\ntry:\n    # The default list for this is populated from build_tools/default_plugins.txt\n    # in the root of the Kolibri repository. The default list is identical to the list below,\n    # except that the style_guide plugin is not enabled in production builds.\n    # Caveat: this list may have been changed at build time to specify a different list of plugins.\n    from .build_config.default_plugins import plugins\n    DEFAULT_PLUGINS = plugins\nexcept ImportError:\n    DEFAULT_PLUGINS = [\n        \"kolibri.plugins.facility_management\",\n        \"kolibri.plugins.device_management\",\n        \"kolibri.plugins.learn\",\n        \"kolibri.plugins.document_pdf_render\",\n        \"kolibri.plugins.html5_app_renderer\",\n        \"kolibri.plugins.media_player\",\n        \"kolibri.plugins.setup_wizard\",\n        \"kolibri.plugins.coach\",\n        \"kolibri.plugins.user\",\n        \"kolibri_exercise_perseus_plugin\",\n        \"kolibri.plugins.style_guide\",\n        \"kolibri.plugins.document_epub_render\",\n    ]\n\n#: Everything in this list is added to django.conf.settings.INSTALLED_APPS\nconfig['INSTALLED_APPS'] = DEFAULT_PLUGINS\n\n#: Well-known plugin names that are automatically searched for and enabled on\n#: first-run.\nconfig['AUTO_SEARCH_PLUGINS'] = []\n\n#: If a config file does not exist, we assume it's the first run\nconfig['FIRST_RUN'] = True\n\nconf_file = os.path.join(KOLIBRI_HOME, \"kolibri_settings.json\")\n\n\ndef update(new_values):\n    \"\"\"\n    Updates current configuration with ``new_values``. Does not save to file.\n    \"\"\"\n    config.update(new_values)\n\n\ndef save(first_run=False):\n    \"\"\"Saves the current state of the configuration\"\"\"\n    config['FIRST_RUN'] = first_run\n    # use default OS encoding\n    with open(conf_file, 'w') as kolibri_conf_file:\n        json.dump(config, kolibri_conf_file, indent=2, sort_keys=True)\n\n\nif not os.path.isfile(conf_file):\n    logger.info(\"Initialize kolibri_settings.json..\")\n    save(True)\nelse:\n    # Open up the config file and overwrite defaults\n    # use default OS encoding\n    with open(conf_file, 'r') as kolibri_conf_file:\n        config.update(json.load(kolibri_conf_file))\n\n\ndef autoremove_unavailable_plugins():\n    \"\"\"\n    Sanitize INSTALLED_APPS - something that should be done separately for all\n    build in plugins, but we should not auto-remove plugins that are actually\n    configured by the user or some other kind of hard dependency that should\n    make execution stop if not loadable.\n    \"\"\"\n    global config\n    changed = False\n    # Iterate over a copy of the list so that it is not modified during the loop\n    for module_path in config['INSTALLED_APPS'][:]:\n        if not module_exists(module_path):\n            config['INSTALLED_APPS'].remove(module_path)\n            logger.error(\n                (\n                    \"Plugin {mod} not found and disabled. To re-enable it, run:\\n\"\n                    \"   $ kolibri plugin {mod} enable\"\n                ).format(mod=module_path)\n            )\n            changed = True\n    if changed:\n        save()\n\n\ndef enable_default_plugins():\n    \"\"\"\n    Enable new plugins that have been added between versions\n    This will have the undesired side effect of reactivating\n    default plugins that have been explicitly disabled by a user.\n    However, until we add disabled plugins to a blacklist, this is\n    unavoidable.\n    \"\"\"\n    global config\n    changed = False\n    for module_path in DEFAULT_PLUGINS:\n        if module_path not in config['INSTALLED_APPS']:\n            config['INSTALLED_APPS'].append(module_path)\n            logger.warning(\n                (\n                    \"Default plugin {mod} not found in configuration. To re-disable it, run:\\n\"\n                    \"   $ kolibri plugin {mod} disable\"\n                ).format(mod=module_path)\n            )\n            changed = True\n\n    if changed:\n        save()\n\n\n# read the config file options in here so they can be accessed from a standard location\nOPTIONS = read_options_file(KOLIBRI_HOME)\n", "path": "kolibri/utils/conf.py"}]}