Skip to content

Commit

Permalink
Python 3 fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjoes committed Jun 13, 2013
1 parent f689439 commit 53c68c7
Show file tree
Hide file tree
Showing 25 changed files with 149 additions and 71 deletions.
10 changes: 5 additions & 5 deletions examples/sqla/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class User(db.Model):
email = db.Column(db.String(120), unique=True)

# Required for administrative interface
def __unicode__(self):
def __str__(self):
return self.username


Expand All @@ -48,15 +48,15 @@ class Post(db.Model):

tags = db.relationship('Tag', secondary=post_tags_table)

def __unicode__(self):
def __str__(self):
return self.title


class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))

def __unicode__(self):
def __str__(self):
return self.name


Expand All @@ -69,7 +69,7 @@ class UserInfo(db.Model):
user_id = db.Column(db.Integer(), db.ForeignKey(User.id))
user = db.relationship(User, backref='info')

def __unicode__(self):
def __str__(self):
return '%s - %s' % (self.key, self.value)


Expand All @@ -79,7 +79,7 @@ class Tree(db.Model):
parent_id = db.Column(db.Integer, db.ForeignKey('tree.id'))
parent = db.relationship('Tree', remote_side=[id], backref='children')

def __unicode__(self):
def __str__(self):
return self.name


Expand Down
65 changes: 65 additions & 0 deletions flask_admin/_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
"""
flask.ext.admin._compat
~~~~~~~~~~~~~~~~~~~~~~~
Some py2/py3 compatibility support based on a stripped down
version of six so we don't have to depend on a specific version
of it.
:copyright: (c) 2013 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import sys

PY2 = sys.version_info[0] == 2


if not PY2:
text_type = str
string_types = (str,)
integer_types = (int, )

iterkeys = lambda d: iter(d.keys())
itervalues = lambda d: iter(d.values())
iteritems = lambda d: iter(d.items())

def as_unicode(text):
return str(text)

from functools import reduce
else:
unicode_type = unicode
text_type = unicode
string_types = (str, unicode)
integer_types = (int, long)

iterkeys = lambda d: d.iterkeys()
itervalues = lambda d: d.itervalues()
iteritems = lambda d: d.iteritems()

def as_unicode(text):
return unicode(text)

reduce = __builtin__.reduce


def with_metaclass(meta, *bases):
# This requires a bit of explanation: the basic idea is to make a
# dummy metaclass for one level of class instantiation that replaces
# itself with the actual metaclass. Because of internal type checks
# we also need to make sure that we downgrade the custom metaclass
# for one level to something closer to type (that's why __call__ and
# __init__ comes back from type etc.).
#
# This has the advantage over six.with_metaclass in that it does not
# introduce dummy classes into the final MRO.
class metaclass(meta):
__call__ = type.__call__
__init__ = type.__init__

def __new__(cls, name, this_bases, d):
if this_bases is None:
return type.__new__(cls, name, (), d)
return meta(name, bases, d)
return metaclass('temporary_class', None, {})
8 changes: 4 additions & 4 deletions flask_admin/actions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask import request, url_for, redirect


from flask.ext.admin.tools import get_dict_attr
from flask.ext.admin import tools, _compat


def action(name, text, confirmation=None):
Expand Down Expand Up @@ -53,7 +53,7 @@ def init_actions(self):
self._actions_data = {}

for p in dir(self):
attr = get_dict_attr(self, p)
attr = tools.get_dict_attr(self, p)

if hasattr(attr, '_action'):
name, text, desc = attr._action
Expand Down Expand Up @@ -85,12 +85,12 @@ def get_actions_list(self):
name, text = act

if self.is_action_allowed(name):
text = unicode(text)
text = _compat.as_unicode(text)

actions.append((name, text))
confirmation = self._actions_data[name][2]
if confirmation:
actions_confirmation[name] = unicode(confirmation)
actions_confirmation[name] = _compat.text_type(confirmation)

return actions, actions_confirmation

Expand Down
5 changes: 2 additions & 3 deletions flask_admin/base.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from functools import wraps
from re import sub
import six

from flask import Blueprint, render_template, url_for, abort, g
from flask.ext.admin import babel
from flask.ext.admin import babel, _compat
from flask.ext.admin import helpers as h


Expand Down Expand Up @@ -95,7 +94,7 @@ class BaseMeta(object):
pass


class BaseView(six.with_metaclass(AdminViewMeta, BaseMeta)):
class BaseView(_compat.with_metaclass(AdminViewMeta, BaseMeta)):
"""
Base administrative view.
Expand Down
9 changes: 5 additions & 4 deletions flask_admin/contrib/mongoengine/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from flask.ext.admin.babel import gettext, ngettext, lazy_gettext
from flask.ext.admin.model import BaseModelView
from flask.ext.admin import _compat

import mongoengine
from bson.objectid import ObjectId
Expand Down Expand Up @@ -115,7 +116,7 @@ def _get_model_fields(self, model=None):
if model is None:
model = self.model

return sorted(model._fields.iteritems(), key=lambda n: n[1].creation_counter)
return sorted(_compat.iteritems(model._fields), key=lambda n: n[1].creation_counter)

def scaffold_pk(self):
# MongoEngine models have predefined 'id' as a key
Expand Down Expand Up @@ -171,7 +172,7 @@ def init_search(self):
"""
if self.column_searchable_list:
for p in self.column_searchable_list:
if isinstance(p, basestring):
if isinstance(p, _compat.string_types):
p = self.model._fields.get(p)

if p is None:
Expand All @@ -195,7 +196,7 @@ def scaffold_filters(self, name):
:param name:
Either field name or field instance
"""
if isinstance(name, basestring):
if isinstance(name, _compat.string_types):
attr = self.model._fields.get(name)
else:
attr = name
Expand All @@ -206,7 +207,7 @@ def scaffold_filters(self, name):
# Find name
visible_name = None

if not isinstance(name, basestring):
if not isinstance(name, _compat.string_types):
visible_name = self.get_column_name(attr.name)

if not visible_name:
Expand Down
4 changes: 2 additions & 2 deletions flask_admin/contrib/peeweemodel/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from wtfpeewee.orm import ModelConverter, model_form

from flask.ext.admin import form
from flask.ext.admin import form, _compat
from flask.ext.admin.model.form import InlineFormAdmin, InlineModelConverterBase
from flask.ext.admin.model.fields import InlineModelFormField, InlineFieldList

Expand Down Expand Up @@ -164,6 +164,6 @@ def contribute(self, converter, model, form_class, inline_model):


def save_inline(form, model):
for _, f in form._fields.iteritems():
for _, f in _compat(form._fields):
if f.type == 'InlineModelFormList':
f.save_related(model)
10 changes: 5 additions & 5 deletions flask_admin/contrib/peeweemodel/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from flask import flash

from flask.ext.admin import form
from flask.ext.admin import form, _compat
from flask.ext.admin.babel import gettext, ngettext, lazy_gettext
from flask.ext.admin.model import BaseModelView

Expand Down Expand Up @@ -173,7 +173,7 @@ def scaffold_sortable_columns(self):
def init_search(self):
if self.column_searchable_list:
for p in self.column_searchable_list:
if isinstance(p, basestring):
if isinstance(p, _compat.string_types):
p = getattr(self.model, p)

field_type = type(p)
Expand All @@ -189,7 +189,7 @@ def init_search(self):
return bool(self._search_fields)

def scaffold_filters(self, name):
if isinstance(name, basestring):
if isinstance(name, _compat.string_types):
attr = getattr(self.model, name, None)
else:
attr = name
Expand All @@ -202,7 +202,7 @@ def scaffold_filters(self, name):
visible_name = '%s / %s' % (self.get_column_name(attr.model_class.__name__),
self.get_column_name(attr.name))
else:
if not isinstance(name, basestring):
if not isinstance(name, _compat.string_types):
visible_name = self.get_column_name(attr.name)
else:
visible_name = self.get_column_name(name)
Expand Down Expand Up @@ -253,7 +253,7 @@ def _handle_join(self, query, field, joins):
return query

def _order_by(self, query, joins, sort_field, sort_desc):
if isinstance(sort_field, basestring):
if isinstance(sort_field, _compat.string_types):
field = getattr(self.model, sort_field)
query = query.order_by(field.desc() if sort_desc else field.asc())
elif isinstance(sort_field, Field):
Expand Down
4 changes: 2 additions & 2 deletions flask_admin/contrib/pymongo/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from bson.errors import InvalidId

from flask import flash
from jinja2 import contextfunction

from flask.ext.admin import _compat
from flask.ext.admin.babel import gettext, ngettext, lazy_gettext
from flask.ext.admin.model import BaseModelView
from flask.ext.admin.actions import action
Expand Down Expand Up @@ -92,7 +92,7 @@ def init_search(self):
"""
if self.column_searchable_list:
for p in self.column_searchable_list:
if not isinstance(p, basestring):
if not isinstance(p, _compat.string_types):
raise ValueError('Expected string')

# TODO: Validation?
Expand Down
11 changes: 6 additions & 5 deletions flask_admin/contrib/sqlamodel/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from wtforms.validators import ValidationError

from .tools import get_primary_key
from flask.ext.admin import _compat
from flask.ext.admin.model.fields import InlineFieldList, InlineModelFormField


Expand Down Expand Up @@ -63,14 +64,14 @@ def __init__(self, label=None, validators=None, query_factory=None,

if get_pk is None:
if not has_identity_key:
raise Exception('The sqlalchemy identity_key function could not be imported.')
raise Exception(u'The sqlalchemy identity_key function could not be imported.')
self.get_pk = get_pk_from_identity
else:
self.get_pk = get_pk

if get_label is None:
self.get_label = lambda x: x
elif isinstance(get_label, basestring):
elif isinstance(get_label, _compat.string_types):
self.get_label = operator.attrgetter(get_label)
else:
self.get_label = get_label
Expand Down Expand Up @@ -98,7 +99,7 @@ def _get_object_list(self):
if self._object_list is None:
query = self.query or self.query_factory()
get_pk = self.get_pk
self._object_list = list((unicode(get_pk(obj)), obj) for obj in query)
self._object_list = [(_compat.as_unicode(get_pk(obj)), obj) for obj in query]
return self._object_list

def iter_choices(self):
Expand Down Expand Up @@ -177,7 +178,7 @@ def pre_validate(self, form):
obj_list = list(x[1] for x in self._get_object_list())
for v in self.data:
if v not in obj_list:
raise ValidationError(self.gettext('Not a valid choice'))
raise ValidationError(self.gettext(u'Not a valid choice'))


class InlineModelFormList(InlineFieldList):
Expand Down Expand Up @@ -238,4 +239,4 @@ def populate_obj(self, obj, name):
def get_pk_from_identity(obj):
# TODO: Remove me
cls, key = identity_key(instance=obj)
return u':'.join(unicode(x) for x in key)
return u':'.join(_compat.as_unicode(x) for x in key)
3 changes: 2 additions & 1 deletion flask_admin/contrib/sqlamodel/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def __init__(self, db_session, model, column, message=None):
def __call__(self, form, field):
try:
obj = (self.db_session.query(self.model)
.filter(self.column == field.data).one())
.filter(self.column == field.data)
.one())

if not hasattr(form, '_obj') or not form._obj == obj:
if self.message is None:
Expand Down
Loading

0 comments on commit 53c68c7

Please sign in to comment.