Python 2.5 compatibility

This commit is contained in:
a_magical_me 2010-04-25 00:14:29 -07:00
parent b91c813966
commit febfb239fb
5 changed files with 160 additions and 10 deletions

View file

@ -55,8 +55,8 @@ def get_session(options):
session = pokedex.db.connect(engine_uri) session = pokedex.db.connect(engine_uri)
if options.verbose: if options.verbose:
print "Connected to database {engine} (from {got_from})" \ print "Connected to database %(engine)s (from %(got_from)s)" \
.format(engine=session.bind.url, got_from=got_from) % dict(engine=session.bind.url, got_from=got_from)
return session return session
@ -75,8 +75,8 @@ def get_lookup(options, session=None, recreate=False):
index_dir, got_from = defaults.get_default_index_dir_with_origin() index_dir, got_from = defaults.get_default_index_dir_with_origin()
if options.verbose: if options.verbose:
print "Opened lookup index {index_dir} (from {got_from})" \ print "Opened lookup index %(index_dir)s (from %(got_from)s)" \
.format(index_dir=index_dir, got_from=got_from) % dict(index_dir=index_dir, got_from=got_from)
lookup = pokedex.lookup.PokedexLookup(index_dir, session=session) lookup = pokedex.lookup.PokedexLookup(index_dir, session=session)
@ -97,8 +97,8 @@ def get_csv_directory(options):
if csvdir is None: if csvdir is None:
csvdir, got_from = defaults.get_default_csv_dir_with_origin() csvdir, got_from = defaults.get_default_csv_dir_with_origin()
print "Using CSV directory {csvdir} (from {got_from})" \ print "Using CSV directory %(csvdir)s (from %(got_from)s)" \
.format(csvdir=csvdir, got_from=got_from) % dict(csvdir=csvdir, got_from=got_from)
return csvdir return csvdir

View file

@ -179,7 +179,7 @@ def load(session, tables=[], directory=None, drop_tables=False, verbose=False):
session.commit() session.commit()
new_rows[:] = [] new_rows[:] = []
progress = "{0}%".format(100 * csvfile.tell() // csvsize) progress = "%d%%" % (100 * csvfile.tell() // csvsize)
print_status(progress) print_status(progress)
for csvs in reader: for csvs in reader:

View file

@ -1,5 +1,4 @@
# encoding: utf8 # encoding: utf8
from collections import namedtuple
import os, os.path import os, os.path
import random import random
import re import re
@ -15,6 +14,8 @@ from whoosh.qparser import QueryParser
import whoosh.scoring import whoosh.scoring
import whoosh.spelling import whoosh.spelling
from pokedex.util import namedtuple
from pokedex.db import connect from pokedex.db import connect
import pokedex.db.tables as tables import pokedex.db.tables as tables
from pokedex.roomaji import romanize from pokedex.roomaji import romanize

View file

@ -8,7 +8,8 @@ Kudos to LordLandon for his pkmlib.py, from which this module was originally
derived. derived.
""" """
import itertools, struct import struct
from pokedex.util import permutations
def pokemon_prng(seed): def pokemon_prng(seed):
u"""Creates a generator that simulates the main Pokémon PRNG.""" u"""Creates a generator that simulates the main Pokémon PRNG."""
@ -79,7 +80,7 @@ class PokemonSave(object):
### Utility methods ### Utility methods
shuffle_orders = list( itertools.permutations(range(4)) ) shuffle_orders = list( permutations(range(4)) )
@classmethod @classmethod
def shuffle_chunks(cls, words, reverse=False): def shuffle_chunks(cls, words, reverse=False):

148
pokedex/util.py Normal file
View file

@ -0,0 +1,148 @@
"""Functions missing from Python 2.5"""
try:
from itertools import permutations
except ImportError:
# From the itertools documentation
def permutations(iterable, r=None):
# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
# permutations(range(3)) --> 012 021 102 120 201 210
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = range(n)
cycles = range(n, n-r, -1)
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
try:
from collections import namedtuple
except ImportError:
# http://code.activestate.com/recipes/500261-named-tuples/
from operator import itemgetter as _itemgetter
from keyword import iskeyword as _iskeyword
import sys as _sys
def namedtuple(typename, field_names, verbose=False, rename=False):
"""Returns a new subclass of tuple with named fields.
>>> Point = namedtuple('Point', 'x y')
>>> Point.__doc__ # docstring for the new class
'Point(x, y)'
>>> p = Point(11, y=22) # instantiate with positional args or keywords
>>> p[0] + p[1] # indexable like a plain tuple
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessable by name
33
>>> d = p._asdict() # convert to a dictionary
>>> d['x']
11
>>> Point(**d) # convert from a dictionary
Point(x=11, y=22)
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
Point(x=100, y=22)
"""
# Parse and validate the field names. Validation serves two purposes,
# generating informative error messages and preventing template injection attacks.
if isinstance(field_names, basestring):
field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
field_names = tuple(map(str, field_names))
if rename:
names = list(field_names)
seen = set()
for i, name in enumerate(names):
if (not min(c.isalnum() or c=='_' for c in name) or _iskeyword(name)
or not name or name[0].isdigit() or name.startswith('_')
or name in seen):
names[i] = '_%d' % i
seen.add(name)
field_names = tuple(names)
for name in (typename,) + field_names:
if not min(c.isalnum() or c=='_' for c in name):
raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
if _iskeyword(name):
raise ValueError('Type names and field names cannot be a keyword: %r' % name)
if name[0].isdigit():
raise ValueError('Type names and field names cannot start with a number: %r' % name)
seen_names = set()
for name in field_names:
if name.startswith('_') and not rename:
raise ValueError('Field names cannot start with an underscore: %r' % name)
if name in seen_names:
raise ValueError('Encountered duplicate field name: %r' % name)
seen_names.add(name)
# Create and fill-in the class template
numfields = len(field_names)
argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
reprtxt = ', '.join('%s=%%r' % name for name in field_names)
template = '''class %(typename)s(tuple):
'%(typename)s(%(argtxt)s)' \n
__slots__ = () \n
_fields = %(field_names)r \n
def __new__(_cls, %(argtxt)s):
return _tuple.__new__(_cls, (%(argtxt)s)) \n
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new %(typename)s object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != %(numfields)d:
raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
return result \n
def __repr__(self):
return '%(typename)s(%(reprtxt)s)' %% self \n
def _asdict(self):
'Return a new dict which maps field names to their values'
return dict(zip(self._fields, self)) \n
def _replace(_self, **kwds):
'Return a new %(typename)s object replacing specified fields with new values'
result = _self._make(map(kwds.pop, %(field_names)r, _self))
if kwds:
raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
return result \n
def __getnewargs__(self):
return tuple(self) \n\n''' % locals()
for i, name in enumerate(field_names):
template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
if verbose:
print template
# Execute the template string in a temporary namespace
namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
_property=property, _tuple=tuple)
try:
exec template in namespace
except SyntaxError, e:
raise SyntaxError(e.message + ':\n' + template)
result = namespace[typename]
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example) or sys._getframe is not
# defined for arguments greater than 0 (IronPython).
try:
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return result