Просмотр исходного кода

Merge pull request #69 from sh4nks/py3-compat

Python3 compatibility
Peter Justin 10 лет назад
Родитель
Сommit
4361fd9cb2

+ 1 - 0
.travis.yml

@@ -1,6 +1,7 @@
 language: python
 python:
   - "2.7"
+  - "3.3"
 # command to install dependencies
 install:
   - "pip install -r requirements.txt"

+ 2 - 1
AUTHORS

@@ -9,4 +9,5 @@ contributors:
 
 # Contributors
 
-* None! Be the first :)
+* CasperVg
+* Feel free to join! :)

+ 29 - 0
flaskbb/_compat.py

@@ -0,0 +1,29 @@
+"""
+Look here for more information:
+https://github.com/mitsuhiko/flask/blob/master/flask/_compat.py
+"""
+
+import sys
+
+PY2 = sys.version_info[0] == 2
+
+if not PY2:     # pragma: no cover
+    text_type = str
+    string_types = (str,)
+    integer_types = (int, )
+    intern_method = sys.intern
+    range_method = range
+    iterkeys = lambda d: iter(d.keys())
+    itervalues = lambda d: iter(d.values())
+    iteritems = lambda d: iter(d.items())
+    max_integer = sys.maxsize
+else:           # pragma: no cover
+    text_type = unicode
+    string_types = (str, unicode)
+    integer_types = (int, long)
+    intern_method = intern
+    range_method = xrange
+    iterkeys = lambda d: d.iterkeys()
+    itervalues = lambda d: d.itervalues()
+    iteritems = lambda d: d.iteritems()
+    max_integer = sys.maxint

+ 2 - 2
flaskbb/app.py

@@ -26,7 +26,7 @@ from flaskbb.management.views import management
 from flaskbb.forum.views import forum
 from flaskbb.forum.models import Post, Topic, Category, Forum
 # extensions
-from flaskbb.extensions import db, login_manager, mail, cache, redis, \
+from flaskbb.extensions import db, login_manager, mail, cache, redis_store, \
     debugtoolbar, migrate, themes, plugin_manager
 from flask.ext.whooshalchemy import whoosh_index
 # various helpers
@@ -100,7 +100,7 @@ def configure_extensions(app):
     themes.init_themes(app, app_identifier="flaskbb")
 
     # Flask-And-Redis
-    redis.init_app(app)
+    redis_store.init_app(app)
 
     # Flask-WhooshAlchemy
     with app.app_context():

+ 3 - 4
flaskbb/configs/default.py

@@ -79,11 +79,10 @@ class DefaultConfig(object):
     # Where to logger should send the emails to
     ADMINS = ["admin@example.org"]
 
-    ## Flask-And-Redis
+    # Flask-Redis
     REDIS_ENABLED = False
-    REDIS_HOST = 'localhost'
-    REDIS_PORT = 6379
-    REDIS_DB = 0
+    REDIS_URL = "redis://:password@localhost:6379"
+    REDIS_DATABASE = 0
 
     FORUM_URL_PREFIX = ""
     USER_URL_PREFIX = "/user"

+ 3 - 4
flaskbb/configs/production.py.example

@@ -80,11 +80,10 @@ class ProductionConfig(DefaultConfig):
     INFO_LOG = "info.log"
     ERROR_LOG = "error.log"
 
-    # Redis
+    # Flask-Redis
     REDIS_ENABLED = False
-    REDIS_HOST = 'localhost'
-    REDIS_PORT = 6379
-    REDIS_DB = 0
+    REDIS_URL = "redis://:password@localhost:6379"
+    REDIS_DATABASE = 0
 
     # URL Prefixes.
     FORUM_URL_PREFIX = ""

+ 1 - 1
flaskbb/extensions.py

@@ -32,7 +32,7 @@ mail = Mail()
 cache = Cache()
 
 # Redis
-redis = Redis()
+redis_store = Redis()
 
 # Debugtoolbar
 debugtoolbar = DebugToolbarExtension()

+ 6 - 4
flaskbb/management/models.py

@@ -12,6 +12,7 @@ import sys
 from wtforms import (TextField, IntegerField, FloatField, BooleanField,
                      SelectField, SelectMultipleField, validators)
 from flask.ext.wtf import Form
+from flaskbb._compat import max_integer, text_type, iteritems
 from flaskbb.extensions import db, cache
 
 
@@ -131,7 +132,7 @@ class Setting(db.Model):
                 if "coerce" in setting.extra:
                     coerce_to = setting.extra['coerce']
                 else:
-                    coerce_to = unicode
+                    coerce_to = text_type
 
                 setattr(
                     SettingsForm, setting.key,
@@ -149,7 +150,7 @@ class Setting(db.Model):
                 if "coerce" in setting.extra:
                     coerce_to = setting.extra['coerce']
                 else:
-                    coerce_to = unicode
+                    coerce_to = text_type
 
                 setattr(
                     SettingsForm, setting.key,
@@ -181,7 +182,7 @@ class Setting(db.Model):
         :param settings: A dictionary with setting items.
         """
         # update the database
-        for key, value in settings.iteritems():
+        for key, value in iteritems(settings):
             setting = cls.query.filter(Setting.key == key.lower()).first()
 
             setting.value = value
@@ -218,7 +219,7 @@ class Setting(db.Model):
         return settings
 
     @classmethod
-    @cache.memoize(timeout=sys.maxint)
+    @cache.memoize(timeout=max_integer)
     def as_dict(cls, from_group=None, upper=True):
         """Returns all settings as a dict. This method is cached. If you want
         to invalidate the cache, simply execute ``self.invalidate_cache()``.
@@ -235,6 +236,7 @@ class Setting(db.Model):
                 first_or_404()
             result = result.settings
         else:
+            print(Setting.query)
             result = cls.query.all()
 
         for setting in result:

+ 3 - 2
flaskbb/management/views.py

@@ -18,6 +18,7 @@ from flask.ext.login import current_user
 from flask.ext.plugins import get_all_plugins, get_plugin, get_plugin_from_all
 
 from flaskbb import __version__ as flaskbb_version
+from flaskbb._compat import iteritems
 from flaskbb.forum.forms import UserSearchForm
 from flaskbb.utils.settings import flaskbb_config
 from flaskbb.utils.helpers import render_template
@@ -70,7 +71,7 @@ def settings(slug=None):
     form = SettingsForm()
 
     if form.validate_on_submit():
-        for key, values in old_settings.iteritems():
+        for key, values in iteritems(old_settings):
             try:
                 # check if the value has changed
                 if values['value'] == form[key].data:
@@ -82,7 +83,7 @@ def settings(slug=None):
 
         Setting.update(settings=new_settings, app=current_app)
     else:
-        for key, values in old_settings.iteritems():
+        for key, values in iteritems(old_settings):
             try:
                 form[key].data = values['value']
             except (KeyError, ValueError):

+ 2 - 2
flaskbb/user/models.py

@@ -8,7 +8,6 @@
     :copyright: (c) 2014 by the FlaskBB Team.
     :license: BSD, see LICENSE for more details.
 """
-import sys
 from datetime import datetime
 
 from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
@@ -16,6 +15,7 @@ from itsdangerous import SignatureExpired
 from werkzeug.security import generate_password_hash, check_password_hash
 from flask import current_app, url_for
 from flask.ext.login import UserMixin, AnonymousUserMixin
+from flaskbb._compat import max_integer
 from flaskbb.extensions import db, cache
 from flaskbb.utils.settings import flaskbb_config
 from flaskbb.forum.models import (Post, Topic, topictracker, TopicsRead,
@@ -316,7 +316,7 @@ class User(db.Model, UserMixin):
         return self.secondary_groups.filter(
             groups_users.c.group_id == group.id).count() > 0
 
-    @cache.memoize(timeout=sys.maxint)
+    @cache.memoize(timeout=max_integer)
     def get_permissions(self, exclude=None):
         """Returns a dictionary with all the permissions the user has.
 

+ 14 - 13
flaskbb/utils/helpers.py

@@ -12,7 +12,6 @@ import re
 import time
 import itertools
 import operator
-from unicodedata import normalize
 from datetime import datetime, timedelta
 
 from flask import session
@@ -20,8 +19,10 @@ from flask.ext.themes2 import render_theme_template
 from flask.ext.login import current_user
 
 from postmarkup import render_bbcode
+import unidecode
+from flaskbb._compat import range_method, text_type
 
-from flaskbb.extensions import redis
+from flaskbb.extensions import redis_store
 from flaskbb.utils.settings import flaskbb_config
 
 _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
@@ -34,12 +35,13 @@ def slugify(text, delim=u'-'):
    :param text: The text which should be slugified
    :param delim: Default "-". The delimeter for whitespace
     """
+
+    text = unidecode.unidecode(text)
     result = []
     for word in _punct_re.split(text.lower()):
-        word = normalize('NFKD', word).encode('ascii', 'ignore')
         if word:
             result.append(word)
-    return unicode(delim.join(result))
+    return text_type(delim.join(result))
 
 
 def render_template(template, **context):
@@ -222,7 +224,7 @@ def mark_online(user_id, guest=False):
     else:
         all_users_key = 'online-users/%d' % (now // 60)
         user_key = 'user-activity/%s' % user_id
-    p = redis.pipeline()
+    p = redis_store.pipeline()
     p.sadd(all_users_key, user_id)
     p.set(user_key, now)
     p.expireat(all_users_key, expires)
@@ -238,9 +240,9 @@ def get_last_user_activity(user_id, guest=False):
     :param guest: If the user is a guest (not signed in)
     """
     if guest:
-        last_active = redis.get('guest-activity/%s' % user_id)
+        last_active = redis_store.get('guest-activity/%s' % user_id)
     else:
-        last_active = redis.get('user-activity/%s' % user_id)
+        last_active = redis_store.get('user-activity/%s' % user_id)
 
     if last_active is None:
         return None
@@ -253,11 +255,11 @@ def get_online_users(guest=False):
     :param guest: If True, it will return the online guests
     """
     current = int(time.time()) // 60
-    minutes = xrange(flaskbb_config['ONLINE_LAST_MINUTES'])
+    minutes = range_method(flaskbb_config['ONLINE_LAST_MINUTES'])
     if guest:
-        return redis.sunion(['online-guests/%d' % (current - x)
+        return redis_store.sunion(['online-guests/%d' % (current - x)
                              for x in minutes])
-    return redis.sunion(['online-users/%d' % (current - x)
+    return redis_store.sunion(['online-users/%d' % (current - x)
                          for x in minutes])
 
 
@@ -338,11 +340,10 @@ def time_delta_format(dt, default=None):
     )
 
     for period, singular, plural in periods:
-
-        if not period:
+        if period < 1:
             continue
 
-        if period == 1:
+        if 1 <= period < 2:
             return u'%d %s ago' % (period, singular)
         else:
             return u'%d %s ago' % (period, plural)

+ 7 - 2
flaskbb/utils/populate.py

@@ -76,8 +76,13 @@ def create_admin_user(username, password, email):
     Creates the administrator user
     """
     admin_group = Group.query.filter_by(admin=True).first()
-    user = User(username=username, password=password, email=email,
-                date_joined=datetime.utcnow(), primary_group_id=admin_group.id)
+    user = User()
+
+    user.username = username
+    user.password = password
+    user.email = email
+    user.primary_group_id = admin_group.id
+
     user.save()
 
 

+ 3 - 5
requirements.txt

@@ -1,5 +1,4 @@
 Flask==0.10.1
-Flask-And-Redis==0.5
 Flask-Cache==0.13.1
 Flask-DebugToolbar==0.9.0
 Flask-Login==0.2.11
@@ -10,7 +9,6 @@ Flask-SQLAlchemy==2.0
 Flask-Script==2.0.5
 Flask-Themes2==0.1.3
 Flask-WTF==0.10.2
-Flask-WhooshAlchemy==0.56
 Jinja2==2.7.3
 Mako==1.0.0
 MarkupSafe==0.23
@@ -30,7 +28,7 @@ pytest-cov==1.8.0
 pytest-random==0.02
 redis==2.10.3
 simplejson==3.6.4
-wsgiref==0.1.2
-
+flask-redis==0.0.6
+unidecode==0.04.16
 https://github.com/frol/postmarkup/tarball/master#egg=postmarkup
-
+https://github.com/jshipley/Flask-WhooshAlchemy/archive/master.zip#egg=Flask-Whooshalchemy

+ 5 - 3
setup.py

@@ -40,7 +40,7 @@ setup(
     platforms='any',
     install_requires=[
         'Flask',
-        'Flask-And-Redis',
+        'Flask-Redis',
         'Flask-Cache',
         'Flask-DebugToolbar',
         'Flask-Login',
@@ -69,10 +69,12 @@ setup(
         'pytest-cov',
         'redis',
         'simplejson',
-        'postmarkup'
+        'postmarkup',
+        'unidecode'
     ],
     dependency_links=[
-        'https://github.com/frol/postmarkup/tarball/master#egg=postmarkup'
+        'https://github.com/frol/postmarkup/tarball/master#egg=postmarkup',
+        'https://github.com/jshipley/Flask-WhooshAlchemy/archive/master.zip#egg=Flask-WhooshAlchemy'
     ],
     classifiers=[
         'Development Status :: 4 - Beta',