Skip to content

Commit

Permalink
add desiutil.depend.mergedep + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sbailey committed Feb 12, 2021
1 parent 9581e6e commit 13b5338
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
45 changes: 45 additions & 0 deletions py/desiutil/depend.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,51 @@ def iterdep(header):
return
return

def mergedep(srchdr, dsthdr, conflict='src'):
'''Merge dependencies from srchdr into dsthdr
Parameters
----------
srchdr : dict-like
source dict-like object, *e.g.* :class:`astropy.io.fits.Header`,
with dependency keywords DEPNAMnn, DEPVERnn
dsthdr : dict-like
destination dict-like object
conflict : str, optional
'src' or 'dst' or 'exception'; see notes
Notes
-----
Dependencies in srchdr are added to dsthdr, modifying it in-place,
adjusting DEPNAMnn/DEPVERnn numbering as needed. If the same dependency
appears in both headers with different versions, ``conflict``
controls the behavior:
* if 'src', the srchdr value replaces the dsthdr value
* if 'dst', the dsthdr value is retained unchanged
* if 'exception', raise a ValueError exception
Raises
------
ValueError
If `conflict == 'exception'` and the same dependency name appears
in both headers with different values; or if `conflict` isn't one
of 'src', 'dst', or 'exception'.
'''
if not conflict in ('src', 'dst', 'exception'):
raise ValueError(f"conflict ({conflict}) should be 'src', 'dst', or 'exception'")

for name, version in iterdep(srchdr):
if hasdep(dsthdr, name) and getdep(dsthdr, name) != version:
if conflict == 'src':
setdep(dsthdr, name, version)
elif conflict == 'dst':
pass
else:
v2 = getdep(dsthdr, name)
raise ValueError(f'Version conflict for {name}: {version} != {v2}')
else:
setdep(dsthdr, name, version)

def add_dependencies(header, module_names=None, long_python=False):
'''Adds ``DEPNAMnn``, ``DEPVERnn`` keywords to header for imported modules.
Expand Down
43 changes: 42 additions & 1 deletion py/desiutil/test/test_depend.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import unittest
import sys
from collections import OrderedDict
from ..depend import (setdep, getdep, hasdep, iterdep, Dependencies,
from ..depend import (setdep, getdep, hasdep, iterdep, mergedep, Dependencies,
add_dependencies)
from .. import __version__ as desiutil_version

Expand Down Expand Up @@ -79,6 +79,47 @@ def test_hasdep(self):
self.assertTrue(hasdep(hdr, 'test010'))
self.assertFalse(hasdep(hdr, 'test020'))

def test_mergedep(self):
"""Test merging dependencies from one header to another
"""
src = dict(
DEPNAM00='blat', DEPVER00='1.0',
DEPNAM01='foo', DEPVER01='2.0',
)
dst = dict(
DEPNAM00='biz', DEPVER00='3.0',
DEPNAM01='bat', DEPVER01='4.0',
)
#- dependencies from src should be added to dst
mergedep(src, dst)
self.assertEqual(getdep(src, 'blat'), getdep(dst, 'blat'))
self.assertEqual(getdep(src, 'foo'), getdep(dst, 'foo'))

#- if conflict='src', a src dependency can replace a dst dependency
dst = dict(
DEPNAM00='biz', DEPVER00='3.0',
DEPNAM01='blat', DEPVER01='4.0',
)
mergedep(src, dst, conflict='src')
self.assertEqual(getdep(src, 'blat'), getdep(dst, 'blat'))
self.assertEqual(getdep(src, 'foo'), getdep(dst, 'foo'))

#- if conflict='dst', the dst dependency is kept even if in src
dst = dict(
DEPNAM00='biz', DEPVER00='3.0',
DEPNAM01='blat', DEPVER01='4.0',
)
mergedep(src, dst, conflict='dst')
self.assertEqual(getdep(dst, 'blat'), '4.0') #- not '1.0'

#- if conflict='exception', should raise a ValueError
dst = dict(
DEPNAM00='biz', DEPVER00='3.0',
DEPNAM01='blat', DEPVER01='4.0',
)
with self.assertRaises(ValueError):
mergedep(src, dst, conflict='exception')

@unittest.skipUnless(test_fits_header, 'requires astropy.io.fits')
def test_fits_header(self):
"""Test dependency functions with an actual FITS header.
Expand Down

0 comments on commit 13b5338

Please sign in to comment.