Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-23711: Support shell variables in includeConfigs directive #234

Merged
merged 1 commit into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/lsst.daf.butler/configuring.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ To construct a Butler configuration object (`~lsst.daf.butler.ButlerConfig`) fro
* The supplied config is read in.
* If any leaf nodes in the configuration end in ``includeConfigs`` the values (either a scalar or list) will be treated as the names of other config files.
These files will be located either as an absolute path or relative to the current working directory, or the directory in which the original configuration file was found.
Shell variables will be expanded.
The contents of these files will then be inserted into the configuration at the same hierarchy as the ``includeConfigs`` directive, with priority given to the values defined explicitly in the parent configuration (for lists of include files later files overwrite content from earlier ones).
* Each sub configuration class is constructed by supplying the relevant subset of the global config to the component Config constructor.
* A search path is constructed by concatenating the supplied search path, the environment variable path (``$DAF_BUTLER_CONFIG_PATH``), and the daf_butler config directory (``$DAF_BUTLER_DIR/config``).
Expand Down
2 changes: 2 additions & 0 deletions python/lsst/daf/butler/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ def _processExplicitIncludes(self):
# assume resolve explicitly
subConfigs = []
for fileName in includes:
# Expand any shell variables
fileName = os.path.expandvars(fileName)
found = None
if os.path.isabs(fileName):
found = fileName
Expand Down
11 changes: 11 additions & 0 deletions tests/config/testConfigs/configIncludesEnv.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
includeConfigs:
- viacls.yaml
- abspath.yaml
comp:
item2: "hello"
item50: 5000
unrelated: 1
addon:
includeConfigs: ${SPECIAL_BUTLER_DIR}/viacls2.yaml
comp:
item11: -1
5 changes: 5 additions & 0 deletions tests/config/testConfigs/test3/viacls2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Intended to be loaded via a "cls" entry in another config
comp:
item1: "envvar"
item11: "class"
item50: 501
19 changes: 19 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ def setUp(self):
self.testDir = os.path.abspath(os.path.dirname(__file__))
self.configDir = os.path.join(self.testDir, "config", "testConfigs")
self.configDir2 = os.path.join(self.testDir, "config", "testConfigs", "test2")
self.configDir3 = os.path.join(self.testDir, "config", "testConfigs", "test3")

def testEmpty(self):
"""Ensure that we can read an empty file."""
Expand Down Expand Up @@ -523,6 +524,24 @@ def testIncludeConfigs(self):
self.assertEqual(c["addon", "comp", "item11"], -1)
self.assertEqual(c["addon", "comp", "item50"], 500)

# Now test with an environment variable in includeConfigs
with modified_environment(SPECIAL_BUTLER_DIR=self.configDir3):
c = Config(os.path.join(self.configDir, "configIncludesEnv.yaml"))
self.assertEqual(c["comp", "item2"], "hello")
self.assertEqual(c["comp", "item50"], 5000)
self.assertEqual(c["comp", "item1"], "first")
self.assertEqual(c["comp", "item10"], "tenth")
self.assertEqual(c["comp", "item11"], "eleventh")
self.assertEqual(c["unrelated"], 1)
self.assertEqual(c["addon", "comp", "item1"], "envvar")
self.assertEqual(c["addon", "comp", "item11"], -1)
self.assertEqual(c["addon", "comp", "item50"], 501)

# This will fail
with modified_environment(SPECIAL_BUTLER_DIR=self.configDir2):
with self.assertRaises(FileNotFoundError):
Config(os.path.join(self.configDir, "configIncludesEnv.yaml"))


if __name__ == "__main__":
unittest.main()