ajax translations
This commit is contained in:
parent
22ba5eed17
commit
4081db19e1
|
@ -73,7 +73,7 @@ class User(db.Model):
|
||||||
|
|
||||||
def followed_posts(self):
|
def followed_posts(self):
|
||||||
return Post.query.join(followers, (followers.c.followed_id == Post.user_id)).filter(followers.c.follower_id == self.id).order_by(Post.timestamp.desc())
|
return Post.query.join(followers, (followers.c.followed_id == Post.user_id)).filter(followers.c.follower_id == self.id).order_by(Post.timestamp.desc())
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<User %r>' % (self.nickname)
|
return '<User %r>' % (self.nickname)
|
||||||
|
|
||||||
|
@ -84,7 +84,8 @@ class Post(db.Model):
|
||||||
body = db.Column(db.String(140))
|
body = db.Column(db.String(140))
|
||||||
timestamp = db.Column(db.DateTime)
|
timestamp = db.Column(db.DateTime)
|
||||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
|
language = db.Column(db.String(5))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Post %r>' % (self.body)
|
return '<Post %r>' % (self.body)
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 673 B |
|
@ -15,6 +15,25 @@
|
||||||
<script src="/static/js/moment-{{g.locale}}.min.js"></script>
|
<script src="/static/js/moment-{{g.locale}}.min.js"></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<script>
|
||||||
|
function translate(sourceLang, destLang, sourceId, destId, loadingId) {
|
||||||
|
$(destId).hide();
|
||||||
|
$(loadingId).show();
|
||||||
|
$.post('/translate', {
|
||||||
|
text: $(sourceId).text(),
|
||||||
|
sourceLang: sourceLang,
|
||||||
|
destLang: destLang
|
||||||
|
}).done(function(translated) {
|
||||||
|
$(destId).text(translated['text'])
|
||||||
|
$(loadingId).hide();
|
||||||
|
$(destId).show();
|
||||||
|
}).fail(function() {
|
||||||
|
$(destId).text("{{ _('Error: Could not contact server.') }}");
|
||||||
|
$(loadingId).hide();
|
||||||
|
$(destId).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -48,4 +67,3 @@
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,15 @@
|
||||||
{% autoescape false %}
|
{% autoescape false %}
|
||||||
<p>{{ _('%(nickname)s said %(when)s:', nickname = '<a href="%s">%s</a>' % (url_for('user', nickname = post.author.nickname), post.author.nickname), when = momentjs(post.timestamp).fromNow()) }}</p>
|
<p>{{ _('%(nickname)s said %(when)s:', nickname = '<a href="%s">%s</a>' % (url_for('user', nickname = post.author.nickname), post.author.nickname), when = momentjs(post.timestamp).fromNow()) }}</p>
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
<p><strong>{{post.body}}</strong></p>
|
<p><strong><span id="post{{post.id}}">{{post.body}}</span></strong></p>
|
||||||
|
{% if post.language != None and post.language != '' and post.language != g.locale %}
|
||||||
|
<div>
|
||||||
|
<span id="translation{{post.id}}">
|
||||||
|
<a href="javascript:translate('{{post.language}}', '{{g.locale}}', '#post{{post.id}}', '#translation{{post.id}}', '#loading{{post.id}}');">{{ _('Translate') }}</a>
|
||||||
|
</span>
|
||||||
|
<img id="loading{{post.id}}" style="display: none" src="/static/img/loading.gif">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import urllib, httplib
|
||||||
|
import json
|
||||||
|
from app import app
|
||||||
|
from flask.ext.babel import gettext
|
||||||
|
from config import MS_TRANSLATOR_CLIENT_ID, MS_TRANSLATOR_CLIENT_SECRET
|
||||||
|
|
||||||
|
def microsoft_translate(text, sourceLang, destLang):
|
||||||
|
if MS_TRANSLATOR_CLIENT_ID == "" or MS_TRANSLATOR_CLIENT_SECRET == "":
|
||||||
|
return gettext('Error: translation service not configured.')
|
||||||
|
try:
|
||||||
|
# get access token
|
||||||
|
params = urllib.urlencode({
|
||||||
|
'client_id': MS_TRANSLATOR_CLIENT_ID,
|
||||||
|
'client_secret': MS_TRANSLATOR_CLIENT_SECRET,
|
||||||
|
'scope': 'http://api.microsofttranslator.com',
|
||||||
|
'grant_type': 'client_credentials'
|
||||||
|
})
|
||||||
|
conn = httplib.HTTPSConnection("datamarket.accesscontrol.windows.net")
|
||||||
|
conn.request("POST", "/v2/OAuth2-13", params)
|
||||||
|
response = json.loads (conn.getresponse().read())
|
||||||
|
token = response[u'access_token']
|
||||||
|
|
||||||
|
# translate
|
||||||
|
conn = httplib.HTTPConnection('api.microsofttranslator.com')
|
||||||
|
params = {
|
||||||
|
'appId': 'Bearer ' + token,
|
||||||
|
'from': sourceLang,
|
||||||
|
'to': destLang,
|
||||||
|
'text': text.encode("utf-8")
|
||||||
|
}
|
||||||
|
conn.request("GET", '/V2/Ajax.svc/Translate?' + urllib.urlencode(params))
|
||||||
|
response = json.loads("{\"response\":" + conn.getresponse().read().decode('utf-8-sig') + "}")
|
||||||
|
return response["response"]
|
||||||
|
except:
|
||||||
|
#return gettext('Error: Unexpected error.')
|
||||||
|
raise
|
||||||
|
|
||||||
|
def google_translate(text, sourceLang, destLang):
|
||||||
|
if not app.debug:
|
||||||
|
return gettext('Error: translation service not available.')
|
||||||
|
try:
|
||||||
|
params = urllib.urlencode({
|
||||||
|
'client': 't',
|
||||||
|
'text': text.encode("utf-8"),
|
||||||
|
'sl': sourceLang,
|
||||||
|
'tl': destLang,
|
||||||
|
'ie': 'UTF-8',
|
||||||
|
'oe': 'UTF-8'
|
||||||
|
})
|
||||||
|
conn = httplib.HTTPSConnection("translate.google.com")
|
||||||
|
conn.request("GET", "/translate_a/t?" + params, headers = { 'User-Agent': 'Mozilla/5.0' })
|
||||||
|
httpresponse = conn.getresponse().read().replace(",,,", ",\"\",\"\",").replace(",,", ",\"\",")
|
||||||
|
response = json.loads("{\"response\":" + httpresponse + "}")
|
||||||
|
return response["response"][0][0][0]
|
||||||
|
except:
|
||||||
|
return gettext('Error: Unexpected error.')
|
|
@ -7,8 +7,8 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2013-01-31 23:19-0800\n"
|
"POT-Creation-Date: 2013-02-19 22:11-0800\n"
|
||||||
"PO-Revision-Date: 2013-01-31 23:19-0800\n"
|
"PO-Revision-Date: 2013-02-19 22:12-0800\n"
|
||||||
"Last-Translator: Miguel Grinberg <miguel.grinberg@gmail.com>\n"
|
"Last-Translator: Miguel Grinberg <miguel.grinberg@gmail.com>\n"
|
||||||
"Language-Team: es <LL@li.org>\n"
|
"Language-Team: es <LL@li.org>\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
@ -34,47 +34,59 @@ msgstr ""
|
||||||
msgid "This nickname is already in use. Please choose another one."
|
msgid "This nickname is already in use. Please choose another one."
|
||||||
msgstr "Este nombre de usuario ya esta usado. Por favor elije otro."
|
msgstr "Este nombre de usuario ya esta usado. Por favor elije otro."
|
||||||
|
|
||||||
#: app/views.py:49
|
#: app/translate.py:9
|
||||||
|
msgid "Error: translation service not configured."
|
||||||
|
msgstr "Error: el servicio de traducción no está configurado."
|
||||||
|
|
||||||
|
#: app/translate.py:35 app/translate.py:55
|
||||||
|
msgid "Error: Unexpected error."
|
||||||
|
msgstr "Error: Un error inesperado ha ocurrido."
|
||||||
|
|
||||||
|
#: app/translate.py:39
|
||||||
|
msgid "Error: translation service not available."
|
||||||
|
msgstr "Error: servicio de traducción no disponible."
|
||||||
|
|
||||||
|
#: app/views.py:56
|
||||||
msgid "Your post is now live!"
|
msgid "Your post is now live!"
|
||||||
msgstr "¡Tu artículo ha sido publicado!"
|
msgstr "¡Tu artículo ha sido publicado!"
|
||||||
|
|
||||||
#: app/views.py:74
|
#: app/views.py:81
|
||||||
msgid "Invalid login. Please try again."
|
msgid "Invalid login. Please try again."
|
||||||
msgstr "Credenciales inválidas. Por favor intenta de nuevo."
|
msgstr "Credenciales inválidas. Por favor intenta de nuevo."
|
||||||
|
|
||||||
#: app/views.py:107
|
#: app/views.py:114
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "User %(nickname)s not found."
|
msgid "User %(nickname)s not found."
|
||||||
msgstr "El usuario %(nickname)s no existe."
|
msgstr "El usuario %(nickname)s no existe."
|
||||||
|
|
||||||
#: app/views.py:123
|
#: app/views.py:130
|
||||||
msgid "Your changes have been saved."
|
msgid "Your changes have been saved."
|
||||||
msgstr "Tus cambios han sido guardados."
|
msgstr "Tus cambios han sido guardados."
|
||||||
|
|
||||||
#: app/views.py:139
|
#: app/views.py:146
|
||||||
msgid "You can't follow yourself!"
|
msgid "You can't follow yourself!"
|
||||||
msgstr "¡No te puedes seguir a tí mismo!"
|
msgstr "¡No te puedes seguir a tí mismo!"
|
||||||
|
|
||||||
#: app/views.py:143
|
#: app/views.py:150
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Cannot follow %(nickname)s."
|
msgid "Cannot follow %(nickname)s."
|
||||||
msgstr "No se pudo seguir a %(nickname)s."
|
msgstr "No se pudo seguir a %(nickname)s."
|
||||||
|
|
||||||
#: app/views.py:147
|
#: app/views.py:154
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You are now following %(nickname)s!"
|
msgid "You are now following %(nickname)s!"
|
||||||
msgstr "¡Ya estás siguiendo a %(nickname)s!"
|
msgstr "¡Ya estás siguiendo a %(nickname)s!"
|
||||||
|
|
||||||
#: app/views.py:159
|
#: app/views.py:166
|
||||||
msgid "You can't unfollow yourself!"
|
msgid "You can't unfollow yourself!"
|
||||||
msgstr "¡No te puedes dejar de seguir a tí mismo!"
|
msgstr "¡No te puedes dejar de seguir a tí mismo!"
|
||||||
|
|
||||||
#: app/views.py:163
|
#: app/views.py:170
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Cannot unfollow %(nickname)s."
|
msgid "Cannot unfollow %(nickname)s."
|
||||||
msgstr "No se pudo dejar de seguir a %(nickname)s."
|
msgstr "No se pudo dejar de seguir a %(nickname)s."
|
||||||
|
|
||||||
#: app/views.py:167
|
#: app/views.py:174
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You have stopped following %(nickname)s."
|
msgid "You have stopped following %(nickname)s."
|
||||||
msgstr "Ya no sigues más a %(nickname)s."
|
msgstr "Ya no sigues más a %(nickname)s."
|
||||||
|
@ -95,19 +107,23 @@ msgstr "Un error inesperado ha ocurrido"
|
||||||
msgid "The administrator has been notified. Sorry for the inconvenience!"
|
msgid "The administrator has been notified. Sorry for the inconvenience!"
|
||||||
msgstr "El administrador ha sido notificado. ¡Lo lamento!"
|
msgstr "El administrador ha sido notificado. ¡Lo lamento!"
|
||||||
|
|
||||||
#: app/templates/base.html:30
|
#: app/templates/base.html:31
|
||||||
|
msgid "Error: Could not contact server."
|
||||||
|
msgstr "Error: No es posible contactar al servidor."
|
||||||
|
|
||||||
|
#: app/templates/base.html:49
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr "Inicio"
|
msgstr "Inicio"
|
||||||
|
|
||||||
#: app/templates/base.html:32
|
#: app/templates/base.html:51
|
||||||
msgid "Your Profile"
|
msgid "Your Profile"
|
||||||
msgstr "Tu Perfil"
|
msgstr "Tu Perfil"
|
||||||
|
|
||||||
#: app/templates/base.html:33
|
#: app/templates/base.html:52
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Desconectarse"
|
msgstr "Desconectarse"
|
||||||
|
|
||||||
#: app/templates/base.html:38
|
#: app/templates/base.html:57
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Buscar"
|
msgstr "Buscar"
|
||||||
|
|
||||||
|
@ -188,6 +204,10 @@ msgstr "Ingresar"
|
||||||
msgid "%(nickname)s said %(when)s:"
|
msgid "%(nickname)s said %(when)s:"
|
||||||
msgstr "%(nickname)s dijo %(when)s:"
|
msgstr "%(nickname)s dijo %(when)s:"
|
||||||
|
|
||||||
|
#: app/templates/post.html:12
|
||||||
|
msgid "Translate"
|
||||||
|
msgstr "Traducir"
|
||||||
|
|
||||||
#: app/templates/search_results.html:5
|
#: app/templates/search_results.html:5
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Search results for \"%(query)s\":"
|
msgid "Search results for \"%(query)s\":"
|
||||||
|
|
24
app/views.py
24
app/views.py
|
@ -1,4 +1,4 @@
|
||||||
from flask import render_template, flash, redirect, session, url_for, request, g
|
from flask import render_template, flash, redirect, session, url_for, request, g, jsonify
|
||||||
from flask.ext.login import login_user, logout_user, current_user, login_required
|
from flask.ext.login import login_user, logout_user, current_user, login_required
|
||||||
from flask.ext.babel import gettext
|
from flask.ext.babel import gettext
|
||||||
from app import app, db, lm, oid, babel
|
from app import app, db, lm, oid, babel
|
||||||
|
@ -6,8 +6,9 @@ from forms import LoginForm, EditForm, PostForm, SearchForm
|
||||||
from models import User, ROLE_USER, ROLE_ADMIN, Post
|
from models import User, ROLE_USER, ROLE_ADMIN, Post
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from emails import follower_notification
|
from emails import follower_notification
|
||||||
from config import POSTS_PER_PAGE, MAX_SEARCH_RESULTS
|
from guess_language import guessLanguage
|
||||||
from config import LANGUAGES
|
from translate import microsoft_translate
|
||||||
|
from config import POSTS_PER_PAGE, MAX_SEARCH_RESULTS, LANGUAGES
|
||||||
|
|
||||||
@lm.user_loader
|
@lm.user_loader
|
||||||
def load_user(id):
|
def load_user(id):
|
||||||
|
@ -43,7 +44,13 @@ def internal_error(error):
|
||||||
def index(page = 1):
|
def index(page = 1):
|
||||||
form = PostForm()
|
form = PostForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
post = Post(body = form.post.data, timestamp = datetime.utcnow(), author = g.user)
|
language = guessLanguage(form.post.data)
|
||||||
|
if language == 'UNKNOWN' or len(language) > 5:
|
||||||
|
language = ''
|
||||||
|
post = Post(body = form.post.data,
|
||||||
|
timestamp = datetime.utcnow(),
|
||||||
|
author = g.user,
|
||||||
|
language = language)
|
||||||
db.session.add(post)
|
db.session.add(post)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash(gettext('Your post is now live!'))
|
flash(gettext('Your post is now live!'))
|
||||||
|
@ -182,3 +189,12 @@ def search_results(query):
|
||||||
query = query,
|
query = query,
|
||||||
results = results)
|
results = results)
|
||||||
|
|
||||||
|
@app.route('/translate', methods = ['POST'])
|
||||||
|
@login_required
|
||||||
|
def translate():
|
||||||
|
return jsonify({
|
||||||
|
'text': microsoft_translate(
|
||||||
|
request.form['text'],
|
||||||
|
request.form['sourceLang'],
|
||||||
|
request.form['destLang']) })
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@ LANGUAGES = {
|
||||||
'es': 'Español'
|
'es': 'Español'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# microsoft translation service
|
||||||
|
MS_TRANSLATOR_CLIENT_ID = '' # enter your MS translator app id here
|
||||||
|
MS_TRANSLATOR_CLIENT_SECRET = '' # enter your MS translator app secret here
|
||||||
|
|
||||||
# administrator list
|
# administrator list
|
||||||
ADMINS = ['you@example.com']
|
ADMINS = ['you@example.com']
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
from sqlalchemy import *
|
||||||
|
from migrate import *
|
||||||
|
|
||||||
|
|
||||||
|
from migrate.changeset import schema
|
||||||
|
pre_meta = MetaData()
|
||||||
|
post_meta = MetaData()
|
||||||
|
post = Table('post', post_meta,
|
||||||
|
Column('id', Integer, primary_key=True, nullable=False),
|
||||||
|
Column('body', String(length=140)),
|
||||||
|
Column('timestamp', DateTime),
|
||||||
|
Column('user_id', Integer),
|
||||||
|
Column('language', String(length=5)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
# Upgrade operations go here. Don't create your own engine; bind
|
||||||
|
# migrate_engine to your metadata
|
||||||
|
pre_meta.bind = migrate_engine
|
||||||
|
post_meta.bind = migrate_engine
|
||||||
|
post_meta.tables['post'].columns['language'].create()
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(migrate_engine):
|
||||||
|
# Operations to reverse the above upgrade go here.
|
||||||
|
pre_meta.bind = migrate_engine
|
||||||
|
post_meta.bind = migrate_engine
|
||||||
|
post_meta.tables['post'].columns['language'].drop()
|
1
setup.py
1
setup.py
|
@ -18,4 +18,5 @@ subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'sqlalchemy-migra
|
||||||
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flask-whooshalchemy'])
|
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flask-whooshalchemy'])
|
||||||
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flask-wtf'])
|
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flask-wtf'])
|
||||||
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flask-babel'])
|
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flask-babel'])
|
||||||
|
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'guess-language'])
|
||||||
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flup'])
|
subprocess.call([os.path.join('flask', bin, 'pip'), 'install', 'flup'])
|
||||||
|
|
103
tests.py
103
tests.py
|
@ -1,4 +1,6 @@
|
||||||
#!flask/bin/python
|
#!flask/bin/python
|
||||||
|
# -*- coding: utf8 -*-
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
@ -6,6 +8,7 @@ from datetime import datetime, timedelta
|
||||||
from config import basedir
|
from config import basedir
|
||||||
from app import app, db
|
from app import app, db
|
||||||
from app.models import User, Post
|
from app.models import User, Post
|
||||||
|
from app.translate import microsoft_translate
|
||||||
|
|
||||||
class TestCase(unittest.TestCase):
|
class TestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -64,54 +67,58 @@ class TestCase(unittest.TestCase):
|
||||||
assert u1.followed.count() == 0
|
assert u1.followed.count() == 0
|
||||||
assert u2.followers.count() == 0
|
assert u2.followers.count() == 0
|
||||||
|
|
||||||
def test_follow_posts(self):
|
def test_follow_posts(self):
|
||||||
# make four users
|
# make four users
|
||||||
u1 = User(nickname = 'john', email = 'john@example.com')
|
u1 = User(nickname = 'john', email = 'john@example.com')
|
||||||
u2 = User(nickname = 'susan', email = 'susan@example.com')
|
u2 = User(nickname = 'susan', email = 'susan@example.com')
|
||||||
u3 = User(nickname = 'mary', email = 'mary@example.com')
|
u3 = User(nickname = 'mary', email = 'mary@example.com')
|
||||||
u4 = User(nickname = 'david', email = 'david@example.com')
|
u4 = User(nickname = 'david', email = 'david@example.com')
|
||||||
db.session.add(u1)
|
db.session.add(u1)
|
||||||
db.session.add(u2)
|
db.session.add(u2)
|
||||||
db.session.add(u3)
|
db.session.add(u3)
|
||||||
db.session.add(u4)
|
db.session.add(u4)
|
||||||
# make four posts
|
# make four posts
|
||||||
utcnow = datetime.utcnow()
|
utcnow = datetime.utcnow()
|
||||||
p1 = Post(body = "post from john", author = u1, timestamp = utcnow + timedelta(seconds = 1))
|
p1 = Post(body = "post from john", author = u1, timestamp = utcnow + timedelta(seconds = 1))
|
||||||
p2 = Post(body = "post from susan", author = u2, timestamp = utcnow + timedelta(seconds = 2))
|
p2 = Post(body = "post from susan", author = u2, timestamp = utcnow + timedelta(seconds = 2))
|
||||||
p3 = Post(body = "post from mary", author = u3, timestamp = utcnow + timedelta(seconds = 3))
|
p3 = Post(body = "post from mary", author = u3, timestamp = utcnow + timedelta(seconds = 3))
|
||||||
p4 = Post(body = "post from david", author = u4, timestamp = utcnow + timedelta(seconds = 4))
|
p4 = Post(body = "post from david", author = u4, timestamp = utcnow + timedelta(seconds = 4))
|
||||||
db.session.add(p1)
|
db.session.add(p1)
|
||||||
db.session.add(p2)
|
db.session.add(p2)
|
||||||
db.session.add(p3)
|
db.session.add(p3)
|
||||||
db.session.add(p4)
|
db.session.add(p4)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
# setup the followers
|
# setup the followers
|
||||||
u1.follow(u1) # john follows himself
|
u1.follow(u1) # john follows himself
|
||||||
u1.follow(u2) # john follows susan
|
u1.follow(u2) # john follows susan
|
||||||
u1.follow(u4) # john follows david
|
u1.follow(u4) # john follows david
|
||||||
u2.follow(u2) # susan follows herself
|
u2.follow(u2) # susan follows herself
|
||||||
u2.follow(u3) # susan follows mary
|
u2.follow(u3) # susan follows mary
|
||||||
u3.follow(u3) # mary follows herself
|
u3.follow(u3) # mary follows herself
|
||||||
u3.follow(u4) # mary follows david
|
u3.follow(u4) # mary follows david
|
||||||
u4.follow(u4) # david follows himself
|
u4.follow(u4) # david follows himself
|
||||||
db.session.add(u1)
|
db.session.add(u1)
|
||||||
db.session.add(u2)
|
db.session.add(u2)
|
||||||
db.session.add(u3)
|
db.session.add(u3)
|
||||||
db.session.add(u4)
|
db.session.add(u4)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
# check the followed posts of each user
|
# check the followed posts of each user
|
||||||
f1 = u1.followed_posts().all()
|
f1 = u1.followed_posts().all()
|
||||||
f2 = u2.followed_posts().all()
|
f2 = u2.followed_posts().all()
|
||||||
f3 = u3.followed_posts().all()
|
f3 = u3.followed_posts().all()
|
||||||
f4 = u4.followed_posts().all()
|
f4 = u4.followed_posts().all()
|
||||||
assert len(f1) == 3
|
assert len(f1) == 3
|
||||||
assert len(f2) == 2
|
assert len(f2) == 2
|
||||||
assert len(f3) == 2
|
assert len(f3) == 2
|
||||||
assert len(f4) == 1
|
assert len(f4) == 1
|
||||||
assert f1 == [p4, p2, p1]
|
assert f1 == [p4, p2, p1]
|
||||||
assert f2 == [p3, p2]
|
assert f2 == [p3, p2]
|
||||||
assert f3 == [p4, p3]
|
assert f3 == [p4, p3]
|
||||||
assert f4 == [p4]
|
assert f4 == [p4]
|
||||||
|
|
||||||
|
def test_translation(self):
|
||||||
|
assert microsoft_translate(u'English', 'en', 'es') == u'Inglés'
|
||||||
|
assert microsoft_translate(u'Español', 'es', 'en') == u'Spanish'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
Loading…
Reference in New Issue