Skip to content

Commit

Permalink
Implement and use config set_value()
Browse files Browse the repository at this point in the history
  • Loading branch information
dkirkby committed Oct 6, 2017
1 parent 43740d2 commit f6bd910
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 3 deletions.
2 changes: 2 additions & 0 deletions doc/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ desisurvey change log
0.9.3 (unreleased)
------------------

* Fixes #18, #49, #54.
* Add progress columns to track fiber assignment and planning.
* Add support for optional depth-first survey strategy.
* Docs now auto-generated at http://desisurvey.readthedocs.io/en/latest/

Expand Down
27 changes: 27 additions & 0 deletions py/desisurvey/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@
to astropy quantities. Strings of the form YYYY-MM-DD are converted to
datetime.date objects.
To change a value after the configuration has been loaded into memory use,
for example::
>>> config.full_moon_nights.set_value(5)
Assigned values must have the appropriate converted types, for example::
>>> import datetime
>>> config.last_day.set_value(datetime.date(2024, 1, 1))
>>> import astropy.units as u
>>> config.location.temperature.set_value(-5 * u.deg_C)
The configuration is implemented as a singleton so the YAML file is only
loaded and parsed the first time a Configuration() is built. Subsequent
calls to Configuration() always return the same object.
Expand Down Expand Up @@ -98,6 +110,21 @@ def __call__(self):
raise RuntimeError(
'{0} is a non-terminal config node.'.format(self.path))

def set_value(self, new_value):
"""Set a terminal node's value or raise a RuntimeError for
a non-terminal node.
"""
try:
old_value = self._value
if not isinstance(new_value, type(old_value)):
raise RuntimeError(
'new type ({}) does not match old type ({}).'
.format(type(new_value), type(old_value)))
self._value = new_value
except AttributeError:
raise RuntimeError(
'{0} is a non-terminal config node.'.format(self.path))


class Configuration(Node):
"""Top-level configuration data node.
Expand Down
13 changes: 13 additions & 0 deletions py/desisurvey/test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,25 @@ def test_terminal_value(self):
self.assertEqual(c.const.pi(), 3.141)
self.assertEqual(c.output_path(), '.')

def test_set_value(self):
"""Terminal node values changed with set_value()"""
Configuration.reset()
c = Configuration(self.simple)
c.const.pi.set_value(4.0)
self.assertEqual(c.const.pi(), 4.0)
with self.assertRaises(RuntimeError):
c.const.pi.set_value(4) # type(4) != float
with self.assertRaises(RuntimeError):
c.const.gravity.set_value(9.81) # type(9.81) != u.Quantity

def test_non_terminal_value(self):
"""Non-terminal nodes do not have an associated value"""
Configuration.reset()
c = Configuration(self.simple)
with self.assertRaises(RuntimeError):
c.const()
with self.assertRaises(RuntimeError):
c.const.set_value(123)

def test_node_path(self):
"""Config nodes have associated paths"""
Expand Down
6 changes: 3 additions & 3 deletions py/desisurvey/test/test_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ def setUpClass(cls):
# Just run for 2 days for testing
start = datetime.date(2019,12,1)
stop = datetime.date(2019,12,3)
config.first_day._value = start
config.last_day._value = stop
config.first_day.set_value(start)
config.last_day.set_value(stop)
# Use just a subset of the tiles for faster testing
tiles = Table(desimodel.io.load_tiles())
subset = (35 < tiles['RA']) & (tiles['RA'] < 55) & \
(-10 < tiles['DEC']) & (tiles['DEC'] < 20)
tiles_file = os.path.join(cls.tmpdir, 'tiles-subset.fits')
tiles[subset].write(tiles_file)
config.tiles_file._value = tiles_file
config.tiles_file.set_value(tiles_file)

@classmethod
def tearDownClass(cls):
Expand Down

0 comments on commit f6bd910

Please sign in to comment.