Various python 3.x compatibility fixes.

This commit is contained in:
Ryan Leckey
2013-06-21 00:08:51 -07:00
parent 9b564433ef
commit 71da6ac902
9 changed files with 43 additions and 35 deletions

View File

@@ -1,9 +1,9 @@
language: python language: python
python: python:
- 2.5
- 2.6 - 2.6
- 2.7 - 2.7
- 3.3
install: install:
- pip install -q -e . --use-mirrors - pip install -q -e ".[test]" --use-mirrors
script: script:
- python setup.py test - python setup.py test

View File

@@ -1,6 +0,0 @@
-r requirements.txt
pytest==2.2.3
Pygments==1.2
Jinja2==2.3
docutils>=0.10
flexmock>=0.9.7

View File

@@ -1,3 +0,0 @@
SQLAlchemy>=0.8.0
phonenumbers>=5.4b1
colour==0.0.2

View File

@@ -4,7 +4,6 @@ SQLAlchemy-Utils
Various utility functions and custom data types for SQLAlchemy. Various utility functions and custom data types for SQLAlchemy.
""" """
from setuptools import setup, Command from setuptools import setup, Command
import subprocess import subprocess
@@ -22,6 +21,7 @@ class PyTest(Command):
errno = subprocess.call(['py.test']) errno = subprocess.call(['py.test'])
raise SystemExit(errno) raise SystemExit(errno)
setup( setup(
name='SQLAlchemy-Utils', name='SQLAlchemy-Utils',
version='0.13.3', version='0.13.3',
@@ -37,11 +37,26 @@ setup(
zip_safe=False, zip_safe=False,
include_package_data=True, include_package_data=True,
platforms='any', platforms='any',
install_requires=[ dependency_links=[
'SQLAlchemy>=0.8.0', # 5.6 supports python 3.x / pending release
'phonenumbers>=5.4b1', 'git+git://github.com/daviddrysdale/python-phonenumbers.git@python3'
'colour==0.0.2' '#egg=phonenumbers3k-5.6b1',
], ],
install_requires=[
'six',
'SQLAlchemy>=0.8.0',
'phonenumbers3k==5.6b1',
'colour>=0.0.3'
],
extras_require={
'test': [
'pytest==2.2.3',
'Pygments>=1.2',
'Jinja2>=2.3',
'docutils>=0.10',
'flexmock>=0.9.7',
]
},
cmdclass={'test': PyTest}, cmdclass={'test': PyTest},
classifiers=[ classifiers=[
'Environment :: Web Environment', 'Environment :: Web Environment',

View File

@@ -1,3 +1,4 @@
import six
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.engine import reflection from sqlalchemy.engine import reflection
from sqlalchemy.orm import object_session, mapperlib from sqlalchemy.orm import object_session, mapperlib
@@ -51,7 +52,7 @@ class Merger(object):
def raw_merge(self, session, table, old_values, new_values): def raw_merge(self, session, table, old_values, new_values):
conditions = [] conditions = []
for key, value in old_values.items(): for key, value in six.iteritems(old_values):
conditions.append(getattr(table.c, key) == value) conditions.append(getattr(table.c, key) == value)
sql = ( sql = (
table table

View File

@@ -1,3 +1,4 @@
import six
import sqlalchemy as sa import sqlalchemy as sa

View File

@@ -1,3 +1,4 @@
import six
import phonenumbers import phonenumbers
from colour import Color from colour import Color
from functools import wraps from functools import wraps
@@ -56,7 +57,7 @@ class PhoneNumber(phonenumbers.phonenumber.PhoneNumber):
return self.national return self.national
def __str__(self): def __str__(self):
return unicode(self).encode('utf-8') return six.text_type(self.national).encode('utf-8')
class PhoneNumberType(types.TypeDecorator): class PhoneNumberType(types.TypeDecorator):
@@ -95,7 +96,7 @@ class ColorType(types.TypeDecorator):
Changes Color objects to a string representation on the way in and Changes Color objects to a string representation on the way in and
changes them back to Color objects on the way out. changes them back to Color objects on the way out.
""" """
STORE_FORMAT = 'hex' STORE_FORMAT = u'hex'
impl = types.Unicode(20) impl = types.Unicode(20)
def __init__(self, max_length=20, *args, **kwargs): def __init__(self, max_length=20, *args, **kwargs):
@@ -104,7 +105,7 @@ class ColorType(types.TypeDecorator):
def process_bind_param(self, value, dialect): def process_bind_param(self, value, dialect):
if value: if value:
return getattr(value, self.STORE_FORMAT) return six.text_type(getattr(value, self.STORE_FORMAT))
return value return value
def process_result_value(self, value, dialect): def process_result_value(self, value, dialect):
@@ -125,22 +126,22 @@ class ScalarListException(Exception):
class ScalarListType(types.TypeDecorator): class ScalarListType(types.TypeDecorator):
impl = sa.UnicodeText() impl = sa.UnicodeText()
def __init__(self, coerce_func=unicode, separator=u','): def __init__(self, coerce_func=six.text_type, separator=u','):
self.separator = unicode(separator) self.separator = six.text_type(separator)
self.coerce_func = coerce_func self.coerce_func = coerce_func
def process_bind_param(self, value, dialect): def process_bind_param(self, value, dialect):
# Convert list of values to unicode separator-separated list # Convert list of values to unicode separator-separated list
# Example: [1, 2, 3, 4] -> u'1, 2, 3, 4' # Example: [1, 2, 3, 4] -> u'1, 2, 3, 4'
if value is not None: if value is not None:
if any(self.separator in unicode(item) for item in value): if any(self.separator in six.text_type(item) for item in value):
raise ScalarListException( raise ScalarListException(
"List values can't contain string '%s' (its being used as " "List values can't contain string '%s' (its being used as "
"separator. If you wish for scalar list values to contain " "separator. If you wish for scalar list values to contain "
"these strings, use a different separator string." "these strings, use a different separator string."
) )
return self.separator.join( return self.separator.join(
map(unicode, value) map(six.text_type, value)
) )
def process_result_value(self, value, dialect): def process_result_value(self, value, dialect):
@@ -148,9 +149,9 @@ class ScalarListType(types.TypeDecorator):
if value == u'': if value == u'':
return [] return []
# coerce each value # coerce each value
return map( return list(map(
self.coerce_func, value.split(self.separator) self.coerce_func, value.split(self.separator)
) ))
class EmailType(sa.types.TypeDecorator): class EmailType(sa.types.TypeDecorator):
@@ -181,7 +182,7 @@ class NumberRangeType(types.TypeDecorator):
def process_result_value(self, value, dialect): def process_result_value(self, value, dialect):
if value: if value:
if not isinstance(value, basestring): if not isinstance(value, six.string_types):
value = NumberRange.from_range_object(value) value = NumberRange.from_range_object(value)
else: else:
return NumberRange.from_normalized_str(value) return NumberRange.from_normalized_str(value)
@@ -189,7 +190,7 @@ class NumberRangeType(types.TypeDecorator):
def coercion_listener(self, target, value, oldvalue, initiator): def coercion_listener(self, target, value, oldvalue, initiator):
if value is not None and not isinstance(value, NumberRange): if value is not None and not isinstance(value, NumberRange):
if isinstance(value, basestring): if isinstance(value, six.string_types):
value = NumberRange.from_normalized_str(value) value = NumberRange.from_normalized_str(value)
else: else:
raise TypeError raise TypeError
@@ -252,7 +253,7 @@ class NumberRange(object):
min_value, max_value = map( min_value, max_value = map(
lambda a: int(a.strip()), values lambda a: int(a.strip()), values
) )
except ValueError, e: except ValueError as e:
raise NumberRangeException(e.message) raise NumberRangeException(e.message)
if value[0] == '(': if value[0] == '(':
@@ -274,8 +275,8 @@ class NumberRange(object):
min_value, max_value = map( min_value, max_value = map(
lambda a: int(a.strip()), values lambda a: int(a.strip()), values
) )
except ValueError, e: except ValueError as e:
raise NumberRangeException(e.message) raise NumberRangeException(str(e))
return cls(min_value, max_value) return cls(min_value, max_value)
@property @property

View File

@@ -20,9 +20,7 @@ def count_sql_calls(conn, cursor, statement, parameters, context, executemany):
class TestCase(object): class TestCase(object):
def setup_method(self, method): def setup_method(self, method):
self.engine = create_engine( self.engine = create_engine('sqlite:///:memory:')
'postgres://postgres@localhost/sqlalchemy_utils_test'
)
self.connection = self.engine.connect() self.connection = self.engine.connect()
self.Base = declarative_base() self.Base = declarative_base()

View File

@@ -1,3 +1,4 @@
import six
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy_utils import ScalarListType from sqlalchemy_utils import ScalarListType
from pytest import raises from pytest import raises
@@ -33,7 +34,7 @@ class TestScalarUnicodeList(TestCase):
class User(self.Base): class User(self.Base):
__tablename__ = 'user' __tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True) id = sa.Column(sa.Integer, primary_key=True)
some_list = sa.Column(ScalarListType(unicode)) some_list = sa.Column(ScalarListType(six.text_type))
def __repr__(self): def __repr__(self):
return 'User(%r)' % self.id return 'User(%r)' % self.id