12
|
1 #!/usr/bin/env python
|
|
2
|
|
3 import sys
|
|
4
|
|
5 def die( message ):
|
|
6 print >> sys.stderr, message
|
|
7 sys.exit(1)
|
|
8
|
|
9 def open_or_die( filename, mode='r', message=None ):
|
|
10 if message is None:
|
|
11 message = 'Error opening {0}'.format( filename )
|
|
12 try:
|
|
13 fh = open( filename, mode )
|
|
14 except IOError, err:
|
|
15 die( '{0}: {1}'.format( message, err.strerror ) )
|
|
16 return fh
|
|
17
|
|
18 class LocationFile( object ):
|
|
19 def __init__( self, filename, comment_chars=None, delimiter='\t', key_column=0 ):
|
|
20 self.filename = filename
|
|
21 if comment_chars is None:
|
|
22 self.comment_chars = ( '#' )
|
|
23 else:
|
|
24 self.comment_chars = tuple( comment_chars )
|
|
25 self.delimiter = delimiter
|
|
26 self.key_column = key_column
|
|
27 self._map = {}
|
|
28 self._populate_map()
|
|
29
|
|
30 def _populate_map( self ):
|
|
31 try:
|
|
32 with open( self.filename ) as fh:
|
|
33 line_number = 0
|
|
34 for line in fh:
|
|
35 line_number += 1
|
|
36 line = line.rstrip( '\r\n' )
|
|
37 if not line.startswith( self.comment_chars ):
|
|
38 elems = line.split( self.delimiter )
|
|
39 if len( elems ) <= self.key_column:
|
|
40 die( 'Location file {0} line {1}: less than {2} columns'.format( self.filename, line_number, self.key_column + 1 ) )
|
|
41 else:
|
|
42 key = elems.pop( self.key_column )
|
|
43 if key in self._map:
|
|
44 if self._map[key] != elems:
|
|
45 die( 'Location file {0} line {1}: duplicate key "{2}"'.format( self.filename, line_number, key ) )
|
|
46 else:
|
|
47 self._map[key] = elems
|
|
48 except IOError, err:
|
|
49 die( 'Error opening location file {0}: {1}'.format( self.filename, err.strerror ) )
|
|
50
|
|
51 def get_values( self, key ):
|
|
52 if key in self._map:
|
|
53 rval = self._map[key]
|
|
54 if len( rval ) == 1:
|
|
55 return rval[0]
|
|
56 else:
|
|
57 return rval
|
|
58 else:
|
|
59 die( 'key "{0}" not found in location file {1}'.format( key, self.filename ) )
|
|
60
|
|
61 def get_values_if_exists( self, key ):
|
|
62 if key in self._map:
|
|
63 rval = self._map[key]
|
|
64 if len( rval ) == 1:
|
|
65 return rval[0]
|
|
66 else:
|
|
67 return rval
|
|
68 else:
|
|
69 return None
|