2 # -*- coding: iso-8859-15 -*-
5 """Contains functions that maintain/update the cache tables."""
6 from xml.etree import ElementTree
7 from sqlalchemy import schema
8 from sqlalchemy.sql import select
10 from wrpylib import mwdb, wrmwdb, mwmarkup, wrmwmarkup
13 class UpdateCacheError(RuntimeError):
17 def update_wrsledruncache(connection):
18 """Updates the wrsledruncache table from the wiki. If convert errors occur, an UpdateCacheError exception
19 is raised. No other exception type should be raised under normal circumstances.
21 >>> from sqlalchemy.engine import create_engine
22 >>> engine = create_engine('mysql://philipp@localhost:3306/winterrodeln_wiki?charset=utf8&use_unicode=0')
23 >>> update_wrsledruncache(engine.connect())
25 metadata = schema.MetaData()
26 wrsledruncache = wrmwdb.wrsledruncache_table(metadata)
27 page = mwdb.page_table(metadata)
28 categorylinks = mwdb.categorylinks_table(metadata)
29 revision = mwdb.revision_table(metadata)
30 text = mwdb.text_table(metadata)
32 transaction = connection.begin()
35 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'))
36 sledrun_pages = connection.execute(q)
38 # 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"
40 # Delete all existing entries in wrsledruncache
41 # We rely on transactions MySQL InnoDB
42 connection.execute(wrsledruncache.delete())
44 # Refill wrsledruncache table
45 for sledrun_page in sledrun_pages:
47 start, end, sledrun = wrmwmarkup.rodelbahnbox_to_sledrun(sledrun_page.old_text)
48 sledrun.page_id = sledrun_page.page_id
49 sledrun.page_title = sledrun_page.page_title
50 sledrun.under_construction = connection.execute(select([categorylinks], (categorylinks.c.cl_from==sledrun_page.page_id) & (categorylinks.c.cl_to == u'In_Arbeit')).alias('x').count()).fetchone()[0] > 0 # It would be better to do this in the query above
51 connection.execute(wrsledruncache.insert(sledrun.__dict__))
52 except (RuntimeError, formencode.Invalid) as e:
53 transaction.rollback()
54 error_msg = u"Error at sled run '{0}': {1}".format(sledrun_page.page_title, unicode(e))
55 raise UpdateCacheError(error_msg, sledrun_page.page_title, e)
59 def update_wrinncache(connection):
60 """Updates the wrinncache table from the wiki. If convert errors occur, an UpdateCacheError exception
61 is raised. No other exception type should be raised under normal circumstances.
63 >>> from sqlalchemy.engine import create_engine
64 >>> engine = create_engine('mysql://philipp@localhost:3306/winterrodeln_wiki?charset=utf8&use_unicode=0')
65 >>> update_wrinncache(engine.connect())
67 metadata = schema.MetaData()
68 wrinncache = wrmwdb.wrinncache_table(metadata)
69 page = mwdb.page_table(metadata)
70 categorylinks = mwdb.categorylinks_table(metadata)
71 revision = mwdb.revision_table(metadata)
72 text = mwdb.text_table(metadata)
74 transaction = connection.begin()
77 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'Gasthaus'))
78 inn_pages = connection.execute(q)
80 # Delete all existing entries in wrinncache
81 # We rely on transactions MySQL InnoDB
82 connection.execute(wrinncache.delete())
84 # Refill wrinncache table
85 for inn_page in inn_pages:
87 start, end, inn = wrmwmarkup.gasthausbox_to_inn(inn_page.old_text)
88 inn.page_id = inn_page.page_id
89 inn.page_title = inn_page.page_title
90 inn.under_construction = connection.execute(select([categorylinks], (categorylinks.c.cl_from==inn_page.page_id) & (categorylinks.c.cl_to == u'In_Arbeit')).alias('x').count()).fetchone()[0] > 0 # It would be better to do this in the query above
91 connection.execute(wrinncache.insert(inn.__dict__))
92 except (RuntimeError, formencode.Invalid) as e:
93 transaction.rollback()
94 error_msg = u"Error as inn '{0}': {1}".format(inn_page.page_title, unicode(e))
95 raise UpdateCacheError(error_msg, inn_page.page_title, e)
99 def update_wrreportcache(connection, page_id=None):
100 """Updates the wrreportcache table.
101 :param connection: sqlalchemy connection
102 :param page_id: Updates only the reportcache table for the sledrun described on the Winterrodeln wiki page
103 with the specified page_id. Use None for this parameter to update the whole table.
105 >>> from sqlalchemy.engine import create_engine
106 >>> engine = create_engine('mysql://philipp@localhost:3306/winterrodeln_wiki?charset=utf8&use_unicode=1')
107 >>> update_wrreportcache(engine.connect())
109 metadata = schema.MetaData()
110 wrreport = wrmwdb.wrreport_table(metadata)
111 wrreportcache = wrmwdb.wrreportcache_table(metadata)
112 transaction = connection.begin()
114 # Delte the datasets we are going to update
115 sql_del = wrreportcache.delete()
116 if not page_id is None: sql_del = sql_del.where(wrreportcache.c.page_id == page_id)
117 connection.execute(sql_del)
119 def insert_row(connection, rowlist):
120 if len(rowlist) == 0: return
122 reports_xml = ElementTree.Element('reports')
124 report_xml = ElementTree.SubElement(reports_xml, 'report')
125 report_xml.set('report_id', unicode(row.report_id))
126 report_xml.set('date_report', unicode(row.report_date_report))
127 report_xml.set('condition', unicode(row.report_condition))
128 report_xml.set('author_name', unicode(row.report_author_name))
129 report_xml.set('author_username', unicode(row.report_author_username))
130 report_xml.text = unicode(row.report_description)
131 reports_xml.set('page_id', unicode(row.page_id))
132 reports_xml.set('page_title', row.page_title)
133 reports_xml = unicode(ElementTree.tostring(reports_xml, 'utf8'), 'utf8') # there is not ElementTree.tounicode())
134 # Insert the report(s)
135 row = dict(rowlist[0])
136 row['reports_xml'] = reports_xml
137 connection.execute(wrreportcache.insert(values=row))
139 # Select the rows to update
140 sql = 'select page_id, page_title, wrreport.id as report_id, date_report as report_date_report, `condition` as report_condition, description as report_description, author_name as report_author_name, if(author_userid is null, null, author_username) as report_author_username from wrreport where {0}`condition` is not null and date_invalid > now() and delete_date is null order by page_id, date_report desc, date_entry desc'.format('' if page_id is None else 'page_id={0} and '.format(page_id))
141 cursor = connection.execute(sql)
145 if row.page_id != page_id:
146 insert_row(connection, rowlist)
147 page_id = row.page_id
150 insert_row(connection, rowlist)
154 def update_wrmapcache(connection):
155 """Updates the wrmappointcache and wrmappathcache tables from the wiki. If convert errors occur, an UpdateCacheError exception
156 is raised. No other exception type should be raised under normal circumstances.
158 >>> from sqlalchemy.engine import create_engine
159 >>> engine = create_engine('mysql://philipp@localhost:3306/winterrodeln_wiki?charset=utf8&use_unicode=0')
160 >>> update_wrmapcache(engine.connect())
162 metadata = schema.MetaData()
163 page = mwdb.page_table(metadata)
164 categorylinks = mwdb.categorylinks_table(metadata)
165 revision = mwdb.revision_table(metadata)
166 text = mwdb.text_table(metadata)
168 transaction = connection.begin()
171 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'))
172 sledrun_pages = connection.execute(q)
174 # 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"
176 # Delete all existing entries in wrmappointcache
177 # We rely on transactions MySQL InnoDB
178 connection.execute('delete from wrmappointcache')
179 connection.execute('delete from wrmappathcache')
181 # Refill wrmappointcache and wrmappathcache tables
182 for sledrun_page in sledrun_pages:
184 result = mwmarkup.parse_googlemap(sledrun_page.old_text)
185 if not result is None:
186 center, zoom, coords, paths = result
189 lon, lat, point_type, label = coord
190 point_types = {u'Gasthaus': u'hut', u'Haltestelle': u'busstop', u'Parkplatz': u'carpark', u'Achtung': u'warning'}
191 if not point_type is None:
192 if not point_types.has_key(point_type): raise RuntimeError(u'Unknown point type {0}'.format(point_type))
193 point_type = point_types[point_type]
194 sql = u'insert into wrmappointcache (page_id, type, point, label) values (%s, %s, POINT(%s, %s), %s)'
195 connection.execute(sql, (sledrun_page.page_id, point_type, lon, lat, None))
197 for path_type, coords in paths:
198 path_type = path_type.lower()
199 path_types = {u'6#ff014e9a': u'sledrun', u'6#ffe98401': u'walkup', u'6#ff7f7fff': u'alternative', u'3#ff000000': u'lift'}
200 if not path_types.has_key(path_type): raise RuntimeError(u'Unknown path type {0}'.format(path_type))
201 path_type = path_types[path_type]
202 path = u", ".join(["{0} {1}".format(lon, lat) for lon, lat, symbol, title in coords])
203 path = u'LineString({0})'.format(path)
204 sql = u'insert into wrmappathcache (path, page_id, type) values (GeomFromText(%s), %s, %s)'
205 connection.execute(sql, (path, sledrun_page.page_id, path_type))
206 except RuntimeError as e:
207 error_msg = u"Error at sledrun '{0}': {1}".format(sledrun_page.page_title, unicode(e))
208 transaction.rollback()
209 raise UpdateCacheError(error_msg, sledrun_page.page_title, e)