Permalink
Browse files

rewrite the whole shit

  • Loading branch information...
1 parent 7b77a62 commit e7f0fa67ae17baf6ee8674bbdbbeea2ddf78af16 Hsiaoming Yang committed Jan 4, 2013
View
2 License
@@ -1,4 +1,4 @@
-Copyright (c) 2012, lepture.com
+Copyright (c) 2012, python-china.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
View
2 Makefile
@@ -43,7 +43,7 @@ clean-pyc:
@find . -name '*.pyo' -exec rm -f {} +
@find . -name '*~' -exec rm -f {} +
-files := $(shell find . -name '*.py' ! -path "*docs/*")
+files := $(shell find . -name '*.py' ! -path "*__init__.py*" ! -path "*docs/*")
lint:
@flake8 ${files}
View
11 dev-reqs.txt
@@ -3,6 +3,7 @@
Flask
misaka
pygments
+gevent
# database
Flask-SQLAlchemy
@@ -23,7 +24,17 @@ WTForms
# mail support
Flask-Mail
+# login support
+Flask-Login
+
+# admin site
+Flask-Admin
+
+# command line tools
+Flask-Script
+
# testing
+Flask-Testing
nose
# lint
View
12 june/account/README.md
@@ -1,12 +0,0 @@
-# Accoout
-
-Account system for June.
-
------------------------------
-
-This system provides:
-
-- signin
-- signout
-- signup
-- setting
View
43 june/account/decorators.py
@@ -1,43 +0,0 @@
-from flask import g, request
-from flask import flash, url_for, redirect, abort
-from flask.ext.babel import lazy_gettext as _
-import functools
-
-
-class require_role(object):
- def __init__(self, role):
- self.role = role
-
- def __call__(self, method):
- @functools.wraps(method)
- def wrapper(*args, **kwargs):
- if not g.user:
- url = url_for('account.signin')
- if '?' not in url:
- url += '?next=' + request.url
- return redirect(url)
- if g.user.role is None:
- return method(*args, **kwargs)
- if g.user.id == 1:
- # this is superuser, have no limitation
- return method(*args, **kwargs)
-
- if not g.user.username:
- flash(_('Please setup a username'), 'warn')
- return redirect('/account/setting')
- if g.user.role == 1:
- flash(_('Please verify your email'), 'warn')
- return redirect('/account/setting')
- if g.user.role < 1:
- #TODO
- return redirect('/doc/guideline')
- if g.user.role < self.role:
- return abort(403)
- return method(*args, **kwargs)
- return wrapper
-
-
-require_login = require_role(None)
-require_user = require_role(2)
-require_staff = require_role(6)
-require_admin = require_role(9)
View
101 june/account/forms.py
@@ -1,101 +0,0 @@
-from flask import g
-from flask.ext.wtf import Form
-from flask.ext.wtf import TextField, PasswordField, TextAreaField, IntegerField
-from flask.ext.wtf import Required, Email, URL, Optional, Length
-from flask.ext.wtf.html5 import EmailField, URLField
-from flask.ext.babel import lazy_gettext as _
-from .models import db, Member
-
-
-class SignupForm(Form):
- username = TextField(
- _('Username'), validators=[Required(), Length(min=3, max=20)],
- )
- email = EmailField(
- _('Email'), validators=[Required(), Email()]
- )
- password = PasswordField(
- _('Password'), validators=[Required()]
- )
-
- def save(self):
- user = Member(
- username=self.username.data,
- email=self.email.data,
- password=self.password.data
- )
- db.session.add(user)
- db.session.commit()
- return user
-
-
-class SigninForm(Form):
- account = TextField(
- _('Account'), validators=[Required()],
- description=_("Username or email")
- )
- password = PasswordField(
- _('Password'), validators=[Required()]
- )
-
- def validate_password(self, field):
- account = self.account.data
- if '@' in account:
- user = Member.query.filter_by(email=account).first()
- else:
- user = Member.query.filter_by(username=account).first()
-
- if not user:
- raise ValueError(_('Wrong account or password'))
- if user.check_password(field.data):
- self.user = user
- return user
- raise ValueError(_('Wrong account or password'))
-
-
-class SettingForm(Form):
- username = TextField(
- _('Username'), validators=[Required(), Length(min=3, max=20)],
- )
- website = URLField(
- _('Website'), validators=[Optional(), URL()]
- )
- city = TextField(
- _('City'), validators=[Optional()]
- )
- description = TextAreaField(
- _('Description'),
- )
-
- def save(self):
- user = g.user
- for name, data in self.data.iteritems():
- setattr(user, name, data)
-
- db.session.add(user)
- db.session.commit()
- return user
-
-
-class EditForm(Form):
- username = TextField(
- _('Username'), validators=[Required(), Length(min=3, max=20)],
- )
- email = EmailField(
- _('Email'), validators=[Required(), Email()]
- )
- role = IntegerField(_('Role'), default=2)
- edit_username_count = IntegerField(
- _('Chance'), default=2, description=_('Chance to edit username'),
- )
- description = TextAreaField(
- _('Description'),
- )
-
- def save(self, user):
- for name, data in self.data.iteritems():
- setattr(user, name, data)
-
- db.session.add(user)
- db.session.commit()
- return user
View
33 june/account/helpers.py
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-
-from flask import session
-from .models import Member
-
-
-def get_current_user():
- if 'id' not in session or 'token' not in session:
- return None
-
- user = Member.query.filter_by(id=session['id']).first()
- if not user:
- return None
- if user.token != session['token']:
- logout()
- return None
- return user
-
-
-def login(user):
- if not user:
- return None
- session.permanent = True
- session['id'] = user.id
- session['token'] = user.token
- return user
-
-
-def logout():
- if 'id' not in session:
- return
- session.pop('id')
- session.pop('token')
View
74 june/account/models.py
@@ -1,74 +0,0 @@
-import hashlib
-from datetime import datetime
-from random import choice
-from june.database import db
-
-
-class Member(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- username = db.Column(db.String(100), unique=True, index=True)
- email = db.Column(db.String(200), unique=True, nullable=False, index=True)
- password = db.Column(db.String(100), nullable=False)
- #avatar = db.Column(db.String(400))
- website = db.Column(db.String(400))
-
- role = db.Column(db.Integer, default=1)
- # 0: registered, 1: username
- reputation = db.Column(db.Integer, default=20, index=True)
- token = db.Column(db.String(16))
- created = db.Column(db.DateTime, default=datetime.utcnow)
-
- city = db.Column(db.String(200))
- edit_username_count = db.Column(db.Integer, default=2)
- description = db.Column(db.Text)
-
- def __init__(self, email, **kwargs):
- self.email = email.lower()
- self.token = self.create_token(16)
-
- if 'password' in kwargs:
- raw = kwargs.pop('password')
- self.password = self.create_password(raw)
-
- for k, v in kwargs.items():
- setattr(self, k, v)
-
- def get_avatar(self, size=48):
- if self.avatar:
- return self.avatar
- md5email = hashlib.md5(self.email).hexdigest()
- query = "%s?s=%s%s" % (md5email, size, db.app.config['GRAVATAR_EXTRA'])
- return db.app.config['GRAVATAR_BASE_URL'] + query
-
- @staticmethod
- def create_password(raw):
- salt = Member.create_token(8)
- passwd = '%s%s%s' % (salt, raw, db.app.config['PASSWORD_SECRET'])
- hsh = hashlib.sha1(passwd).hexdigest()
- return "%s$%s" % (salt, hsh)
-
- @staticmethod
- def create_token(length=16):
- chars = ('0123456789'
- 'abcdefghijklmnopqrstuvwxyz'
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
- salt = ''.join([choice(chars) for i in range(length)])
- return salt
-
- def check_password(self, raw):
- if '$' not in self.password:
- return False
- salt, hsh = self.password.split('$')
- passwd = '%s%s%s' % (salt, raw, db.app.config['PASSWORD_SECRET'])
- verify = hashlib.sha1(passwd).hexdigest()
- return verify == hsh
-
- def is_admin(self):
- if self.id == 1:
- return True
- return self.role > 9
-
- def is_staff(self):
- if self.id == 1:
- return True
- return self.role > 6
View
63 june/account/views.py
@@ -1,63 +0,0 @@
-from flask import Blueprint
-from flask import render_template
-from flask import request, redirect, url_for
-from flask import flash
-from flask import g
-from flask.ext.babel import gettext as _
-from .forms import SigninForm, SignupForm, SettingForm, EditForm
-from .models import Member
-from .helpers import login, logout
-from .decorators import require_login, require_admin
-
-app = Blueprint('account', __name__)
-
-
-@app.route('/signin', methods=['GET', 'POST'])
-def signin():
- next_url = request.args.get('next', '/')
- if g.user:
- return redirect(next_url)
- form = SigninForm()
- if form.validate_on_submit():
- login(form.user)
- return redirect(next_url)
- return render_template('account/signin.html', form=form)
-
-
-@app.route('/signout')
-def signout():
- next_url = request.args.get('next', '/')
- logout()
- return redirect(next_url)
-
-
-@app.route('/signup', methods=['GET', 'POST'])
-def signup():
- form = SignupForm()
- if form.validate_on_submit():
- user = form.save()
- login(user)
- return redirect(url_for('.setting'))
- return render_template('account/signup.html', form=form)
-
-
-@app.route('/setting', methods=['GET', 'POST'])
-@require_login
-def setting():
- form = SettingForm(obj=g.user)
- if form.validate_on_submit():
- form.save()
- flash(_('Account has been updated'), 'info')
- return redirect(url_for('.setting'))
- return render_template('account/setting.html', form=form)
-
-
-@app.route('/edit/<username>', methods=['GET', 'POST'])
-@require_admin
-def edit(username):
- user = Member.query.filter_by(username=username).first_or_404()
- form = EditForm(obj=user)
- if form.validate_on_submit():
- form.save(user)
- return redirect(url_for('.edit', username=username))
- return render_template('account/edit.html', form=form)
View
53 june/app.py
@@ -6,20 +6,10 @@
CONFDIR = os.path.join(PROJDIR, '_config')
from flask import Flask
-from flask import g
from flask import request
-from flask import render_template
from flask.ext.babel import Babel
-try:
- import june
- print('Start june version: %s' % june.__version__)
-except ImportError:
- import site
- site.addsitedir(ROOTDIR)
+from .models import db
-from june.account.helpers import get_current_user
-from june.utils import import_object
-from june.database import db
app = Flask(
__name__,
@@ -38,7 +28,7 @@
@app.before_request
def load_current_user():
- g.user = get_current_user()
+ pass
#@app.errorhandler(404)
@@ -52,42 +42,3 @@ def get_locale():
match = app.config['BABEL_SUPPORTED_LOCALES']
default = app.config['BABEL_DEFAULT_LOCALE']
return request.accept_languages.best_match(match, default)
-
-
-def register(blueprint, url_prefix=None):
- """blueprint structure:
-
- {{blueprint}}/
- __init__.py
- models.py
- views.py
- """
- #models = import_object('june.%s.models' % blueprint)
- #models.db.init_app(app)
- #models.db.app = app
-
- if url_prefix is None:
- url_prefix = '/%s' % blueprint
-
- views = import_object('june.%s.views' % blueprint)
- app.register_blueprint(views.app, url_prefix=url_prefix)
- return app
-
-
-def prepare_app():
- register('account')
- register('node')
- register('topic')
-
- return app
-
-
-@app.route('/')
-def hello():
- return render_template('index.html')
-
-
-if __name__ == '__main__':
- app.config.from_pyfile(os.path.join(CONFDIR, 'development.py'))
- prepare_app()
- app.run(host='0.0.0.0')
View
4 june/cache.py
@@ -4,6 +4,7 @@
__all__ = ['cache', 'cache_decorator']
+
class _Cache(object):
"""python-memcahe compatable instance cache
"""
@@ -15,7 +16,8 @@ def create_instance(cls):
if hasattr(cls, '_instance'):
return cls._instance
- if hasattr(app.config, 'memcache_clients') and app.config['memcache_clients']:
+ if hasattr(app.config, 'memcache_clients') and \
+ app.config['memcache_clients']:
try:
import pylibmc
cache = pylibmc.Client(app.config['memcache_clients'],
View
0 june/templates/snippet/foot.html → june/forms/account.py
File renamed without changes.
View
0 june/node/__init__.py → june/forms/node.py
File renamed without changes.
View
0 june/account/__init__.py → june/forms/topic.py
File renamed without changes.
View
4 june/models/__init__.py
@@ -0,0 +1,4 @@
+# coding: utf-8
+# flake8: noqa
+
+from ._base import db
View
0 june/database.py → june/models/_base.py
File renamed without changes.
View
47 june/node/forms.py
@@ -1,47 +0,0 @@
-from flask.ext.wtf import Form
-from flask.ext.wtf import TextField, TextAreaField, IntegerField
-from flask.ext.wtf import Required, Regexp
-from flask.ext.babel import lazy_gettext as _
-from .models import db, Node
-
-
-messages = [
- _('Only lower English characters are allowed'),
-]
-
-
-class NodeForm(Form):
- title = TextField(
- _('Title'), validators=[Required()]
- )
- slug = TextField(
- _('Slug'),
- validators=[Required(), Regexp(r'[a-z]+', message=messages[0])],
- description=messages[0]
- )
- fgcolor = TextField(_('Front Color'))
- bgcolor = TextField(_('Background Color'))
- description = TextAreaField(
- _('Description')
- )
- header = TextAreaField(
- _('Header')
- )
- sidebar = TextAreaField(
- _('Sidebar')
- )
- footer = TextAreaField(
- _('Footer')
- )
- limit_role = IntegerField(_('Role Limitation'), default=0)
-
- def save(self, obj=None):
- if not obj:
- obj = Node()
-
- for name, data in self.data.iteritems():
- setattr(obj, name, data)
-
- db.session.add(obj)
- db.session.commit()
- return obj
View
28 june/node/models.py
@@ -1,28 +0,0 @@
-from datetime import datetime
-from june.database import db
-
-
-class Node(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- title = db.Column(db.String(200), nullable=False)
- slug = db.Column(db.String(200), nullable=False, index=True, unique=True)
- avatar = db.Column(db.String(400))
- description = db.Column(db.String(1000))
- fgcolor = db.Column(db.String(40))
- bgcolor = db.Column(db.String(40))
- header = db.Column(db.String(2000))
- sidebar = db.Column(db.String(2000))
- footer = db.Column(db.String(2000))
- created = db.Column(db.DateTime, default=datetime.utcnow)
- updated = db.Column(db.DateTime, default=datetime.utcnow,
- onupdate=datetime.utcnow)
- limit_reputation = db.Column(db.Integer, default=0)
- limit_role = db.Column(db.Integer, default=2)
- topic_count = db.Column(db.Integer, default=0)
-
-
-class FollowNode(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- user_id = db.Column(db.Integer, nullable=False, index=True)
- node_id = db.Column(db.Integer, nullable=False, index=True)
- created = db.Column(db.DateTime, default=datetime.utcnow)
View
41 june/node/views.py
@@ -1,41 +0,0 @@
-from flask import Blueprint
-from flask import render_template, redirect, url_for
-from .forms import NodeForm
-from .models import Node
-from june.account.decorators import require_admin
-
-
-app = Blueprint('node', __name__, template_folder='templates')
-
-
-@app.route('/')
-def index():
- nodes = Node.query.all()
- return render_template('node/index.html', nodes=nodes)
-
-
-@app.route('/<slug>')
-def topics(slug):
- node = Node.query.filter_by(slug=slug).first_or_404()
- return render_template('node/topics.html', node=node)
-
-
-@app.route('/-create', methods=['GET', 'POST'])
-@require_admin
-def create():
- form = NodeForm()
- if form.validate_on_submit():
- node = form.save()
- return redirect(url_for('.topics', slug=node.slug))
- return render_template('node/create.html', form=form)
-
-
-@app.route('/<slug>/-edit', methods=['GET', 'POST'])
-@require_admin
-def edit(slug):
- node = Node.query.filter_by(slug=slug).first_or_404()
- form = NodeForm(obj=node)
- if form.validate_on_submit():
- node = form.save(node)
- return redirect(url_for('.topics', slug=node.slug))
- return render_template('node/create.html', form=form)
View
15 june/templates/account/edit.html
@@ -1,15 +0,0 @@
-{% extends "layout.html" %}
-{% from "snippet/macros.html" import render_field, render_submit %}
-
-{% block content %}
-<form class="fm-form" method="post" action="">
- {{ form.csrf_token }}
- {{ render_field(form.username) }}
- {{ render_field(form.email) }}
- {{ render_field(form.role) }}
- {{ render_field(form.edit_username_count) }}
- {{ render_field(form.description, 'fm-textarea') }}
-
- {{ render_submit(_("Update")) }}
-</form>
-{% endblock %}
View
14 june/templates/account/setting.html
@@ -1,14 +0,0 @@
-{% extends "layout.html" %}
-{% from "snippet/macros.html" import render_field, render_submit %}
-
-{% block content %}
-<form class="fm-form" method="post" action="{{ url_for('account.setting')}}">
- {{ form.csrf_token }}
- {{ render_field(form.username) }}
- {{ render_field(form.website) }}
- {{ render_field(form.city) }}
- {{ render_field(form.description, 'fm-textarea') }}
-
- {{ render_submit(_("Update")) }}
-</form>
-{% endblock %}
View
11 june/templates/account/signin.html
@@ -1,11 +0,0 @@
-{% extends "layout.html" %}
-{% from "snippet/macros.html" import render_field, render_submit %}
-
-{% block main %}
-<form class="fm-form" method="post" action="">
- {{ form.csrf_token }}
- {{ render_field(form.account) }}
- {{ render_field(form.password) }}
- {{ render_submit(_("Login")) }}
-</form>
-{% endblock %}
View
12 june/templates/account/signup.html
@@ -1,12 +0,0 @@
-{% extends "layout.html" %}
-{% from "snippet/macros.html" import render_field, render_submit %}
-
-{% block main %}
-<form class="fm-form" method="post" action="{{url_for('account.signup')}}">
- {{ form.csrf_token }}
- {{ render_field(form.username) }}
- {{ render_field(form.email) }}
- {{ render_field(form.password) }}
- {{ render_submit(_("Register")) }}
-</form>
-{% endblock %}
View
1 june/templates/index.html
@@ -1 +0,0 @@
-{% extends "layout.html" %}
View
63 june/templates/layout.html
@@ -1,63 +0,0 @@
-<!DOCTYPE HTML>
-<html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>{% block title %}{{ config.SITE_TITLE }}{% endblock %}</title>
- {% include "snippet/head.html" %}
- </head>
- <body>
- <header id="site-header">
- <div class="container fn-clear">
- {% block brand %}
- <div id="brand">
- <a id="brand-name" href="/">{{ config.SITE_TITLE }}</a>
- <a id="indicator" href="#" title="You have 1 message">1</a>
- <form action="">
- <input type="search" />
- </form>
- </div>
- {% endblock %}
- <nav role="navigation">
- {% block navigation %}
- <a href="/">Latest</a>
- <a href="/following">Following</a>
- <a href="/nodes">Nodes</a>
- {% endblock %}
- </nav>
- </div>
- </header>
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
- <ul id="flash-message">
- {% for category, message in messages %}
- <li class="{{category}}">{{ message }}</li>
- {% endfor %}
- </ul>
- {% endif %}
- {% endwith %}
-
- <div id="site-container" class="container">
- {% block main %}
- <div id="main" class="fn-clear">
- <div id="content">
- {% block content %}
- hello world
- {% endblock %}
- </div>
-
- <aside id="sidebar">
- {% block sidebar %}
- <div class="widget">
- <header class="widget-head">Head</header>
- <div class="widget-content">
- hello world
- </div>
- </div>
- {% endblock %}
- </aside>
- </div>
- {% endblock %}
- </div>
- {% include "snippet/foot.html" %}
- </body>
-</html>
View
18 june/templates/node/create.html
@@ -1,18 +0,0 @@
-{% extends "layout.html" %}
-{% from "snippet/macros.html" import render_field, render_submit %}
-
-{% block main %}
-<form class="fm-form" method="post" action="">
- {{ form.csrf_token }}
- {{ render_field(form.title) }}
- {{ render_field(form.slug) }}
- {{ render_field(form.fgcolor) }}
- {{ render_field(form.bgcolor) }}
- {{ render_field(form.description, 'fm-textarea') }}
- {{ render_field(form.header, 'fm-textarea') }}
- {{ render_field(form.sidebar, 'fm-textarea') }}
- {{ render_field(form.footer, 'fm-textarea') }}
- {{ render_field(form.limit_role) }}
- {{ render_submit(_("Create")) }}
-</form>
-{% endblock %}
View
9 june/templates/node/index.html
@@ -1,9 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-<ul>
- {% for node in nodes %}
- <li><a href="{{ url_for('node.topics', slug=node.slug) }}">{{ node.title }}</a></li>
- {% endfor %}
-</ul>
-{% endblock %}
View
5 june/templates/node/topics.html
@@ -1,5 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-{{ node.title }}
-{% endblock %}
View
5 june/templates/snippet/head.html
@@ -1,5 +0,0 @@
-{% if config.DEBUG %}
-<link rel="stylesheet" href="{{url_for('static', filename='css/base.css')}}" />
-<link rel="stylesheet" href="{{url_for('static', filename='css/layout.css')}}" />
-<link rel="stylesheet" href="{{url_for('static', filename='css/ui.css')}}" />
-{% endif %}
View
25 june/templates/snippet/macros.html
@@ -1,25 +0,0 @@
-{% macro render_field(field, class=None) %}
-<div class="fm-field{% if field.flags.required %} fm-required{% endif %}{% if class %} {{class}}{% endif %}">
- {{ field.label }}
- {{ field() }}
- {% if field.errors %}
- <ul class="fm-errors">
- {% for error in field.errors %}
- <li>{{ error }}</li>
- {% endfor %}
- </ul>
- {% else %}
- {% if field.description %}
- <p class="fm-description">{{ field.description }}</p>
- {% endif %}
- {% endif %}
-</div>
-{% endmacro %}
-
-{% macro render_submit(name) %}
-<div class="fm-field">
- <div class="fm-submit">
- <button class="fm-button">{{ name }}</button>
- </div>
-</div>
-{% endmacro %}
View
5 june/topic/__init__.py
@@ -1,5 +0,0 @@
-"""June Topic
-
-:copyright: (c) 2012 by lepture liuw
-:license: BSD
-"""
View
38 june/topic/forms.py
@@ -1,38 +0,0 @@
-from flask.ext.wtf import Form
-
-
-class TopicForm(Form):
- title = TextField(
- _('Title'), validators=[Required()]
- )
- slug = TextField(
- _('Slug'),
- validators=[Required(), Regexp(r'[a-z]+', message=messages[0])],
- description=messages[0]
- )
- fgcolor = TextField(_('Front Color'))
- bgcolor = TextField(_('Background Color'))
- description = TextAreaField(
- _('Description')
- )
- header = TextAreaField(
- _('Header')
- )
- sidebar = TextAreaField(
- _('Sidebar')
- )
- footer = TextAreaField(
- _('Footer')
- )
- limit_role = IntegerField(_('Role Limitation'), default=0)
-
- def save(self, obj=None):
- if not obj:
- obj = Node()
-
- for name, data in self.data.iteritems():
- setattr(obj, name, data)
-
- db.session.add(obj)
- db.session.commit()
- return obj
View
82 june/topic/lib.py
@@ -1,82 +0,0 @@
-import math
-from datetime import datetime
-from june.account.models import Member
-from june.node.models import Node
-from june.cache import get_cache_list
-
-
-def get_user_id_list(topics):
- for t in topics:
- yield t.user_id
- if t.last_reply_by:
- yield t.last_reply_by
-
-
-def get_full_topics(topics):
- users = get_cache_list(Member, get_user_id_list(topics), 'member:')
- nodes = get_cache_list(Node, (t.node_id for t in topics), 'node:')
- for topic in topics:
- if topic.user_id in users and topic.node_id in nodes:
- topic.user = users[topic.user_id]
- if topic.last_reply_by:
- topic.replyer = users[topic.last_reply_by]
- else:
- topic.replyer = None
- topic.node = nodes[topic.node_id]
- yield topic
-
-
-def get_full_replies(replies):
- users = get_cache_list(Member, (r.user_id for r in replies), 'member:')
- for reply in replies:
- if reply.user_id in users:
- reply.user = users[reply.user_id]
- yield reply
-
-
-def reply_impact_for_topic(topic, reputation):
- if reputation < 2:
- return 0
- factor = int(options.reply_factor_for_topic)
- time_factor = int(options.reply_time_factor)
- time = datetime.utcnow() - topic.created
- factor += time.days * time_factor
- return factor * int(math.log(reputation))
-
-
-def up_impact_for_topic(reputation):
- if reputation < 2:
- return 0
- factor = int(options.up_factor_for_topic)
- return factor * int(math.log(reputation))
-
-
-def down_impact_for_topic(reputation):
- if reputation < 2:
- return 0
- factor = int(options.down_factor_for_topic)
- return factor * int(math.log(reputation))
-
-
-def up_impact_for_user(reputation):
- if reputation < 2:
- return 0
- factor = int(options.up_factor_for_user)
- impact = factor * int(math.log(reputation))
- return min(impact, int(options.up_max_for_user))
-
-
-def down_impact_for_user(reputation):
- if reputation < 2:
- return 0
- factor = int(options.down_factor_for_user)
- impact = factor * int(math.log(reputation))
- return min(impact, int(options.down_max_for_user))
-
-
-def accept_reply_impact_for_user(reputation):
- if reputation < 2:
- return 0
- factor = int(options.accept_reply_factor_for_user)
- impact = factor * int(math.log(reputation))
- return min(impact, int(options.vote_max_for_user))
View
76 june/topic/models.py
@@ -1,76 +0,0 @@
-"""
-Topic:
- topic must be in a node
-
- impact:
- for sorting topic
-
- 1. when user reply a topic, impact increase:
- + (n1 + day_del * n2) * log(user.reputation)
-
- 2. when user up vote a topic, impact increase:
- + n3 * log(user.reputation)
-
- 3. when user down vote a topic, impact decrease:
- - n4 * log(user.reputation)
-
-"""
-
-import time
-from datetime import datetime
-from june.database import db
-
-
-def get_current_impact():
- return int(time.time())
-
-
-class Topic(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- node_id = db.Column(db.Integer, nullable=False, index=True)
- user_id = db.Column(db.Integer, nullable=False, index=True)
- title = db.Column(db.String(200))
- content = db.Column(db.Text)
- created = db.Column(db.DateTime, default=datetime.utcnow)
- updated = db.Column(db.DateTime, default=datetime.utcnow,
- onupdate=datetime.utcnow)
- status = db.Column(db.String(40))
- hits = db.Column(db.Integer, default=1)
-
- up_count = db.Column(db.Integer, default=0)
- down_count = db.Column(db.Integer, default=0)
-
- #:TODO delete ups, downs
- #ups = db.Column(db.Text) # e.g. 1,2,3,4
- #downs = db.Column(db.Text)
-
- reply_count = db.Column(db.Integer, default=0)
- last_reply_by = db.Column(db.Integer, default=0)
- last_reply_time = db.Column(db.DateTime,
- default=datetime.utcnow, index=True)
-
- impact = db.Column(db.Integer, default=get_current_impact, index=True)
-
-
-class Reply(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- topic_id = db.Column(db.Integer, nullable=False, index=True)
- user_id = db.Column(db.Integer, nullable=False, index=True)
- content = db.Column(db.String(2000))
- created = db.Column(db.DateTime, default=datetime.utcnow)
-
- accepted = db.Column(db.String(1), default='n') # accepted by topic owner
-
-
-class Vote(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- user_id = db.Column(db.Integer, nullable=False, index=True)
- topic_id = db.Column(db.Integer, nullable=False, index=True)
- type = db.Column(db.String(10))
-
-
-class TopicLog(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- topic_id = db.Column(db.Integer, nullable=False, index=True)
- user_id = db.Column(db.Integer, nullable=False)
- created = db.Column(db.DateTime, default=datetime.utcnow)
View
2 june/utils.py
@@ -1,12 +1,14 @@
import re
+
def import_object(name, arg=None):
if '.' not in name:
return __import__(name)
parts = name.split('.')
obj = __import__('.'.join(parts[:-1]), None, None, [parts[-1]], 0)
return getattr(obj, parts[-1], arg)
+
def find_mention(text):
regex = r'@(\w+)\s'
return re.findall(regex, text)
View
0 june/views/account.py
No changes.
View
0 june/views/node.py
No changes.
View
5 june/topic/views.py → june/views/topic.py
@@ -2,10 +2,7 @@
from flask import Blueprint
from flask import render_template
-from flask import request
-from flask import g
from june.node.models import Node
-from .models import Topic
app = Blueprint('topic', __name__, template_folder='templates')
@@ -14,7 +11,7 @@
@app.route('/-create/<slug>')
def create(slug):
node = Node.query.filter_by(slug=slug).first_or_404()
- return render_template("create_topic.html")
+ return render_template("create_topic.html", node=node)
@app.route('/<int:id>/-edit', methods=['GET', 'POST'])
View
29 manager.py
@@ -0,0 +1,29 @@
+# coding: utf-8
+
+from flask.ext.script import Manager
+
+from june.app import app
+
+manager = Manager(app)
+
+
+@manager.command
+def runserver(port=5000):
+ """Run a development server"""
+ from gevent.wsgi import WSGIServer
+ from werkzeug.server import run_with_reloader
+ from werkzeug.debug import DebuggerApplication
+
+ port = int(port)
+
+ @run_with_reloader
+ def run_server():
+ print('start server at: 127.0.0.1:%s' % port)
+ http_server = WSGIServer(('', port), DebuggerApplication(app))
+ http_server.serve_forever()
+
+ run_server()
+
+
+if __name__ == '__main__':
+ manager.run()
View
7 tests/test_db.py
@@ -1,21 +1,20 @@
import os
import tempfile
-from june.app import app, prepare_app
+from june.app import app
class TestDatabase(object):
def setUp(self):
self.db_fd, self.db_path = tempfile.mkstemp()
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///%s' % self.db_path
app.config['TESTING'] = True
- prepare_app()
self.app = app.test_client()
#: rv = self.app.get('/')
#: assert 'something' in rv.data
- from june.account import models
- models.db.create_all()
+ #from june.account import models
+ #models.db.create_all()
def tearDown(self):
os.close(self.db_fd)

0 comments on commit e7f0fa6

Please sign in to comment.