# Encoding: UTF-8 """Rewrite Markdown strings to use identifiers instead of names This is an unmaintained one-shot script, only included in the repo for reference. """ from functools import partial import sys import re from sqlalchemy.orm.exc import MultipleResultsFound from sqlalchemy.sql.expression import func from pokedex.db import connect, tables sanity_re = re.compile(ur"^[-A-Za-z0-9 é\[\]{}.%':;,×/()\"|–`—!*♂♀\\]$") # RE that matches anything that might look like a link fuzzy_link_re = re.compile(r""" \[ [^]]+ \] \{ [^}]+ \}""", re.VERBOSE) # Very specific RE that matches links that appear in our Markdown strings strict_link_re = re.compile(r""" \[ (?P<label> [-A-Za-z 0-9'.]{,30} ) \] \{ (?P<category> [a-z]{,20} ) ( : (?P<target> [A-Za-z 0-9]{,20} ) )? \} """, re.VERBOSE) english_id = 9 def is_md_col(column): return column.info.get('format') == 'markdown' manual_replacements = { ( u'Used in battle\n: Attempts to [catch]{mechanic} a wild Pok\xe9mon, using a catch rate of 1.5\xd7.\n\nThis item can only be used in the [Great Marsh]{location} or [Safari Zone]{location}.', u'[Safari Zone]{location}', ): 'in a Safari Zone', ( u'Used outside of battle\n: Transports the trainer to the last-entered dungeon entrance. Cannot be used outside, in buildings, or in [Distortion World]{location}, [Hall of Origin]{location}, [Spear Pillar]{location}, or [Turnback Cave]{location}.', u'[Hall of Origin]{location}', ): '[Hall of Origin]{location:hall-of-origin-1}', ( u'Give to the [Wingull]{pokemon} on [Route 13]{location}, along with [Gram 2]{item} and [Gram 3]{item}, to receive [TM89]{item}.', u'[Route 13]{location}', ): u'[Route 13]{location:unova-route-13}', ( u'Give to the [Wingull]{pokemon} on [Route 13]{location}, along with [Gram 1]{item} and [Gram 3]{item}, to receive [TM89]{item}.', u'[Route 13]{location}', ): u'[Route 13]{location:unova-route-13}', ( u'Give to the [Wingull]{pokemon} on [Route 13]{location}, along with [Gram 1]{item} and [Gram 2]{item}, to receive [TM89]{item}.', u'[Route 13]{location}', ): u'[Route 13]{location:unova-route-13}', ( u"Forms have different stats and movepools. In Generation III, Deoxys's form depends on the game: Normal Forme in Ruby and Sapphire, Attack Forme in FireRed, Defense Forme in LeafGreen, and Speed Forme in Emerald. In Generation IV, every form exists: form is preserved when transferring via [Pal Park]{location}, and meteorites in the southeast corner of [Veilstone City]{location} or at the west end of [Route 3]{location} can be used to switch between forms.", u'[Route 3]{location}', ): u'[Route 3]{location:kanto-route-13}', } def get_replacement(session, entire_text, matchobj): print "%-30s" % matchobj.group(0), label = matchobj.group('label') category = matchobj.group('category') target = matchobj.group('target') or label try: result = manual_replacements[entire_text, matchobj.group(0)] except KeyError: if category == 'mechanic': target = target.lower() else: query = None if category == 'item': table = tables.Item elif category == 'ability': table = tables.Ability elif category == 'move': table = tables.Move elif category == 'type': table = tables.Type elif category == 'pokemon': table = tables.Pokemon query = session.query(table).filter(tables.Pokemon.id < 10000) elif category == 'location': table = tables.Location else: print print repr(entire_text) print repr(matchobj.group(0)) raise ValueError('Category %s not implemented' % category) if not query: query = session.query(table) query = query.join(table.names_local) query = query.filter(func.lower(table.names_table.name) == target.lower()) try: thingy = query.one() target = thingy.identifier except: print print repr(entire_text) print repr(matchobj.group(0)) raise result = "[%s]{%s:%s}" % (label, category, target) print result return result def main(argv): session = connect() for cls in tables.mapped_classes: for translation_class in cls.translation_classes: columns = translation_class.__table__.c md_columns = [c for c in columns if c.info.get('format') == 'markdown'] if not md_columns: continue for row in session.query(translation_class): if row.local_language_id != english_id: continue for column in md_columns: markdown = getattr(row, column.name) if not markdown: continue text = unicode(markdown) # Make sure everything that remotely looks like a link is one links = fuzzy_link_re.findall(text) if not links: continue for link in links: assert strict_link_re.findall(link), [link] # Do the replacement replaced = strict_link_re.sub( partial(get_replacement, session, text), text, ) setattr(row, column.name, replaced) if argv and argv[0] == '--commit': session.commit() print 'Committed' else: print 'Run with --commit to commit changes' if __name__ == '__main__': main(sys.argv[1:])