[mwm.py] Review fixes and python3 support

This commit is contained in:
Ilya Zverev 2016-06-06 15:55:56 +03:00
parent 114ae06469
commit 8bcaac7b8e
3 changed files with 54 additions and 36 deletions

View file

@ -4,31 +4,33 @@ import json
from mwm import MWM
if len(sys.argv) < 2:
print 'Dumps some MWM structures.'
print 'Usage: {0} <country.mwm>'.format(sys.argv[0])
print('Dumps some MWM structures.')
print('Usage: {0} <country.mwm>'.format(sys.argv[0]))
sys.exit(1)
mwm = MWM(open(sys.argv[1], 'rb'))
mwm.read_types(os.path.join(os.path.dirname(sys.argv[0]), '..', '..', '..', 'data', 'types.txt'))
print 'Tags:'
tvv = sorted([(k, v[0], v[1]) for k, v in mwm.tags.iteritems()], key=lambda x: x[1])
print('Tags:')
tvv = sorted([(k, v[0], v[1]) for k, v in mwm.tags.items()], key=lambda x: x[1])
for tv in tvv:
print ' {0:<8}: offs {1:9} len {2:8}'.format(tv[0], tv[1], tv[2])
print 'Version:', mwm.read_version()
print 'Header:', mwm.read_header()
print 'Metadata count:', len(mwm.read_metadata())
print(' {0:<8}: offs {1:9} len {2:8}'.format(tv[0], tv[1], tv[2]))
v = mwm.read_version()
print('Format: {0}, version: {1}'.format(v['fmt'], v['version'].strftime('%Y-%m-%d %H:%M')))
print('Header: {0}'.format(mwm.read_header()))
print('Metadata count: {0}'.format(len(mwm.read_metadata())))
cross = mwm.read_crossmwm()
if cross:
print 'Outgoing points:', len(cross['out']), 'incoming:', len(cross['in'])
print 'Outgoing regions:', set(cross['neighbours'])
print('Outgoing points: {0}, incoming: {1}'.format(len(cross['out']), len(cross['in'])))
print('Outgoing regions: {0}'.format(set(cross['neighbours'])))
print 'Sample features:'
print('Sample features:')
# Print 5 random features ~10000 features apart
count = 5
probability = 1.0 / 1000
probability = 1.0 / 10000
for feature in mwm.iter_features():
if random.random() < probability:
print json.dumps(feature, ensure_ascii=False)
print(json.dumps(feature, ensure_ascii=False))
count -= 1
if count <= 0:
break

View file

@ -3,13 +3,17 @@ import sys, os.path, json
from mwm import MWM
if len(sys.argv) < 4:
print 'Finds features in an mwm file'
print 'Usage: {0} <country.mwm> <type> <string>'.format(sys.argv[0])
print 'Type: t for inside types, et for exact type, n for names'
print('Finds features in an mwm file based on a query')
print('Usage: {0} <country.mwm> <type> <string>'.format(sys.argv[0]))
print('')
print('Type:')
print(' t for inside types ("t hwtag" will find all hwtags-*)')
print(' et for exact type ("et shop" won\'t find shop-chemist)')
print(' n for names, case-sensitive ("n Starbucks" for all starbucks)')
sys.exit(1)
typ = sys.argv[2].lower()
find = sys.argv[3]
find = sys.argv[3].decode('utf-8')
mwm = MWM(open(sys.argv[1], 'rb'))
mwm.read_header()
@ -27,4 +31,4 @@ for feature in mwm.iter_features():
elif typ == 't' and find in t:
found = True
if found:
print json.dumps(feature, ensure_ascii=False)
print(json.dumps(feature, ensure_ascii=False))

View file

@ -46,7 +46,7 @@ class MWM:
cnt = self.read_varuint()
self.tags = {}
for i in range(cnt):
name = self.read_string(True)
name = self.read_string(plain=True)
offset = self.read_varuint()
length = self.read_varuint()
self.tags[name] = (offset, length)
@ -57,13 +57,13 @@ class MWM:
def seek_tag(self, tag):
self.f.seek(self.tags[tag][0])
def inside_tag(self, tag):
pos = self.tag_position(tag)
return pos >= 0 and pos < self.tags[tag][1]
def tag_position(self, tag):
def tag_offset(self, tag):
return self.f.tell() - self.tags[tag][0]
def inside_tag(self, tag):
pos = self.tag_offset(tag)
return pos >= 0 and pos < self.tags[tag][1]
def read_version(self):
"""Reads 'version' section."""
self.seek_tag('version')
@ -128,7 +128,7 @@ class MWM:
self.seek_tag('meta')
metadatar = {}
while self.inside_tag('meta'):
tag_pos = self.tag_position('meta')
tag_pos = self.tag_offset('meta')
fields = {}
if fmt >= 8:
sz = self.read_varuint()
@ -144,7 +144,7 @@ class MWM:
t = t & 0x7f
t = self.metadata[t] if t < len(self.metadata) else str(t)
l = self.read_uint(1)
fields[t] = self.f.read(l)
fields[t] = self.f.read(l).decode('utf-8')
if is_last:
break
@ -189,7 +189,7 @@ class MWM:
neighbours = []
for i in range(neighboursCount):
size = self.read_uint(4)
neighbours.append(self.f.read(size))
neighbours.append(self.f.read(size).decode('utf-8'))
return { 'in': incoming, 'out': outgoing, 'matrix': matrix, 'neighbours': neighbours }
class GeomType:
@ -314,9 +314,13 @@ class MWM:
b = self.f.read(1)
if not b:
return res
res |= (ord(b[0]) & 0x7F) << shift
try:
bc = ord(b)
except TypeError:
bc = b
res |= (bc & 0x7F) << shift
shift += 7
more = ord(b[0]) >= 0x80
more = bc >= 0x80
return res
def zigzag_decode(self, uint):
@ -353,6 +357,7 @@ class MWM:
return self.mwm_decode_delta(u, ref)
def to_4326(self, point):
"""Convert a point in maps.me-mercator CS to WGS-84 (EPSG:4326)."""
if self.coord_size is None:
raise Exception('Call read_header() first.')
merc_bounds = (-180.0, -180.0, 180.0, 180.0) # Xmin, Ymin, Xmax, Ymax
@ -374,9 +379,10 @@ class MWM:
pmax = self.to_4326(rmax)
return (pmin[0], pmin[1], pmax[0], pmax[1])
def read_string(self, plain=False):
def read_string(self, plain=False, decode=True):
length = self.read_varuint() + (0 if plain else 1)
return self.f.read(length)
s = self.f.read(length)
return s.decode('utf-8') if decode else s
def read_uint_array(self):
length = self.read_varuint()
@ -390,13 +396,16 @@ class MWM:
if sz & 1 != 0:
return str(sz >> 1)
sz = (sz >> 1) + 1
return self.f.read(sz)
return self.f.read(sz).decode('utf-8')
def read_multilang(self):
def find_multilang_next(s, i):
i += 1
while i < len(s):
c = struct.unpack('B', s[i])[0]
try:
c = ord(s[i])
except:
c = s[i]
if c & 0xC0 == 0x80:
break
if c & 0x80 == 0:
@ -416,13 +425,16 @@ class MWM:
i += 1
return i
s = self.read_string()
s = self.read_string(decode=False)
langs = {}
i = 0
while i < len(s):
n = find_multilang_next(s, i)
lng = struct.unpack('B', s[i])[0] & 0x3F
try:
lng = ord(s[i]) & 0x3F
except TypeError:
lng = s[i] & 0x3F
if lng < len(self.languages):
langs[self.languages[lng]] = s[i+1:n]
langs[self.languages[lng]] = s[i+1:n].decode('utf-8')
i = n
return langs