We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Solr credential ENV vars not passed alongside CKAN_SOLR_URL
### CKAN Version if known (or site URL)

2.7.2

### Please describe the expected behaviour

Setting the following environment variables enables basic authentication for a Solr instance:

```
CKAN_SOLR_URL
CKAN_SOLR_USER
CKAN_SOLR_PASSWORD
```

### Please describe the actual behaviour

`CKAN_SOLR_URL` is honoured, but `CKAN_SOLR_USER` and `CKAN_SOLR_PASSWORD` are ignored and must be set in `ckan.ini`.

### What steps can be taken to reproduce the issue? 

1. Set the following environment variables:

```
CKAN_SOLR_USER=my_missing_user
CKAN_SOLR_PASSWORD=my_password
```

2. Restart CKAN
3. Observe that nothing has changed

Alternatively, create a Solr instance with Basic authentication, set the correct credentials as environment variables, then restart CKAN and watch the Solr connection fail.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ckan/config/environment.py`
Content:
```
1 # encoding: utf-8
2 
3 '''CKAN environment configuration'''
4 import os
5 import logging
6 import warnings
7 from urlparse import urlparse
8 import pytz
9 
10 import sqlalchemy
11 from pylons import config as pylons_config
12 import formencode
13 
14 import ckan.config.routing as routing
15 import ckan.model as model
16 import ckan.plugins as p
17 import ckan.lib.helpers as helpers
18 import ckan.lib.app_globals as app_globals
19 from ckan.lib.redis import is_redis_available
20 import ckan.lib.render as render
21 import ckan.lib.search as search
22 import ckan.logic as logic
23 import ckan.authz as authz
24 import ckan.lib.jinja_extensions as jinja_extensions
25 from ckan.lib.i18n import build_js_translations
26 
27 from ckan.common import _, ungettext, config
28 from ckan.exceptions import CkanConfigurationException
29 
30 log = logging.getLogger(__name__)
31 
32 
33 # Suppress benign warning 'Unbuilt egg for setuptools'
34 warnings.simplefilter('ignore', UserWarning)
35 
36 
37 def load_environment(global_conf, app_conf):
38     """
39     Configure the Pylons environment via the ``pylons.config`` object. This
40     code should only need to be run once.
41     """
42     # this must be run at a time when the env is semi-setup, thus inlined here.
43     # Required by the deliverance plugin and iATI
44     from pylons.wsgiapp import PylonsApp
45     import pkg_resources
46     find_controller_generic = PylonsApp.find_controller
47 
48     # This is from pylons 1.0 source, will monkey-patch into 0.9.7
49     def find_controller(self, controller):
50         if controller in self.controller_classes:
51             return self.controller_classes[controller]
52         # Check to see if its a dotted name
53         if '.' in controller or ':' in controller:
54             ep = pkg_resources.EntryPoint.parse('x={0}'.format(controller))
55 
56             if hasattr(ep, 'resolve'):
57                 # setuptools >= 10.2
58                 mycontroller = ep.resolve()
59             else:
60                 # setuptools >= 11.3
61                 mycontroller = ep.load(False)
62 
63             self.controller_classes[controller] = mycontroller
64             return mycontroller
65         return find_controller_generic(self, controller)
66     PylonsApp.find_controller = find_controller
67 
68     os.environ['CKAN_CONFIG'] = global_conf['__file__']
69 
70     # Pylons paths
71     root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
72 
73     valid_base_public_folder_names = ['public', 'public-bs2']
74     static_files = app_conf.get('ckan.base_public_folder', 'public')
75     app_conf['ckan.base_public_folder'] = static_files
76 
77     if static_files not in valid_base_public_folder_names:
78         raise CkanConfigurationException(
79             'You provided an invalid value for ckan.base_public_folder. '
80             'Possible values are: "public" and "public-bs2".'
81         )
82 
83     log.info('Loading static files from %s' % static_files)
84     paths = dict(root=root,
85                  controllers=os.path.join(root, 'controllers'),
86                  static_files=os.path.join(root, static_files),
87                  templates=[])
88 
89     # Initialize main CKAN config object
90     config.update(global_conf)
91     config.update(app_conf)
92 
93     # Initialize Pylons own config object
94     pylons_config.init_app(global_conf, app_conf, package='ckan', paths=paths)
95 
96     # Update the main CKAN config object with the Pylons specific stuff, as it
97     # quite hard to keep them separated. This should be removed once Pylons
98     # support is dropped
99     config.update(pylons_config)
100 
101     # Setup the SQLAlchemy database engine
102     # Suppress a couple of sqlalchemy warnings
103     msgs = ['^Unicode type received non-unicode bind param value',
104             "^Did not recognize type 'BIGINT' of column 'size'",
105             "^Did not recognize type 'tsvector' of column 'search_vector'"
106             ]
107     for msg in msgs:
108         warnings.filterwarnings('ignore', msg, sqlalchemy.exc.SAWarning)
109 
110     # load all CKAN plugins
111     p.load_all()
112 
113     # Check Redis availability
114     if not is_redis_available():
115         log.critical('Could not connect to Redis.')
116 
117     app_globals.reset()
118 
119     # issue #3260: remove idle transaction
120     # Session that was used for getting all config params nor committed,
121     # neither removed and we have idle connection as result
122     model.Session.commit()
123 
124     # Build JavaScript translations. Must be done after plugins have
125     # been loaded.
126     build_js_translations()
127 
128 
129 # A mapping of config settings that can be overridden by env vars.
130 # Note: Do not remove the following lines, they are used in the docs
131 # Start CONFIG_FROM_ENV_VARS
132 CONFIG_FROM_ENV_VARS = {
133     'sqlalchemy.url': 'CKAN_SQLALCHEMY_URL',
134     'ckan.datastore.write_url': 'CKAN_DATASTORE_WRITE_URL',
135     'ckan.datastore.read_url': 'CKAN_DATASTORE_READ_URL',
136     'ckan.redis.url': 'CKAN_REDIS_URL',
137     'solr_url': 'CKAN_SOLR_URL',
138     'ckan.site_id': 'CKAN_SITE_ID',
139     'ckan.site_url': 'CKAN_SITE_URL',
140     'ckan.storage_path': 'CKAN_STORAGE_PATH',
141     'ckan.datapusher.url': 'CKAN_DATAPUSHER_URL',
142     'smtp.server': 'CKAN_SMTP_SERVER',
143     'smtp.starttls': 'CKAN_SMTP_STARTTLS',
144     'smtp.user': 'CKAN_SMTP_USER',
145     'smtp.password': 'CKAN_SMTP_PASSWORD',
146     'smtp.mail_from': 'CKAN_SMTP_MAIL_FROM'
147 }
148 # End CONFIG_FROM_ENV_VARS
149 
150 
151 def update_config():
152     ''' This code needs to be run when the config is changed to take those
153     changes into account. It is called whenever a plugin is loaded as the
154     plugin might have changed the config values (for instance it might
155     change ckan.site_url) '''
156 
157     for plugin in p.PluginImplementations(p.IConfigurer):
158         # must do update in place as this does not work:
159         # config = plugin.update_config(config)
160         plugin.update_config(config)
161 
162     # Set whitelisted env vars on config object
163     # This is set up before globals are initialized
164 
165     ckan_db = os.environ.get('CKAN_DB', None)
166     if ckan_db:
167         msg = 'Setting CKAN_DB as an env var is deprecated and will be' \
168             ' removed in a future release. Use CKAN_SQLALCHEMY_URL instead.'
169         log.warn(msg)
170         config['sqlalchemy.url'] = ckan_db
171 
172     for option in CONFIG_FROM_ENV_VARS:
173         from_env = os.environ.get(CONFIG_FROM_ENV_VARS[option], None)
174         if from_env:
175             config[option] = from_env
176 
177     root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
178 
179     site_url = config.get('ckan.site_url', '')
180     if not site_url:
181         raise RuntimeError(
182             'ckan.site_url is not configured and it must have a value.'
183             ' Please amend your .ini file.')
184     if not site_url.lower().startswith('http'):
185         raise RuntimeError(
186             'ckan.site_url should be a full URL, including the schema '
187             '(http or https)')
188 
189     display_timezone = config.get('ckan.display_timezone', '')
190     if (display_timezone and
191             display_timezone != 'server' and
192             display_timezone not in pytz.all_timezones):
193         raise CkanConfigurationException(
194             "ckan.display_timezone is not 'server' or a valid timezone"
195         )
196 
197     # Remove backslash from site_url if present
198     config['ckan.site_url'] = config['ckan.site_url'].rstrip('/')
199 
200     ckan_host = config['ckan.host'] = urlparse(site_url).netloc
201     if config.get('ckan.site_id') is None:
202         if ':' in ckan_host:
203             ckan_host, port = ckan_host.split(':')
204         assert ckan_host, 'You need to configure ckan.site_url or ' \
205                           'ckan.site_id for SOLR search-index rebuild to work.'
206         config['ckan.site_id'] = ckan_host
207 
208     # ensure that a favicon has been set
209     favicon = config.get('ckan.favicon', '/base/images/ckan.ico')
210     config['ckan.favicon'] = favicon
211 
212     # Init SOLR settings and check if the schema is compatible
213     # from ckan.lib.search import SolrSettings, check_solr_schema_version
214 
215     # lib.search is imported here as we need the config enabled and parsed
216     search.SolrSettings.init(config.get('solr_url'),
217                              config.get('solr_user'),
218                              config.get('solr_password'))
219     search.check_solr_schema_version()
220 
221     routes_map = routing.make_map()
222     config['routes.map'] = routes_map
223     # The RoutesMiddleware needs its mapper updating if it exists
224     if 'routes.middleware' in config:
225         config['routes.middleware'].mapper = routes_map
226     # routes.named_routes is a CKAN thing
227     config['routes.named_routes'] = routing.named_routes
228     config['pylons.app_globals'] = app_globals.app_globals
229     # initialise the globals
230     app_globals.app_globals._init()
231 
232     helpers.load_plugin_helpers()
233     config['pylons.h'] = helpers.helper_functions
234 
235     # Templates and CSS loading from configuration
236     valid_base_templates_folder_names = ['templates', 'templates-bs2']
237     templates = config.get('ckan.base_templates_folder', 'templates')
238     config['ckan.base_templates_folder'] = templates
239 
240     if templates not in valid_base_templates_folder_names:
241         raise CkanConfigurationException(
242             'You provided an invalid value for ckan.base_templates_folder. '
243             'Possible values are: "templates" and "templates-bs2".'
244         )
245 
246     jinja2_templates_path = os.path.join(root, templates)
247     log.info('Loading templates from %s' % jinja2_templates_path)
248     template_paths = [jinja2_templates_path]
249 
250     extra_template_paths = config.get('extra_template_paths', '')
251     if extra_template_paths:
252         # must be first for them to override defaults
253         template_paths = extra_template_paths.split(',') + template_paths
254     config['computed_template_paths'] = template_paths
255 
256     # Set the default language for validation messages from formencode
257     # to what is set as the default locale in the config
258     default_lang = config.get('ckan.locale_default', 'en')
259     formencode.api.set_stdtranslation(domain="FormEncode",
260                                       languages=[default_lang])
261 
262     # Markdown ignores the logger config, so to get rid of excessive
263     # markdown debug messages in the log, set it to the level of the
264     # root logger.
265     logging.getLogger("MARKDOWN").setLevel(logging.getLogger().level)
266 
267     # Create Jinja2 environment
268     env = jinja_extensions.Environment(
269         **jinja_extensions.get_jinja_env_options())
270     env.install_gettext_callables(_, ungettext, newstyle=True)
271     # custom filters
272     env.filters['empty_and_escape'] = jinja_extensions.empty_and_escape
273     config['pylons.app_globals'].jinja_env = env
274 
275     # CONFIGURATION OPTIONS HERE (note: all config options will override
276     # any Pylons config options)
277 
278     # Initialize SQLAlchemy
279     engine = sqlalchemy.engine_from_config(config, client_encoding='utf8')
280     model.init_model(engine)
281 
282     for plugin in p.PluginImplementations(p.IConfigurable):
283         plugin.configure(config)
284 
285     # reset the template cache - we do this here so that when we load the
286     # environment it is clean
287     render.reset_template_info_cache()
288 
289     # clear other caches
290     logic.clear_actions_cache()
291     logic.clear_validators_cache()
292     authz.clear_auth_functions_cache()
293 
294     # Here we create the site user if they are not already in the database
295     try:
296         logic.get_action('get_site_user')({'ignore_auth': True}, None)
297     except (sqlalchemy.exc.ProgrammingError, sqlalchemy.exc.OperationalError):
298         # (ProgrammingError for Postgres, OperationalError for SQLite)
299         # The database is not initialised.  This is a bit dirty.  This occurs
300         # when running tests.
301         pass
302     except sqlalchemy.exc.InternalError:
303         # The database is not initialised.  Travis hits this
304         pass
305 
306     # Close current session and open database connections to ensure a clean
307     # clean environment even if an error occurs later on
308     model.Session.remove()
309     model.Session.bind.dispose()
310
```
--- 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/ckan/config/environment.py b/ckan/config/environment.py
--- a/ckan/config/environment.py
+++ b/ckan/config/environment.py
@@ -135,6 +135,8 @@
     'ckan.datastore.read_url': 'CKAN_DATASTORE_READ_URL',
     'ckan.redis.url': 'CKAN_REDIS_URL',
     'solr_url': 'CKAN_SOLR_URL',
+    'solr_user': 'CKAN_SOLR_USER',
+    'solr_password': 'CKAN_SOLR_PASSWORD',
     'ckan.site_id': 'CKAN_SITE_ID',
     'ckan.site_url': 'CKAN_SITE_URL',
     'ckan.storage_path': 'CKAN_STORAGE_PATH',

{"golden_diff": "diff --git a/ckan/config/environment.py b/ckan/config/environment.py\n--- a/ckan/config/environment.py\n+++ b/ckan/config/environment.py\n@@ -135,6 +135,8 @@\n     'ckan.datastore.read_url': 'CKAN_DATASTORE_READ_URL',\n     'ckan.redis.url': 'CKAN_REDIS_URL',\n     'solr_url': 'CKAN_SOLR_URL',\n+    'solr_user': 'CKAN_SOLR_USER',\n+    'solr_password': 'CKAN_SOLR_PASSWORD',\n     'ckan.site_id': 'CKAN_SITE_ID',\n     'ckan.site_url': 'CKAN_SITE_URL',\n     'ckan.storage_path': 'CKAN_STORAGE_PATH',\n", "issue": "Solr credential ENV vars not passed alongside CKAN_SOLR_URL\n### CKAN Version if known (or site URL)\r\n\r\n2.7.2\r\n\r\n### Please describe the expected behaviour\r\n\r\nSetting the following environment variables enables basic authentication for a Solr instance:\r\n\r\n```\r\nCKAN_SOLR_URL\r\nCKAN_SOLR_USER\r\nCKAN_SOLR_PASSWORD\r\n```\r\n\r\n### Please describe the actual behaviour\r\n\r\n`CKAN_SOLR_URL` is honoured, but `CKAN_SOLR_USER` and `CKAN_SOLR_PASSWORD` are ignored and must be set in `ckan.ini`.\r\n\r\n### What steps can be taken to reproduce the issue? \r\n\r\n1. Set the following environment variables:\r\n\r\n```\r\nCKAN_SOLR_USER=my_missing_user\r\nCKAN_SOLR_PASSWORD=my_password\r\n```\r\n\r\n2. Restart CKAN\r\n3. Observe that nothing has changed\r\n\r\nAlternatively, create a Solr instance with Basic authentication, set the correct credentials as environment variables, then restart CKAN and watch the Solr connection fail.\n", "before_files": [{"content": "# encoding: utf-8\n\n'''CKAN environment configuration'''\nimport os\nimport logging\nimport warnings\nfrom urlparse import urlparse\nimport pytz\n\nimport sqlalchemy\nfrom pylons import config as pylons_config\nimport formencode\n\nimport ckan.config.routing as routing\nimport ckan.model as model\nimport ckan.plugins as p\nimport ckan.lib.helpers as helpers\nimport ckan.lib.app_globals as app_globals\nfrom ckan.lib.redis import is_redis_available\nimport ckan.lib.render as render\nimport ckan.lib.search as search\nimport ckan.logic as logic\nimport ckan.authz as authz\nimport ckan.lib.jinja_extensions as jinja_extensions\nfrom ckan.lib.i18n import build_js_translations\n\nfrom ckan.common import _, ungettext, config\nfrom ckan.exceptions import CkanConfigurationException\n\nlog = logging.getLogger(__name__)\n\n\n# Suppress benign warning 'Unbuilt egg for setuptools'\nwarnings.simplefilter('ignore', UserWarning)\n\n\ndef load_environment(global_conf, app_conf):\n    \"\"\"\n    Configure the Pylons environment via the ``pylons.config`` object. This\n    code should only need to be run once.\n    \"\"\"\n    # this must be run at a time when the env is semi-setup, thus inlined here.\n    # Required by the deliverance plugin and iATI\n    from pylons.wsgiapp import PylonsApp\n    import pkg_resources\n    find_controller_generic = PylonsApp.find_controller\n\n    # This is from pylons 1.0 source, will monkey-patch into 0.9.7\n    def find_controller(self, controller):\n        if controller in self.controller_classes:\n            return self.controller_classes[controller]\n        # Check to see if its a dotted name\n        if '.' in controller or ':' in controller:\n            ep = pkg_resources.EntryPoint.parse('x={0}'.format(controller))\n\n            if hasattr(ep, 'resolve'):\n                # setuptools >= 10.2\n                mycontroller = ep.resolve()\n            else:\n                # setuptools >= 11.3\n                mycontroller = ep.load(False)\n\n            self.controller_classes[controller] = mycontroller\n            return mycontroller\n        return find_controller_generic(self, controller)\n    PylonsApp.find_controller = find_controller\n\n    os.environ['CKAN_CONFIG'] = global_conf['__file__']\n\n    # Pylons paths\n    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n    valid_base_public_folder_names = ['public', 'public-bs2']\n    static_files = app_conf.get('ckan.base_public_folder', 'public')\n    app_conf['ckan.base_public_folder'] = static_files\n\n    if static_files not in valid_base_public_folder_names:\n        raise CkanConfigurationException(\n            'You provided an invalid value for ckan.base_public_folder. '\n            'Possible values are: \"public\" and \"public-bs2\".'\n        )\n\n    log.info('Loading static files from %s' % static_files)\n    paths = dict(root=root,\n                 controllers=os.path.join(root, 'controllers'),\n                 static_files=os.path.join(root, static_files),\n                 templates=[])\n\n    # Initialize main CKAN config object\n    config.update(global_conf)\n    config.update(app_conf)\n\n    # Initialize Pylons own config object\n    pylons_config.init_app(global_conf, app_conf, package='ckan', paths=paths)\n\n    # Update the main CKAN config object with the Pylons specific stuff, as it\n    # quite hard to keep them separated. This should be removed once Pylons\n    # support is dropped\n    config.update(pylons_config)\n\n    # Setup the SQLAlchemy database engine\n    # Suppress a couple of sqlalchemy warnings\n    msgs = ['^Unicode type received non-unicode bind param value',\n            \"^Did not recognize type 'BIGINT' of column 'size'\",\n            \"^Did not recognize type 'tsvector' of column 'search_vector'\"\n            ]\n    for msg in msgs:\n        warnings.filterwarnings('ignore', msg, sqlalchemy.exc.SAWarning)\n\n    # load all CKAN plugins\n    p.load_all()\n\n    # Check Redis availability\n    if not is_redis_available():\n        log.critical('Could not connect to Redis.')\n\n    app_globals.reset()\n\n    # issue #3260: remove idle transaction\n    # Session that was used for getting all config params nor committed,\n    # neither removed and we have idle connection as result\n    model.Session.commit()\n\n    # Build JavaScript translations. Must be done after plugins have\n    # been loaded.\n    build_js_translations()\n\n\n# A mapping of config settings that can be overridden by env vars.\n# Note: Do not remove the following lines, they are used in the docs\n# Start CONFIG_FROM_ENV_VARS\nCONFIG_FROM_ENV_VARS = {\n    'sqlalchemy.url': 'CKAN_SQLALCHEMY_URL',\n    'ckan.datastore.write_url': 'CKAN_DATASTORE_WRITE_URL',\n    'ckan.datastore.read_url': 'CKAN_DATASTORE_READ_URL',\n    'ckan.redis.url': 'CKAN_REDIS_URL',\n    'solr_url': 'CKAN_SOLR_URL',\n    'ckan.site_id': 'CKAN_SITE_ID',\n    'ckan.site_url': 'CKAN_SITE_URL',\n    'ckan.storage_path': 'CKAN_STORAGE_PATH',\n    'ckan.datapusher.url': 'CKAN_DATAPUSHER_URL',\n    'smtp.server': 'CKAN_SMTP_SERVER',\n    'smtp.starttls': 'CKAN_SMTP_STARTTLS',\n    'smtp.user': 'CKAN_SMTP_USER',\n    'smtp.password': 'CKAN_SMTP_PASSWORD',\n    'smtp.mail_from': 'CKAN_SMTP_MAIL_FROM'\n}\n# End CONFIG_FROM_ENV_VARS\n\n\ndef update_config():\n    ''' This code needs to be run when the config is changed to take those\n    changes into account. It is called whenever a plugin is loaded as the\n    plugin might have changed the config values (for instance it might\n    change ckan.site_url) '''\n\n    for plugin in p.PluginImplementations(p.IConfigurer):\n        # must do update in place as this does not work:\n        # config = plugin.update_config(config)\n        plugin.update_config(config)\n\n    # Set whitelisted env vars on config object\n    # This is set up before globals are initialized\n\n    ckan_db = os.environ.get('CKAN_DB', None)\n    if ckan_db:\n        msg = 'Setting CKAN_DB as an env var is deprecated and will be' \\\n            ' removed in a future release. Use CKAN_SQLALCHEMY_URL instead.'\n        log.warn(msg)\n        config['sqlalchemy.url'] = ckan_db\n\n    for option in CONFIG_FROM_ENV_VARS:\n        from_env = os.environ.get(CONFIG_FROM_ENV_VARS[option], None)\n        if from_env:\n            config[option] = from_env\n\n    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n    site_url = config.get('ckan.site_url', '')\n    if not site_url:\n        raise RuntimeError(\n            'ckan.site_url is not configured and it must have a value.'\n            ' Please amend your .ini file.')\n    if not site_url.lower().startswith('http'):\n        raise RuntimeError(\n            'ckan.site_url should be a full URL, including the schema '\n            '(http or https)')\n\n    display_timezone = config.get('ckan.display_timezone', '')\n    if (display_timezone and\n            display_timezone != 'server' and\n            display_timezone not in pytz.all_timezones):\n        raise CkanConfigurationException(\n            \"ckan.display_timezone is not 'server' or a valid timezone\"\n        )\n\n    # Remove backslash from site_url if present\n    config['ckan.site_url'] = config['ckan.site_url'].rstrip('/')\n\n    ckan_host = config['ckan.host'] = urlparse(site_url).netloc\n    if config.get('ckan.site_id') is None:\n        if ':' in ckan_host:\n            ckan_host, port = ckan_host.split(':')\n        assert ckan_host, 'You need to configure ckan.site_url or ' \\\n                          'ckan.site_id for SOLR search-index rebuild to work.'\n        config['ckan.site_id'] = ckan_host\n\n    # ensure that a favicon has been set\n    favicon = config.get('ckan.favicon', '/base/images/ckan.ico')\n    config['ckan.favicon'] = favicon\n\n    # Init SOLR settings and check if the schema is compatible\n    # from ckan.lib.search import SolrSettings, check_solr_schema_version\n\n    # lib.search is imported here as we need the config enabled and parsed\n    search.SolrSettings.init(config.get('solr_url'),\n                             config.get('solr_user'),\n                             config.get('solr_password'))\n    search.check_solr_schema_version()\n\n    routes_map = routing.make_map()\n    config['routes.map'] = routes_map\n    # The RoutesMiddleware needs its mapper updating if it exists\n    if 'routes.middleware' in config:\n        config['routes.middleware'].mapper = routes_map\n    # routes.named_routes is a CKAN thing\n    config['routes.named_routes'] = routing.named_routes\n    config['pylons.app_globals'] = app_globals.app_globals\n    # initialise the globals\n    app_globals.app_globals._init()\n\n    helpers.load_plugin_helpers()\n    config['pylons.h'] = helpers.helper_functions\n\n    # Templates and CSS loading from configuration\n    valid_base_templates_folder_names = ['templates', 'templates-bs2']\n    templates = config.get('ckan.base_templates_folder', 'templates')\n    config['ckan.base_templates_folder'] = templates\n\n    if templates not in valid_base_templates_folder_names:\n        raise CkanConfigurationException(\n            'You provided an invalid value for ckan.base_templates_folder. '\n            'Possible values are: \"templates\" and \"templates-bs2\".'\n        )\n\n    jinja2_templates_path = os.path.join(root, templates)\n    log.info('Loading templates from %s' % jinja2_templates_path)\n    template_paths = [jinja2_templates_path]\n\n    extra_template_paths = config.get('extra_template_paths', '')\n    if extra_template_paths:\n        # must be first for them to override defaults\n        template_paths = extra_template_paths.split(',') + template_paths\n    config['computed_template_paths'] = template_paths\n\n    # Set the default language for validation messages from formencode\n    # to what is set as the default locale in the config\n    default_lang = config.get('ckan.locale_default', 'en')\n    formencode.api.set_stdtranslation(domain=\"FormEncode\",\n                                      languages=[default_lang])\n\n    # Markdown ignores the logger config, so to get rid of excessive\n    # markdown debug messages in the log, set it to the level of the\n    # root logger.\n    logging.getLogger(\"MARKDOWN\").setLevel(logging.getLogger().level)\n\n    # Create Jinja2 environment\n    env = jinja_extensions.Environment(\n        **jinja_extensions.get_jinja_env_options())\n    env.install_gettext_callables(_, ungettext, newstyle=True)\n    # custom filters\n    env.filters['empty_and_escape'] = jinja_extensions.empty_and_escape\n    config['pylons.app_globals'].jinja_env = env\n\n    # CONFIGURATION OPTIONS HERE (note: all config options will override\n    # any Pylons config options)\n\n    # Initialize SQLAlchemy\n    engine = sqlalchemy.engine_from_config(config, client_encoding='utf8')\n    model.init_model(engine)\n\n    for plugin in p.PluginImplementations(p.IConfigurable):\n        plugin.configure(config)\n\n    # reset the template cache - we do this here so that when we load the\n    # environment it is clean\n    render.reset_template_info_cache()\n\n    # clear other caches\n    logic.clear_actions_cache()\n    logic.clear_validators_cache()\n    authz.clear_auth_functions_cache()\n\n    # Here we create the site user if they are not already in the database\n    try:\n        logic.get_action('get_site_user')({'ignore_auth': True}, None)\n    except (sqlalchemy.exc.ProgrammingError, sqlalchemy.exc.OperationalError):\n        # (ProgrammingError for Postgres, OperationalError for SQLite)\n        # The database is not initialised.  This is a bit dirty.  This occurs\n        # when running tests.\n        pass\n    except sqlalchemy.exc.InternalError:\n        # The database is not initialised.  Travis hits this\n        pass\n\n    # Close current session and open database connections to ensure a clean\n    # clean environment even if an error occurs later on\n    model.Session.remove()\n    model.Session.bind.dispose()\n", "path": "ckan/config/environment.py"}], "after_files": [{"content": "# encoding: utf-8\n\n'''CKAN environment configuration'''\nimport os\nimport logging\nimport warnings\nfrom urlparse import urlparse\nimport pytz\n\nimport sqlalchemy\nfrom pylons import config as pylons_config\nimport formencode\n\nimport ckan.config.routing as routing\nimport ckan.model as model\nimport ckan.plugins as p\nimport ckan.lib.helpers as helpers\nimport ckan.lib.app_globals as app_globals\nfrom ckan.lib.redis import is_redis_available\nimport ckan.lib.render as render\nimport ckan.lib.search as search\nimport ckan.logic as logic\nimport ckan.authz as authz\nimport ckan.lib.jinja_extensions as jinja_extensions\nfrom ckan.lib.i18n import build_js_translations\n\nfrom ckan.common import _, ungettext, config\nfrom ckan.exceptions import CkanConfigurationException\n\nlog = logging.getLogger(__name__)\n\n\n# Suppress benign warning 'Unbuilt egg for setuptools'\nwarnings.simplefilter('ignore', UserWarning)\n\n\ndef load_environment(global_conf, app_conf):\n    \"\"\"\n    Configure the Pylons environment via the ``pylons.config`` object. This\n    code should only need to be run once.\n    \"\"\"\n    # this must be run at a time when the env is semi-setup, thus inlined here.\n    # Required by the deliverance plugin and iATI\n    from pylons.wsgiapp import PylonsApp\n    import pkg_resources\n    find_controller_generic = PylonsApp.find_controller\n\n    # This is from pylons 1.0 source, will monkey-patch into 0.9.7\n    def find_controller(self, controller):\n        if controller in self.controller_classes:\n            return self.controller_classes[controller]\n        # Check to see if its a dotted name\n        if '.' in controller or ':' in controller:\n            ep = pkg_resources.EntryPoint.parse('x={0}'.format(controller))\n\n            if hasattr(ep, 'resolve'):\n                # setuptools >= 10.2\n                mycontroller = ep.resolve()\n            else:\n                # setuptools >= 11.3\n                mycontroller = ep.load(False)\n\n            self.controller_classes[controller] = mycontroller\n            return mycontroller\n        return find_controller_generic(self, controller)\n    PylonsApp.find_controller = find_controller\n\n    os.environ['CKAN_CONFIG'] = global_conf['__file__']\n\n    # Pylons paths\n    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n    valid_base_public_folder_names = ['public', 'public-bs2']\n    static_files = app_conf.get('ckan.base_public_folder', 'public')\n    app_conf['ckan.base_public_folder'] = static_files\n\n    if static_files not in valid_base_public_folder_names:\n        raise CkanConfigurationException(\n            'You provided an invalid value for ckan.base_public_folder. '\n            'Possible values are: \"public\" and \"public-bs2\".'\n        )\n\n    log.info('Loading static files from %s' % static_files)\n    paths = dict(root=root,\n                 controllers=os.path.join(root, 'controllers'),\n                 static_files=os.path.join(root, static_files),\n                 templates=[])\n\n    # Initialize main CKAN config object\n    config.update(global_conf)\n    config.update(app_conf)\n\n    # Initialize Pylons own config object\n    pylons_config.init_app(global_conf, app_conf, package='ckan', paths=paths)\n\n    # Update the main CKAN config object with the Pylons specific stuff, as it\n    # quite hard to keep them separated. This should be removed once Pylons\n    # support is dropped\n    config.update(pylons_config)\n\n    # Setup the SQLAlchemy database engine\n    # Suppress a couple of sqlalchemy warnings\n    msgs = ['^Unicode type received non-unicode bind param value',\n            \"^Did not recognize type 'BIGINT' of column 'size'\",\n            \"^Did not recognize type 'tsvector' of column 'search_vector'\"\n            ]\n    for msg in msgs:\n        warnings.filterwarnings('ignore', msg, sqlalchemy.exc.SAWarning)\n\n    # load all CKAN plugins\n    p.load_all()\n\n    # Check Redis availability\n    if not is_redis_available():\n        log.critical('Could not connect to Redis.')\n\n    app_globals.reset()\n\n    # issue #3260: remove idle transaction\n    # Session that was used for getting all config params nor committed,\n    # neither removed and we have idle connection as result\n    model.Session.commit()\n\n    # Build JavaScript translations. Must be done after plugins have\n    # been loaded.\n    build_js_translations()\n\n\n# A mapping of config settings that can be overridden by env vars.\n# Note: Do not remove the following lines, they are used in the docs\n# Start CONFIG_FROM_ENV_VARS\nCONFIG_FROM_ENV_VARS = {\n    'sqlalchemy.url': 'CKAN_SQLALCHEMY_URL',\n    'ckan.datastore.write_url': 'CKAN_DATASTORE_WRITE_URL',\n    'ckan.datastore.read_url': 'CKAN_DATASTORE_READ_URL',\n    'ckan.redis.url': 'CKAN_REDIS_URL',\n    'solr_url': 'CKAN_SOLR_URL',\n    'solr_user': 'CKAN_SOLR_USER',\n    'solr_password': 'CKAN_SOLR_PASSWORD',\n    'ckan.site_id': 'CKAN_SITE_ID',\n    'ckan.site_url': 'CKAN_SITE_URL',\n    'ckan.storage_path': 'CKAN_STORAGE_PATH',\n    'ckan.datapusher.url': 'CKAN_DATAPUSHER_URL',\n    'smtp.server': 'CKAN_SMTP_SERVER',\n    'smtp.starttls': 'CKAN_SMTP_STARTTLS',\n    'smtp.user': 'CKAN_SMTP_USER',\n    'smtp.password': 'CKAN_SMTP_PASSWORD',\n    'smtp.mail_from': 'CKAN_SMTP_MAIL_FROM'\n}\n# End CONFIG_FROM_ENV_VARS\n\n\ndef update_config():\n    ''' This code needs to be run when the config is changed to take those\n    changes into account. It is called whenever a plugin is loaded as the\n    plugin might have changed the config values (for instance it might\n    change ckan.site_url) '''\n\n    for plugin in p.PluginImplementations(p.IConfigurer):\n        # must do update in place as this does not work:\n        # config = plugin.update_config(config)\n        plugin.update_config(config)\n\n    # Set whitelisted env vars on config object\n    # This is set up before globals are initialized\n\n    ckan_db = os.environ.get('CKAN_DB', None)\n    if ckan_db:\n        msg = 'Setting CKAN_DB as an env var is deprecated and will be' \\\n            ' removed in a future release. Use CKAN_SQLALCHEMY_URL instead.'\n        log.warn(msg)\n        config['sqlalchemy.url'] = ckan_db\n\n    for option in CONFIG_FROM_ENV_VARS:\n        from_env = os.environ.get(CONFIG_FROM_ENV_VARS[option], None)\n        if from_env:\n            config[option] = from_env\n\n    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n    site_url = config.get('ckan.site_url', '')\n    if not site_url:\n        raise RuntimeError(\n            'ckan.site_url is not configured and it must have a value.'\n            ' Please amend your .ini file.')\n    if not site_url.lower().startswith('http'):\n        raise RuntimeError(\n            'ckan.site_url should be a full URL, including the schema '\n            '(http or https)')\n\n    display_timezone = config.get('ckan.display_timezone', '')\n    if (display_timezone and\n            display_timezone != 'server' and\n            display_timezone not in pytz.all_timezones):\n        raise CkanConfigurationException(\n            \"ckan.display_timezone is not 'server' or a valid timezone\"\n        )\n\n    # Remove backslash from site_url if present\n    config['ckan.site_url'] = config['ckan.site_url'].rstrip('/')\n\n    ckan_host = config['ckan.host'] = urlparse(site_url).netloc\n    if config.get('ckan.site_id') is None:\n        if ':' in ckan_host:\n            ckan_host, port = ckan_host.split(':')\n        assert ckan_host, 'You need to configure ckan.site_url or ' \\\n                          'ckan.site_id for SOLR search-index rebuild to work.'\n        config['ckan.site_id'] = ckan_host\n\n    # ensure that a favicon has been set\n    favicon = config.get('ckan.favicon', '/base/images/ckan.ico')\n    config['ckan.favicon'] = favicon\n\n    # Init SOLR settings and check if the schema is compatible\n    # from ckan.lib.search import SolrSettings, check_solr_schema_version\n\n    # lib.search is imported here as we need the config enabled and parsed\n    search.SolrSettings.init(config.get('solr_url'),\n                             config.get('solr_user'),\n                             config.get('solr_password'))\n    search.check_solr_schema_version()\n\n    routes_map = routing.make_map()\n    config['routes.map'] = routes_map\n    # The RoutesMiddleware needs its mapper updating if it exists\n    if 'routes.middleware' in config:\n        config['routes.middleware'].mapper = routes_map\n    # routes.named_routes is a CKAN thing\n    config['routes.named_routes'] = routing.named_routes\n    config['pylons.app_globals'] = app_globals.app_globals\n    # initialise the globals\n    app_globals.app_globals._init()\n\n    helpers.load_plugin_helpers()\n    config['pylons.h'] = helpers.helper_functions\n\n    # Templates and CSS loading from configuration\n    valid_base_templates_folder_names = ['templates', 'templates-bs2']\n    templates = config.get('ckan.base_templates_folder', 'templates')\n    config['ckan.base_templates_folder'] = templates\n\n    if templates not in valid_base_templates_folder_names:\n        raise CkanConfigurationException(\n            'You provided an invalid value for ckan.base_templates_folder. '\n            'Possible values are: \"templates\" and \"templates-bs2\".'\n        )\n\n    jinja2_templates_path = os.path.join(root, templates)\n    log.info('Loading templates from %s' % jinja2_templates_path)\n    template_paths = [jinja2_templates_path]\n\n    extra_template_paths = config.get('extra_template_paths', '')\n    if extra_template_paths:\n        # must be first for them to override defaults\n        template_paths = extra_template_paths.split(',') + template_paths\n    config['computed_template_paths'] = template_paths\n\n    # Set the default language for validation messages from formencode\n    # to what is set as the default locale in the config\n    default_lang = config.get('ckan.locale_default', 'en')\n    formencode.api.set_stdtranslation(domain=\"FormEncode\",\n                                      languages=[default_lang])\n\n    # Markdown ignores the logger config, so to get rid of excessive\n    # markdown debug messages in the log, set it to the level of the\n    # root logger.\n    logging.getLogger(\"MARKDOWN\").setLevel(logging.getLogger().level)\n\n    # Create Jinja2 environment\n    env = jinja_extensions.Environment(\n        **jinja_extensions.get_jinja_env_options())\n    env.install_gettext_callables(_, ungettext, newstyle=True)\n    # custom filters\n    env.filters['empty_and_escape'] = jinja_extensions.empty_and_escape\n    config['pylons.app_globals'].jinja_env = env\n\n    # CONFIGURATION OPTIONS HERE (note: all config options will override\n    # any Pylons config options)\n\n    # Initialize SQLAlchemy\n    engine = sqlalchemy.engine_from_config(config, client_encoding='utf8')\n    model.init_model(engine)\n\n    for plugin in p.PluginImplementations(p.IConfigurable):\n        plugin.configure(config)\n\n    # reset the template cache - we do this here so that when we load the\n    # environment it is clean\n    render.reset_template_info_cache()\n\n    # clear other caches\n    logic.clear_actions_cache()\n    logic.clear_validators_cache()\n    authz.clear_auth_functions_cache()\n\n    # Here we create the site user if they are not already in the database\n    try:\n        logic.get_action('get_site_user')({'ignore_auth': True}, None)\n    except (sqlalchemy.exc.ProgrammingError, sqlalchemy.exc.OperationalError):\n        # (ProgrammingError for Postgres, OperationalError for SQLite)\n        # The database is not initialised.  This is a bit dirty.  This occurs\n        # when running tests.\n        pass\n    except sqlalchemy.exc.InternalError:\n        # The database is not initialised.  Travis hits this\n        pass\n\n    # Close current session and open database connections to ensure a clean\n    # clean environment even if an error occurs later on\n    model.Session.remove()\n    model.Session.bind.dispose()\n", "path": "ckan/config/environment.py"}]}