def test_line_repeat_in_definition():
    # You cannot repeat keys
    r = InputReader()
    r.add_line_key(str('red'))
    with raises(ReaderError) as e:
        r.add_line_key('red')
    assert search(r'The keyname "\w+" has been defined twice', str(e.value))
def test_line_case_definition():
    r = InputReader()
    a = r.add_line_key('red', case=True)
    assert a._case
    with raises(ValueError) as e:
        r.add_line_key('blue', case='True')
    assert 'case must be bool' in str(e.value)
def test_line_read_case_sensitive():
    r = InputReader()
    r.add_line_key('blue', type=str)
    inp = r.read_input(['blue HeLLo'])
    assert inp.blue == 'hello'
    r.add_line_key('red', type=str, case=True)
    inp = r.read_input(['red HeLLo'])
    assert inp.red == 'HeLLo'
def test_unknown_keys_cause_failure(setup):
    # Don't ignore unknown keys
    parse_string = setup[-1]
    reader = InputReader(comment='//', ignoreunknown=False)
    reader.add_boolean_key('red')
    reader.add_line_key('path')
    with raises(ReaderError) as e:
        reader.read_input(parse_string)
    assert 'Unrecognized key' in str(e.value)
def test_ignoreunknown_actually_ignores_unknown(setup):
    # Ignore unknown keys
    parse_string = setup[-1]
    reader = InputReader(comment='//', ignoreunknown=True)
    reader.add_boolean_key('red')
    reader.add_line_key('path')
    inp = reader.read_input(parse_string)
    with raises(AttributeError):
        inp.blue
def test_comments_are_handled_correctly(setup):
    parse_string = setup[-1]
    reader = InputReader(comment='#')
    reader.add_boolean_key('red')
    reader.add_boolean_key('blue')
    reader.add_line_key('path')
    with raises(ReaderError) as e:
        reader.read_input(parse_string)
    regex = r'expected \d+ arguments, got \d+'
    assert search(regex, str(e.value))
def test_line_read_using_defaults():
    r = InputReader()
    r.add_line_key('blue')
    inp = r.read_input(['blue bird'])
    assert inp.blue == 'bird'
    with raises(ReaderError) as e:
        inp = r.read_input(['blue'])
    assert search(r'expected .*\d+ arguments, got \d+', str(e.value))
    with raises(ReaderError) as e:
        inp = r.read_input(['blue bird egg'])
    assert search(r'expected .*\d+ arguments, got \d+', str(e.value))
def test_line_missing_keyname():
    r = InputReader()
    with raises(TypeError):
        r.add_line_key()
    with raises(TypeError):
        r.add_line_key(type=str)
    with raises(TypeError):
        r.add_line_key(glob={})
    with raises(TypeError):
        r.add_line_key(keywords={})
    with raises(TypeError):
        r.add_line_key(case=False)
def test_line_correct_call():
    r = InputReader()
    a = r.add_line_key('red')
    assert a.name == 'red'
    assert a._type == [str]
    assert a._glob == {}
    assert a._keywords == {}
    assert not a._case
    with raises(TypeError) as e:
        r.add_line_key('blue', glob={'len':'*'},
                               keywords={'bird':{}})
    assert 'Cannot define both glob and keywords' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('pink', type=None, 
                               glob=None, keywords=None)
    assert 'type, glob and keywords cannot all be empty' in str(e.value)
def test_case_sensitivity_at_class_level():
    ir = InputReader(case=True)
    assert ir._case
    l = ir.add_line_key('RED')
    assert l._case
    with raises(ValueError):
        ir2 = InputReader(case='True')
Exemple #11
0
def test_line_read_using_keywords():
    r = InputReader()
    r.add_line_key('red', type=int, 
                          keywords={'robin':{}})
    inp = r.read_input(['red 5 robin=early'])
    assert inp.red == (5, {'robin':'early'})
    inp = r.read_input(['red 5'])
    assert inp.red == (5, {})
    with raises(ReaderError) as e:
        r.read_input(['red 5 robin=early light=special'])
    assert 'Unknown keyword' in str(e.value)
    
    r.add_line_key('blue', type=[int, int],
                           keywords={'egg':{'type':int, 'default':1},
                                     'ice':{'type':(4, 5)}})
    inp = r.read_input(['blue 5 7 egg=6 ice=4'])
    assert inp.blue == (5, 7, {'egg':6, 'ice':4})
    inp = r.read_input(['blue 5 7 ice=5'])
    assert inp.blue == (5, 7, {'egg':1, 'ice':5})
    inp = r.read_input(['blue 5 7'])
    assert inp.blue == (5, 7, {'egg':1})

    r.add_line_key('cyan', type=None, keywords={'by':{'type':int},
                                                'to':{'type':int}})
    inp = r.read_input(['cyan by=14 to=11'])
    assert inp.cyan == {'by':14, 'to':11}
    inp = r.read_input(['cyan by=14'])
    assert inp.cyan == {'by':14}
    inp = r.read_input(['cyan'])
    assert inp.cyan == {}
    with raises(ReaderError) as e:
        inp = r.read_input(['cyan by = 3'])
    assert 'Error reading keyword argument' in str(e.value)
Exemple #12
0
def test_line_name_definition():
    r = InputReader()
    with raises(ValueError) as e:
        r.add_line_key(23)
    assert 'keyname must be str' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('hello goodbye')
    assert 'String cannot contain spaces' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('')
    assert 'String cannot be of zero length' in str(e.value)
Exemple #13
0
def test_line_glob_definitions():
    # Test that glob checking is OK
    r = InputReader()
    a = r.add_line_key('red', glob={'len':'*'})
    assert a._glob == {'len':'*', 'type':str, 'join':False}
    b = r.add_line_key('blue', glob={str('len'):str('?')})
    assert b._glob == {'len':'?', 'type':str, 'join':False}
    c = r.add_line_key('green', glob={'len':'+', 'join':True})
    assert c._glob == {'len':'+', 'type':str, 'join':True}
    e = r.add_line_key('pink', glob={'len':'?', 'type':int})
    assert e._glob == {'len':'?', 'type':int, 'join':False}
    f = r.add_line_key('gray', glob={'len':'*', 'type':(int,"hey",str("hi"),str)})
    assert f._glob == {'len':'*', 'type':(int,"hey","hi",str), 'join':False}
    # Test that glob checking is OK for bad input
    with raises(ValueError) as e:
        r.add_line_key('black', glob='wrong')
    assert 'glob must be a dict' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', glob={'len':'1'})
    assert search(r'"len" must be one of "\*", "\+", or "\?" in glob', str(e.value))
    with raises(ValueError) as e:
        r.add_line_key('black', glob={'join':True})
    assert '"len" required for glob' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', glob={'len':'*', 'join':'True'})
    assert '"join" must be a bool in glob' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', glob={'len':'*', 'type':complex})
    assert 'type must be one of' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', glob={'len':'*', 'type':[str]})
    assert 'list not allowed in type for glob or keywords' in str(e.value)
    with raises(TypeError) as e:
        r.add_line_key('black', glob={'len':'*', 'dumb':True})
    assert 'Unknown key in glob' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', glob={'len':'?', 'join':True})
    assert r'"join=True" makes no sense for "len=?"' in str(e.value)
Exemple #14
0
def test_line_reading_types():
    r = InputReader()
    r.add_line_key('blue', type=int)
    inp = r.read_input(['blue 23'])
    assert inp.blue == 23
    with raises(ReaderError) as e:
        inp = r.read_input(['blue bird'])
    assert search(r'expected \w+, got "\w+"', str(e.value))

    r.add_line_key('red', type=(0, 1, 2, 3))
    inp = r.read_input(['red 3'])
    assert inp.red == 3
    with raises(ReaderError) as e:
        inp = r.read_input(['red 4'])
    assert search(r'expected one of .+, got "\w+"', str(e.value))

    r.add_line_key('green', type=(float, None))
    inp = r.read_input(['green 3'])
    assert inp.green == 3
    inp = r.read_input(['green 3.5'])
    assert inp.green == 3.5
    inp = r.read_input(['green none'])
    assert inp.green is None
    with raises(ReaderError) as e:
        inp = r.read_input(['green bird'])
    assert search(r'expected one of .+, got "\w+"', str(e.value))

    r.add_line_key('cyan', type=[str, (None, str), float])
    inp = r.read_input(['cyan cat dog 6'])
    assert inp.cyan == ('cat', 'dog', 6)
    with raises(ReaderError) as e:
        inp = r.read_input(['cyan cat dog 7 8'])
    assert search('expected .+, got \w+', str(e.value))
    with raises(ReaderError) as e:
        inp = r.read_input(['cyan cat none bird'])
    assert search('expected \w+, got "\w+"', str(e.value))
    inp = r.read_input(['cyan cat none 7.8'])
    assert inp.cyan == ('cat', None, 7.8)

    r.add_line_key('black', type=('hey', str('hi'), 4, 2.8))
    inp = r.read_input(['black 4'])
    assert inp.black == 4
    inp = r.read_input(['black 2.8'])
    assert inp.black == 2.8
    inp = r.read_input(['black hey'])
    assert inp.black == 'hey'
    inp = r.read_input(['black hi'])
    assert inp.black == 'hi'
    with raises(ReaderError) as e:
        inp = r.read_input(['black whoops'])
    assert search('expected one of [a-zA-Z0-9, ".]+, got "\w+"', str(e.value))
    with raises(ReaderError) as e:
        inp = r.read_input(['black 2'])
    assert search('expected one of [a-zA-Z0-9, ".]+, got "\d+"', str(e.value))

    import re
    r.add_line_key('pink', type=re.compile(r'neat\d+'))
    inp = r.read_input(['pink neat68'])
    assert inp.pink == 'neat68'
    with raises(ReaderError) as e:
        inp = r.read_input(['pink near68'])
    assert search('expected regex\(.*\)', str(e.value))
Exemple #15
0
def test_line_read_using_globs():
    r = InputReader()
    r.add_line_key('blue', type=[int, int],
                        glob={'len':'*', 'type':int})
    inp = r.read_input(['blue 1 2 3 4 5 6 7'])
    assert inp.blue == (1, 2, 3, 4, 5, 6, 7)
    inp = r.read_input(['blue 1 2'])
    assert inp.blue == (1, 2)

    r.add_line_key('red', type=[int, int],
                        glob={'len':'*', 'type':int, 'join':True})
    inp = r.read_input(['red 1 2 3 4 5 6 7'])
    assert inp.red == (1, 2, '3 4 5 6 7')
    inp = r.read_input(['red 1 2'])
    assert inp.red == (1, 2)

    r.add_line_key('pink', type=[int, int],
                        glob={'len':'+', 'type':float, 'join':True})
    inp = r.read_input(['pink 1 2 3 4 5 6 7'])
    assert inp.pink == (1, 2, '3.0 4.0 5.0 6.0 7.0')
    inp = r.read_input(['pink 1 2 3'])
    assert inp.pink == (1, 2, '3.0')

    r.add_line_key('cyan', type=[int, int],
                        glob={'len':'?', 'type':int})
    inp = r.read_input(['cyan 1 2 3'])
    assert inp.cyan == (1, 2, 3)
    inp = r.read_input(['cyan 1 2'])
    assert inp.cyan == (1, 2)

    r.add_line_key('yellow', type=int, glob={'len':'?', 'type':int})
    inp = r.read_input(['yellow 1 2'])
    assert inp.yellow == (1, 2)
    inp = r.read_input(['yellow 1'])
    assert inp.yellow == (1,)

    r.add_line_key('teal', type=int, glob={'len':'?', 'type':int, 'default':3})
    inp = r.read_input(['teal 1 2'])
    assert inp.teal == (1, 2)
    inp = r.read_input(['teal 1'])
    assert inp.teal == (1, 3)

    r.add_line_key('gray', type=None, glob={'len':'?'})
    inp = r.read_input(['gray bye'])
    assert inp.gray == 'bye'
    inp = r.read_input(['gray'])
    assert inp.gray == ''

    r.add_line_key('white', type=None, glob={'len':'*'})
    inp = r.read_input(['white hi lo'])
    assert inp.white == ('hi', 'lo')
    inp = r.read_input(['white'])
    assert inp.white == ()

    r.add_line_key('green', type=None, glob={'len':'+', 'join':True})
    inp = r.read_input(['green hi lo'])
    assert inp.green == 'hi lo'

    r.add_line_key('orange', type=None, glob={'len':'*', 'join':True})
    inp = r.read_input(['orange'])
    assert inp.orange == ''

    r.add_line_key('black', type=int, glob={'len':'?', 'type':int})
    with raises(ReaderError) as e:
        r.read_input(['black 1 2 3'])
    assert search(r'expected at most \d+ arguments, got \d+', str(e.value))
    r.add_line_key('maroon', type=int, glob={'len':'+', 'type':int})
    with raises(ReaderError) as e:
        r.read_input(['maroon 1'])
    assert search(r'expected at least \d+ arguments, got \d+', str(e.value))
Exemple #16
0
def read_input(input_file):
    '''Defines what to expect from the input file and then
    reads it in.'''

    # Creates an input reader instance
    reader = InputReader(default=SUPPRESS)

    # Rate parameter, either rate or lifetime, not both
    rate = reader.add_mutually_exclusive_group(required=True)
    # The units are s, ns, ps, or fs.  The default is ps.
    rate.add_line_key('lifetime', type=float,
                      glob={'len' : '?',
                            'type' : ('ps', 'fs', 'ns', 's'),
                            'default' : 'ps'})
    rate.add_line_key('rate', type=float,
                      glob={'len' : '?',
                            'type' : ('thz', 'phz', 'ghz', 'hz'),
                            'default' : 'thz'})

    # The range of the X-axis
    reader.add_line_key('xlim', type=[int, int], default=(1900, 2000))
    reader.add_boolean_key('reverse', action=True, default=False)

    # Read in the raw data.  
    reader.add_line_key('raw', type=[], glob={'len':'*', 'join':True, },
                               default=None, case=True)

    # Read in the peak data.  The wavenumber and height is required.
    # The Lorentzian and Gaussian widths are defaulted to 10 if not given.
    floatkw = {'type' : float, 'default' : 10.0}
    reader.add_line_key('peak', required=True, repeat=True, type=[float,float],
                                keywords={'g':floatkw, 'l':floatkw,
                                          'num' : {'type':int,'default':-1}})

    # Read the exchange information.
    reader.add_line_key('exchange', repeat=True, type=[int, int],
                                    glob={'type' : float,
                                          'default' : 1.0,
                                          'len' : '?'})
    reader.add_boolean_key('nosym', action=False, default=True,
                           dest='symmetric_exchange')

    # Actually read the input file
    args = reader.read_input(input_file)

    # Make sure the filename was given correctly and read in data
    if args.raw:
        args.add('rawName', args.raw)
        args.raw = loadtxt(abs_file_path(args.raw))

    # Make the output file path absolute if given
    args.data = abs_file_path(args.data) if 'data' in args else ''

    if 'save_plot_script' in args:
        args.save_plot_script = abs_file_path(args.save_plot_script)
    else:
        args.save_plot_script = ''

    # Adjust the input rate or lifetime to wavenumbers
    if 'lifetime' in args:
        convert = { 'ps' : 1E-12, 'ns' : 1E-9, 'fs' : 1E-15, 's' : 1 }
        args.add('k', 1 / ( convert[args.lifetime[1]] * args.lifetime[0] ))
    else:
        convert = { 'thz' : 1E12, 'ghz' : 1E9, 'phz' : 1E15, 'hz' : 1 }
        args.add('k', convert[args.rate[1]] * args.rate[0])
    args.k *= HZ2WAVENUM / ( 2 * pi )

    # Parse the vibrational input
    num, vib, Gamma_Lorentz, Gamma_Gauss, heights, rel_rates, num_given = (
                                                    [], [], [], [], [], [], [])
    for peak in args.peak:
        # Vibration #
        num.append(peak[2]['num'])
        num_given.append(False if peak[2]['num'] < 0 else True)
        # Angular frequency
        vib.append(peak[0])
        # Relative peak heights
        heights.append(peak[1])
        # Default Gaussian or Lorentzian width or relative rate
        Gamma_Lorentz.append(peak[2]['l'])
        Gamma_Gauss.append(peak[2]['g'])

    # Either all or none of the numbers must be given explicitly
    if not (all(num_given) or not any(num_given)):
        raise ReaderError('All or none of the peaks must '
                          'be given numbers explicitly')
    # If the numbers were give, make sure there are no duplicates
    if all(num_given):
        if len(num) != len(set(num)):
            raise ReaderError('Duplicate peaks cannot be given')
    # If none were given, number automatically
    else:
        num = range(1, len(num)+1, 1)

    args.add('num', array(num))
    args.add('vib', array(vib))
    args.add('heights', array(heights))
    args.add('Gamma_Lorentz', array(Gamma_Lorentz))
    args.add('Gamma_Gauss', array(Gamma_Gauss))

    # Set up the exchanges
    # Make sure the each exchange number appears in num.
    num = set(num)
    ex = []
    rates = []
    string = 'Requested peak {0} in exchange does not exist'
    if 'exchange' in args:
        for exchange in args.exchange:
            p1 = exchange[0]
            if p1 not in num:
                raise ReaderError(string.format(p1))
            p2 = exchange[1]
            if p2 not in num:
                raise ReaderError(string.format(p2))
            if p1 == p2 and args.symmetric_exchange:
                raise ReaderError('Self exchange is not allowed')
            rate = exchange[2]
            # Offset the peak number by one to match python indicies
            ex.append([p1-1, p2-1])
            rates.append(rate)
    else:
        ex = []
        rates = []
    args.add('exchanges', array(ex, dtype=int))
    args.add('exchange_rates', array(rates))

    # Make sure the xlimits are ascending
    try:
        range_check(args.xlim[0], args.xlim[1])
    except ValueError:
        raise ReaderError('In xrange, the low value must '
                          'less than the high value')

    return args
Exemple #17
0
def test_line_type_definitions():
    # Make sure that correct types are OK
    r = InputReader()
    a = r.add_line_key('red', type=str)
    assert a._type == [str]
    s = r.add_line_key('blue', type=[int])
    assert s._type == [int]
    t = r.add_line_key('green', type=(14, 2.8, None, 'hey', str('hello'), str))
    assert t._type == [(14, 2.8, None, 'hey', 'hello', str)]
    with raises(ValueError) as e:
        u = r.add_line_key('gray', type=None)
    assert 'type, glob and keywords cannot all be empty' in str(e.value)
    v = r.add_line_key('cyan', type=[(int, float), str])
    assert v._type == [(int, float), str]
    import re
    regex = re.compile(r'(\d+|\w*)')
    w = r.add_line_key('pink', type=regex)
    assert w._type == [regex]
    # Make sure incorrect types are not OK
    regex = re.compile(str(r'hi\s+bye'))
    with raises(ValueError) as e:
        r.add_line_key('black', type=regex)
    assert 'Regex should not allow the possibility of spaces' in str(e.value)
    regex = re.compile(r'hi.*bye')
    with raises(ValueError) as e:
        r.add_line_key('black', type=regex)
    assert 'Regex should not allow the possibility of spaces' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type="")
    assert 'String cannot be of zero length' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type='hey there')
    assert 'String cannot contain spaces' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type=str('hey there'))
    assert 'String cannot contain spaces' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type=set([str, int]))
    assert 'type must be one of' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type=complex)
    assert 'type must be one of' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type=[str, [str, int]])
    assert r'Embedded lists not allowed in type' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('black', type=[str, ()])
    assert r'Empty tuple in type' in str(e.value)
Exemple #18
0
def test_line_keyword_definitions():
    # Test that keyword checking is OK
    r = InputReader()
    a = r.add_line_key('red', keywords={'rose':{}})
    assert a._keywords == {'rose':{'default':SUPPRESS,'type':str}}
    # Make sure str works, not just unicode (python2.x)
    b = r.add_line_key('blue', keywords={str('rose'):None})
    assert b._keywords == {'rose':{'default':SUPPRESS,'type':str}}
    c = r.add_line_key('pink', keywords={
                                    'elephant':{str('default'):'drunk'},
                                    'cadillac':{'default':str('bruce')}})
    assert c._keywords == \
                     {'elephant':{'default':'drunk','type':str},
                      'cadillac':{'default':'bruce','type':str}}
    # Test that keyword checking is OK for bad input
    with raises(ValueError) as e:
        r.add_line_key('cyan', keywords='wrong')
    assert 'keywords must be a dict' in str(e.value)
    with raises(TypeError) as e:
        r.add_line_key('cyan', keywords={'p':{'wrong':None}})
    assert 'Unknown key in keyword' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('cyan', keywords={23:None})
    assert 'must be of type str' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('cyan', keywords={'p':['things']})
    assert search(r'Options for keyword "\w+" must be a dict', str(e.value))
    with raises(ValueError) as e:
        r.add_line_key('cyan', keywords={'p':{'type':[str]}})
    assert 'list not allowed in type' in str(e.value)
    with raises(ValueError) as e:
        r.add_line_key('cyan', keywords={'p':{'type':complex}})
    assert 'type must be one of' in str(e.value)