1 # -*- coding: utf-8 -*-
2 from __future__ import division
10 'datetime_to_timestamp',
16 'clean_alnum_unicode',
22 'str_split_column_ipv6',
29 IPV4_IN_IPV6_PREFIX = '::ffff:'
31 def datetime_to_timestamp(dt):
32 return calendar.timegm(dt.utctimetuple())
34 def read_cfg(filename):
36 Function that reads a file in the form
38 and returns the resulting dictionary
41 for line in file(filename).readlines():
42 line = line.rstrip('\r\n\0')
43 line = unicode(line, 'utf-8')
44 if line.startswith(u'#'):
45 continue # skip comments
46 spl = line.split(u'=', 1)
54 def strmmsi_to_mmsi(strmmsi):
56 Convert from str mmsi to sql-int mmsi
57 Special treatment manal input
62 assert strmmsi[3:5] == 'MI', 'Invalid strmmsi ' + strmmsi
63 strmmsi = strmmsi[:3]+'00'+strmmsi[5:]
64 return int('-'+strmmsi)
67 def mmsi_to_strmmsi(mmsi):
69 Convert from sql-into mmsi to str mmsi
70 Special treatment manal input
74 strmmsi = "%08d" % -mmsi
75 assert strmmsi[3:5] == '00'
76 strmmsi = strmmsi[:3]+'MI'+strmmsi[5:]
80 def clean_ais_charset(txt):
81 assert isinstance(txt, str)
85 if oc < 32 or oc > 95:
92 assert isinstance(txt, str)
95 if ( c >= '0' and c <= '9' ) or ( c >= 'A' and c <= 'Z' ):
99 def clean_alnum_unicode(txt):
100 assert isinstance(txt, unicode)
101 return unicode(clean_alnum(txt.encode('ascii7', 'replace')))
104 def open_with_mkdirs(filename, mode):
106 return file(filename, mode)
107 except IOError, ioerr:
108 logging.warning("file(%s,%s): errno %s %s", filename, mode, ioerr.errno, ioerr.strerror)
109 # FIXME only if doesn't exists ...
110 #print 'Creating directory', os.path.dirname(filename)
111 os.makedirs(os.path.dirname(filename))
112 return file(filename, mode)
116 def logliner(filename):
117 for line in file(filename).readlines():
121 # debug/display wraper source
122 def dumpsource(source):
124 while line and line[-1] in '\r\n\0':
130 return txt.replace(u'&', u'&').replace(u'<', u'<')
133 os.system('touch /home/nirgal/kod/ais/alarm &')
136 def str_split_column_ipv6(txt):
138 Helper function that will split a column separated string of tokens.
139 It will take care not to ignore : in [] for ipv6 support.
144 for i in range(len(txt)):
147 res.append(txt[iprev:i])
154 res.append(txt[iprev:])
158 def formataddr(addr):
159 if addr.startswith(IPV4_IN_IPV6_PREFIX):
169 class LatLonFormatError(ValueError):
173 def clean_latitude(data):
175 Convert a string latitude into a float.
176 Raises LatLonFormatError on error.
178 data = data.replace(u"''", u'"') # common mistake
179 data = data.replace(u' ', u'') # remove spaces
183 tmp, side = data[:-1], data[-1]
186 elif side == sides[1]:
189 raise LatLonFormatError(u'Last character must be either %s or %s.', sides[0], sides[1])
190 spl = tmp.split(u'°')
192 raise LatLonFormatError(u'You need to use the ° character.')
197 raise LatLonFormatError(u'Degrees must be an number. It\'s %s.', d)
198 spl = tmp.split(u"'", 1)
200 # no ' sign: ok only if there is nothing but the side after °
201 # we don't accept seconds if there is no minutes:
202 # It might be an entry mistake
207 raise LatLonFormatError(u'You must use the \' character between ° and %s.', data[-1])
213 raise LatLonFormatError(u'Minutes must be an number. It\'s %s.', m)
218 raise LatLonFormatError(u'You must use the " character between seconds and %s.', data[-1])
223 raise LatLonFormatError(u'Seconds must be an number. It\'s %s.', s)
224 data = side * ( d + m / 60 + s / 3600)
226 if data < -90 or data > 90:
227 raise LatLonFormatError(u'%s in not in -90..90 range', data)
232 def clean_longitude(data):
234 Convert a string latitude into a float.
235 Raises LatLonFormatError on error.
237 data = data.replace(u"''", u'"') # common mistake
238 data = data.replace(u' ', u'') # remove spaces
242 tmp, side = data[:-1], data[-1]
245 elif side == sides[1]:
248 raise LatLonFormatError(u'Last character must be either %s or %s.', sides[0], sides[1])
249 spl = tmp.split(u'°')
251 raise LatLonFormatError(u'You need to use the ° character.')
256 raise LatLonFormatError(u'Degrees must be an number. It\'s %s.', d)
257 spl = tmp.split(u"'", 1)
259 # no ' sign: ok only if there is nothing but the side after °
260 # we don't accept seconds if there is no minutes:
261 # It might be an entry mistake
266 raise LatLonFormatError(u'You must use the \' character between ° and %s.', data[-1])
272 raise LatLonFormatError(u'Minutes must be an number. It\'s %s.', m)
277 raise LatLonFormatError(u'You must use the " character between seconds and %s.', data[-1])
282 raise LatLonFormatError(u'Seconds must be an number. It\'s %s.', s)
283 data = side * ( d + m / 60 + s / 3600)
285 if data < -180 or data > 180:
286 raise LatLonFormatError(u'%s in not in -180..180 range', data)
289 #if __name__ == '__main__':
290 # for test in ('12:34:56:78',
292 # '1:2:3:abc:[bd:ef::]:45',
293 # '1:2:3:abc:[bd:ef:]:]:45'):
294 # print test, str_split_column_ipv6(test)