* mwlib http://code.pediapress.com/wiki/wiki
"""
import re
+import xml.etree.ElementTree
def find_template(wikitext, template_title):
parts.append(key + equal_char + named_param_values[i])
return pipe_char.join(parts) + end_char
+
+def parse_googlemap(wikitext):
+ """Parses the (unicode) u'<googlemap ...>content</googlemap>' of the googlemap extension
+ out of a page. If wikitext does not contain the googlemaps extension text None is returned.
+ If the googlemap contains invalid formatted lines, a RuntimeError is raised.
+
+ :param wikitext: wikitext containing the template. Example:
+
+ wikitext = '''
+ <googlemap version="0.9" lat="47.113291" lon="11.272337" zoom="15">
+ (Parkplatz)47.114958,11.266026
+ Parkplatz
+
+ (Gasthaus) 47.114715, 11.266262, Alt Bärnbad (Gasthaus)
+ 6#FF014E9A
+ 47.114715,11.266262
+ 47.114135,11.268381
+ 47.113421,11.269322
+ 47.11277,11.269979
+ 47.112408,11.271119
+ </googlemap>
+ '''
+ :returns: the tuple (center, zoom, coords, paths).
+ center is the tuple (lon, lat) of the google maps or (None, None) if not provided
+ zoom is the google zoom level as integer or None if not provided
+ coords is a list of (lon, lat, symbol, title) tuples.
+ paths is a list of (style, coords) tuples.
+ coords is again a list of (lot, lat, symbol, title) tuples."""
+
+ def is_coord(line):
+ """Returns True if the line contains a coordinate."""
+ match = re.search('[0-9]{1,2}\.[0-9]+, ?[0-9]{1,2}\.[0-9]+', line)
+ return not match is None
+
+ def is_path(line):
+ """Returns True if the line contains a path style definition."""
+ match = re.match('[0-9]#[0-9a-fA-F]{8}', line)
+ return not match is None
+
+ def parse_coord(line):
+ """Returns (lon, lat, symbol, title). If symbol or text is not present, None is returned."""
+ match = re.match(u'\(([^)]+)\) ?([0-9]{1,2}\.[0-9]+), ?([0-9]{1,2}\.[0-9]+),(.*)', line)
+ if not match is None: return (float(match.group(3)), float(match.group(2)), match.group(1), match.group(4))
+ match = re.match(u'\(([^)]+)\) ?([0-9]{1,2}\.[0-9]+), ?([0-9]{1,2}\.[0-9]+)', line)
+ if not match is None: return (float(match.group(3)), float(match.group(2)), match.group(1), None)
+ match = re.match(u'([0-9]{1,2}\.[0-9]+), ?([0-9]{1,2}\.[0-9]+),(.*)', line)
+ if not match is None: return (float(match.group(2)), float(match.group(1)), None, match.group(3))
+ match = re.match(u'([0-9]{1,2}\.[0-9]+), ?([0-9]{1,2}\.[0-9]+)', line)
+ if not match is None: return (float(match.group(2)), float(match.group(1)), None, None)
+ return RuntimeError(u'Could not parse line ' + line)
+
+ regexp = re.compile(u"(<googlemap[^>]*>)(.*)(</googlemap>)", re.DOTALL)
+ match = regexp.search(wikitext)
+ if match is None: return None
+ content = match.group(2)
+ gm = xml.etree.ElementTree.XML((match.group(1)+match.group(3)).encode('UTF8'))
+ zoom = gm.get('zoom')
+ lon = gm.get('lon')
+ lat = gm.get('lat')
+ if not zoom is None: zoom = int(zoom)
+ if not lon is None: lon = float(lon)
+ if not lat is None: lat = float(lat)
+ center = (lon, lat)
+
+ coords = []
+ paths = []
+ lines = content.split("\n")
+ i = 0
+ while i < len(lines):
+ line = lines[i].strip()
+ i += 1
+
+ # Skip whitespace
+ if len(line) == 0: continue
+
+ # Handle a path
+ if is_path(line):
+ match = re.match(u'([0-9]#[0-9a-fA-F]{8})', line)
+ style = match.group(1)
+ local_coords = []
+ while i < len(lines):
+ line = lines[i].strip()
+ i += 1
+ if is_path(line):
+ i -= 1
+ break
+ if is_coord(line):
+ lon, lat, symbol, title = parse_coord(line)
+ local_coords.append((lon, lat, symbol, title))
+ paths.append((style, local_coords))
+ continue
+
+ # Handle a coordinate
+ if is_coord(line):
+ lon, lat, symbol, title = parse_coord(line)
+ coords.append((lon, lat, symbol, title))
+ while i < len(lines):
+ line = lines[i].strip()
+ i += 1
+ if is_path(line) or is_coord(line):
+ i -= 1
+ break
+ continue
+
+ raise RuntimeError(u'Unknown line syntax: ' + line)
+ return (center, zoom, coords, paths)
+
from sqlalchemy import schema
from sqlalchemy.sql import select
import formencode
-from wrpylib import mwdb, wrmwdb, wrmwmarkup
+from wrpylib import mwdb, wrmwdb, mwmarkup, wrmwmarkup
class UpdateCacheError(RuntimeError):
insert_row(connection, rowlist)
transaction.commit()
+
+def update_wrmapcache(connection):
+ """Updates the wrmappointcache and wrmappathcache tables from the wiki. If convert errors occur, an UpdateCacheError exception
+ is raised. No other exception type should be raised under normal circumstances.
+
+ >>> from sqlalchemy.engine import create_engine
+ >>> engine = create_engine('mysql://philipp@localhost:3306/winterrodeln_wiki?charset=utf8&use_unicode=0')
+ >>> update_wrmapcache(engine.connect())
+ """
+ metadata = schema.MetaData()
+ page = mwdb.page_table(metadata)
+ categorylinks = mwdb.categorylinks_table(metadata)
+ revision = mwdb.revision_table(metadata)
+ text = mwdb.text_table(metadata)
+
+ transaction = connection.begin()
+
+ # Query all sledruns
+ q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to==u'Rodelbahn'))
+ sledrun_pages = connection.execute(q)
+ # Original SQL:
+ # sql = u"select page_id, rev_id, old_id, page_title, old_text, 'In_Arbeit' in (select cl_to from categorylinks where cl_from=page_id) as under_construction from page, revision, text, categorylinks where page_latest=rev_id and old_id=rev_text_id and cl_from=page_id and cl_to='Rodelbahn' order by page_title"
+
+ # Delete all existing entries in wrmappointcache
+ # We rely on transactions MySQL InnoDB
+ connection.execute('delete from wrmappointcache')
+ connection.execute('delete from wrmappathcache')
+
+ # Refill wrmappointcache and wrmappathcache tables
+ for sledrun_page in sledrun_pages:
+ try:
+ result = mwmarkup.parse_googlemap(sledrun_page.old_text)
+ if not result is None:
+ center, zoom, coords, paths = result
+ for coord in coords:
+ lon, lat, point_type, label = coord
+ point_types = {u'Gasthaus': u'hut', u'Haltestelle': u'busstop', u'Parkplatz': u'carpark', u'Achtung': u'warning'}
+ if not point_type is None:
+ if not point_types.has_key(point_type): raise RuntimeError('Unknown point type {0}'.format(point_type))
+ point_type = point_types[point_type]
+ sql = 'insert into wrmappointcache (page_id, type, point, label) values (%s, %s, POINT(%s, %s), %s)'
+ connection.execute(sql, (sledrun_page.page_id, point_type, lon, lat, None))
+ except RuntimeError as e:
+ error_msg = u"Error at sledrun '{0}': {1}".format(sledrun_page.page_title, unicode(e))
+ transaction.rollback()
+ raise UpdateCacheError(error_msg, sledrun_page.page_title, e)
+ transaction.commit()