support for Python 3.3
This commit is contained in:
parent
f9133b984e
commit
61a486d2ea
@ -33,8 +33,6 @@ dist = pkg_resources.get_distribution("isso")
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
import httplib
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from os.path import dirname, join
|
from os.path import dirname, join
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
@ -73,7 +71,7 @@ rules = Map([
|
|||||||
|
|
||||||
class Isso(object):
|
class Isso(object):
|
||||||
|
|
||||||
salt = "Eech7co8Ohloopo9Ol6baimi"
|
salt = b"Eech7co8Ohloopo9Ol6baimi"
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
# from isso import compat
|
# from isso import compat
|
||||||
# from isso.compat import text_type as str, string_types
|
from isso.compat import text_type as str, string_types
|
||||||
|
|
||||||
str = unicode
|
|
||||||
string_types = (unicode, str)
|
|
||||||
|
|
||||||
|
|
||||||
# @compat.implements_to_string
|
# @compat.implements_to_string
|
||||||
|
21
isso/compat.py
Normal file
21
isso/compat.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
PY2K = sys.version_info[0] == 2
|
||||||
|
|
||||||
|
if not PY2K:
|
||||||
|
# iterkeys = lambda d: iter(d.keys())
|
||||||
|
# iteritems = lambda d: iter(d.items())
|
||||||
|
|
||||||
|
text_type = str
|
||||||
|
string_types = (str, )
|
||||||
|
|
||||||
|
buffer = memoryview
|
||||||
|
else:
|
||||||
|
# iterkeys = lambda d: d.iterkeys()
|
||||||
|
# iteritems = lambda d: d.iteritems()
|
||||||
|
|
||||||
|
text_type = unicode
|
||||||
|
string_types = (str, unicode)
|
||||||
|
|
||||||
|
buffer = buffer
|
18
isso/core.py
18
isso/core.py
@ -6,16 +6,11 @@ import io
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import binascii
|
import binascii
|
||||||
|
|
||||||
import thread
|
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import smtplib
|
import smtplib
|
||||||
|
|
||||||
import httplib
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -23,6 +18,19 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
uwsgi = None
|
uwsgi = None
|
||||||
|
|
||||||
|
from isso.compat import PY2K
|
||||||
|
|
||||||
|
if PY2K:
|
||||||
|
import thread
|
||||||
|
|
||||||
|
import httplib
|
||||||
|
import urlparse
|
||||||
|
else:
|
||||||
|
import _thread as thread
|
||||||
|
|
||||||
|
import http.client as httplib
|
||||||
|
import urllib.parse as urlparse
|
||||||
|
|
||||||
from isso import notify, colors
|
from isso import notify, colors
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ import hashlib
|
|||||||
import binascii
|
import binascii
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
|
||||||
def _bin_to_long(x):
|
def _bin_to_long(x):
|
||||||
"""
|
"""
|
||||||
@ -76,7 +78,7 @@ def _pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
|||||||
def F(i):
|
def F(i):
|
||||||
def U():
|
def U():
|
||||||
u = salt + struct.pack(b'>I', i)
|
u = salt + struct.pack(b'>I', i)
|
||||||
for j in xrange(int(iterations)):
|
for j in range(int(iterations)):
|
||||||
u = _fast_hmac(password, u, digest).digest()
|
u = _fast_hmac(password, u, digest).digest()
|
||||||
yield _bin_to_long(u)
|
yield _bin_to_long(u)
|
||||||
return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
|
return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
|
||||||
|
@ -4,6 +4,7 @@ import time
|
|||||||
|
|
||||||
from isso.db import spam
|
from isso.db import spam
|
||||||
from isso.utils import Bloomfilter
|
from isso.utils import Bloomfilter
|
||||||
|
from isso.compat import buffer
|
||||||
|
|
||||||
|
|
||||||
class Comments:
|
class Comments:
|
||||||
@ -77,7 +78,7 @@ class Comments:
|
|||||||
'UPDATE comments SET',
|
'UPDATE comments SET',
|
||||||
','.join(key + '=' + '?' for key in data),
|
','.join(key + '=' + '?' for key in data),
|
||||||
'WHERE id=?;'],
|
'WHERE id=?;'],
|
||||||
data.values() + [id])
|
list(data.values()) + [id])
|
||||||
|
|
||||||
return self.get(id)
|
return self.get(id)
|
||||||
|
|
||||||
|
@ -11,9 +11,13 @@ import sys
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from time import mktime, strptime
|
from time import mktime, strptime
|
||||||
from urlparse import urlparse
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urlparse import urlparse
|
||||||
|
except ImportError:
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,13 +3,18 @@
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
try:
|
||||||
import httplib
|
import httplib
|
||||||
|
from urlparse import urlparse
|
||||||
|
except ImportError:
|
||||||
|
import http.client as httplib
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from string import ascii_letters, digits
|
from string import ascii_letters, digits
|
||||||
from urlparse import urlparse
|
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
import html5lib
|
import html5lib
|
||||||
|
@ -12,6 +12,8 @@ from itsdangerous import SignatureExpired, BadSignature
|
|||||||
from werkzeug.wrappers import Response
|
from werkzeug.wrappers import Response
|
||||||
from werkzeug.exceptions import abort, BadRequest
|
from werkzeug.exceptions import abort, BadRequest
|
||||||
|
|
||||||
|
from isso.compat import text_type as str
|
||||||
|
|
||||||
from isso import utils, notify, db
|
from isso import utils, notify, db
|
||||||
from isso.crypto import pbkdf2
|
from isso.crypto import pbkdf2
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ def new(app, environ, request, uri):
|
|||||||
return Response('URI does not exist', 404)
|
return Response('URI does not exist', 404)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(request.data)
|
data = json.loads(request.get_data().decode('utf-8'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return Response("No JSON object could be decoded", 400)
|
return Response("No JSON object could be decoded", 400)
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ def new(app, environ, request, uri):
|
|||||||
if data.get(field):
|
if data.get(field):
|
||||||
data[field] = cgi.escape(data[field])
|
data[field] = cgi.escape(data[field])
|
||||||
|
|
||||||
data['remote_addr'] = utils.anonymize(unicode(request.remote_addr))
|
data['remote_addr'] = utils.anonymize(str(request.remote_addr))
|
||||||
|
|
||||||
with app.lock:
|
with app.lock:
|
||||||
if uri not in app.db.threads:
|
if uri not in app.db.threads:
|
||||||
@ -82,14 +84,14 @@ def new(app, environ, request, uri):
|
|||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
href = (app.conf.get('general', 'host').rstrip("/") + uri + "#isso-%i" % rv["id"])
|
href = (app.conf.get('general', 'host').rstrip("/") + uri + "#isso-%i" % rv["id"])
|
||||||
app.notify(title, notify.format(rv, href, utils.anonymize(unicode(request.remote_addr))))
|
app.notify(title, notify.format(rv, href, utils.anonymize(str(request.remote_addr))))
|
||||||
|
|
||||||
# save checksum of text into cookie, so mallory can't modify/delete a comment, if
|
# save checksum of text into cookie, so mallory can't modify/delete a comment, if
|
||||||
# he add a comment, then removed it but not the signed cookie.
|
# he add a comment, then removed it but not the signed cookie.
|
||||||
checksum = hashlib.md5(rv["text"].encode('utf-8')).hexdigest()
|
checksum = hashlib.md5(rv["text"].encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
rv["text"] = app.markdown(rv["text"])
|
rv["text"] = app.markdown(rv["text"])
|
||||||
rv["hash"] = pbkdf2(rv.get('email') or rv['remote_addr'], app.salt, 1000, 6)
|
rv["hash"] = str(pbkdf2(rv.get('email') or rv['remote_addr'], app.salt, 1000, 6))
|
||||||
|
|
||||||
for key in set(rv.keys()) - FIELDS:
|
for key in set(rv.keys()) - FIELDS:
|
||||||
rv.pop(key)
|
rv.pop(key)
|
||||||
@ -132,7 +134,7 @@ def single(app, environ, request, id):
|
|||||||
|
|
||||||
if request.method == 'PUT':
|
if request.method == 'PUT':
|
||||||
try:
|
try:
|
||||||
data = json.loads(request.data)
|
data = json.loads(request.get_data().decode('utf-8'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return Response("No JSON object could be decoded", 400)
|
return Response("No JSON object could be decoded", 400)
|
||||||
|
|
||||||
@ -181,7 +183,7 @@ def fetch(app, environ, request, uri):
|
|||||||
|
|
||||||
for item in rv:
|
for item in rv:
|
||||||
|
|
||||||
item['hash'] = pbkdf2(item['email'] or item['remote_addr'], app.salt, 1000, 6)
|
item['hash'] = str(pbkdf2(item['email'] or item['remote_addr'], app.salt, 1000, 6))
|
||||||
|
|
||||||
for key in set(item.keys()) - FIELDS:
|
for key in set(item.keys()) - FIELDS:
|
||||||
item.pop(key)
|
item.pop(key)
|
||||||
@ -195,13 +197,13 @@ def fetch(app, environ, request, uri):
|
|||||||
|
|
||||||
def like(app, environ, request, id):
|
def like(app, environ, request, id):
|
||||||
|
|
||||||
nv = app.db.comments.vote(True, id, utils.anonymize(unicode(request.remote_addr)))
|
nv = app.db.comments.vote(True, id, utils.anonymize(str(request.remote_addr)))
|
||||||
return Response(json.dumps(nv), 200)
|
return Response(json.dumps(nv), 200)
|
||||||
|
|
||||||
|
|
||||||
def dislike(app, environ, request, id):
|
def dislike(app, environ, request, id):
|
||||||
|
|
||||||
nv = app.db.comments.vote(False, id, utils.anonymize(unicode(request.remote_addr)))
|
nv = app.db.comments.vote(False, id, utils.anonymize(str(request.remote_addr)))
|
||||||
return Response(json.dumps(nv), 200)
|
return Response(json.dumps(nv), 200)
|
||||||
|
|
||||||
|
|
||||||
@ -217,4 +219,4 @@ def count(app, environ, request, uri):
|
|||||||
|
|
||||||
|
|
||||||
def checkip(app, env, req):
|
def checkip(app, env, req):
|
||||||
return Response(utils.anonymize(unicode(req.remote_addr)), 200)
|
return Response(utils.anonymize(str(req.remote_addr)), 200)
|
||||||
|
6
setup.py
6
setup.py
@ -7,6 +7,9 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
requires = ['Jinja2>=2.7', 'werkzeug>=0.9', 'itsdangerous', 'misaka', 'html5lib']
|
requires = ['Jinja2>=2.7', 'werkzeug>=0.9', 'itsdangerous', 'misaka', 'html5lib']
|
||||||
|
|
||||||
|
if (3, 0) <= sys.version_info < (3, 3):
|
||||||
|
raise SystemExit("Python 3.0, 3.1 and 3.2 are not supported")
|
||||||
|
|
||||||
if sys.version_info < (3, 0):
|
if sys.version_info < (3, 0):
|
||||||
requires += ['ipaddress', 'configparser']
|
requires += ['ipaddress', 'configparser']
|
||||||
|
|
||||||
@ -28,7 +31,8 @@ setup(
|
|||||||
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
|
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
|
||||||
"License :: OSI Approved :: BSD License",
|
"License :: OSI Approved :: BSD License",
|
||||||
"Programming Language :: Python :: 2.6",
|
"Programming Language :: Python :: 2.6",
|
||||||
"Programming Language :: Python :: 2.7"
|
"Programming Language :: Python :: 2.7",
|
||||||
|
"Programming Language :: Python :: 3.3"
|
||||||
],
|
],
|
||||||
install_requires=requires,
|
install_requires=requires,
|
||||||
entry_points={
|
entry_points={
|
||||||
|
@ -3,10 +3,14 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import urllib
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
except ImportError:
|
||||||
|
from urllib import urlencode
|
||||||
|
|
||||||
from werkzeug.test import Client
|
from werkzeug.test import Client
|
||||||
from werkzeug.wrappers import Response
|
from werkzeug.wrappers import Response
|
||||||
|
|
||||||
@ -16,6 +20,8 @@ from isso.views import comment
|
|||||||
utils.heading = lambda *args: "Untitled."
|
utils.heading = lambda *args: "Untitled."
|
||||||
utils.urlexists = lambda *args: True
|
utils.urlexists = lambda *args: True
|
||||||
|
|
||||||
|
loads = lambda data: json.loads(data.decode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
class FakeIP(object):
|
class FakeIP(object):
|
||||||
|
|
||||||
@ -56,7 +62,7 @@ class TestComments(unittest.TestCase):
|
|||||||
r = self.get('/id/1')
|
r = self.get('/id/1')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
rv = json.loads(r.data)
|
rv = loads(r.data)
|
||||||
|
|
||||||
assert rv['id'] == 1
|
assert rv['id'] == 1
|
||||||
assert rv['text'] == '<p>Lorem ipsum ...</p>\n'
|
assert rv['text'] == '<p>Lorem ipsum ...</p>\n'
|
||||||
@ -66,9 +72,9 @@ class TestComments(unittest.TestCase):
|
|||||||
rv = self.post('/new?uri=%2Fpath%2F', data=json.dumps({'text': 'Lorem ipsum ...'}))
|
rv = self.post('/new?uri=%2Fpath%2F', data=json.dumps({'text': 'Lorem ipsum ...'}))
|
||||||
|
|
||||||
assert rv.status_code == 201
|
assert rv.status_code == 201
|
||||||
assert len(filter(lambda header: header[0] == 'Set-Cookie', rv.headers)) == 1
|
assert any(filter(lambda header: header[0] == 'Set-Cookie', rv.headers))
|
||||||
|
|
||||||
rv = json.loads(rv.data)
|
rv = loads(rv.data)
|
||||||
|
|
||||||
assert rv["mode"] == 1
|
assert rv["mode"] == 1
|
||||||
assert rv["text"] == '<p>Lorem ipsum ...</p>\n'
|
assert rv["text"] == '<p>Lorem ipsum ...</p>\n'
|
||||||
@ -79,9 +85,9 @@ class TestComments(unittest.TestCase):
|
|||||||
b = self.post('/new?uri=test', data=json.dumps({'text': '...'}))
|
b = self.post('/new?uri=test', data=json.dumps({'text': '...'}))
|
||||||
c = self.post('/new?uri=test', data=json.dumps({'text': '...'}))
|
c = self.post('/new?uri=test', data=json.dumps({'text': '...'}))
|
||||||
|
|
||||||
assert json.loads(a.data)["id"] == 1
|
assert loads(a.data)["id"] == 1
|
||||||
assert json.loads(b.data)["id"] == 2
|
assert loads(b.data)["id"] == 2
|
||||||
assert json.loads(c.data)["id"] == 3
|
assert loads(c.data)["id"] == 3
|
||||||
|
|
||||||
def testCreateAndGetMultiple(self):
|
def testCreateAndGetMultiple(self):
|
||||||
|
|
||||||
@ -91,7 +97,7 @@ class TestComments(unittest.TestCase):
|
|||||||
r = self.get('/?uri=%2Fpath%2F')
|
r = self.get('/?uri=%2Fpath%2F')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
rv = json.loads(r.data)
|
rv = loads(r.data)
|
||||||
assert len(rv) == 20
|
assert len(rv) == 20
|
||||||
|
|
||||||
def testGetInvalid(self):
|
def testGetInvalid(self):
|
||||||
@ -109,7 +115,7 @@ class TestComments(unittest.TestCase):
|
|||||||
r = self.get('/id/1?plain=1')
|
r = self.get('/id/1?plain=1')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
rv = json.loads(r.data)
|
rv = loads(r.data)
|
||||||
assert rv['text'] == 'Hello World'
|
assert rv['text'] == 'Hello World'
|
||||||
assert rv['author'] == 'me'
|
assert rv['author'] == 'me'
|
||||||
assert rv['website'] == 'http://example.com/'
|
assert rv['website'] == 'http://example.com/'
|
||||||
@ -120,7 +126,7 @@ class TestComments(unittest.TestCase):
|
|||||||
self.post('/new?uri=%2Fpath%2F', data=json.dumps({'text': 'Lorem ipsum ...'}))
|
self.post('/new?uri=%2Fpath%2F', data=json.dumps({'text': 'Lorem ipsum ...'}))
|
||||||
r = self.delete('/id/1')
|
r = self.delete('/id/1')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert json.loads(r.data) == None
|
assert loads(r.data) == None
|
||||||
assert self.get('/id/1').status_code == 404
|
assert self.get('/id/1').status_code == 404
|
||||||
|
|
||||||
def testDeleteWithReference(self):
|
def testDeleteWithReference(self):
|
||||||
@ -131,8 +137,7 @@ class TestComments(unittest.TestCase):
|
|||||||
|
|
||||||
r = client.delete('/id/1')
|
r = client.delete('/id/1')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
print r.data
|
assert loads(r.data)['mode'] == 4
|
||||||
assert json.loads(r.data)['mode'] == 4
|
|
||||||
|
|
||||||
assert self.get('/?uri=%2Fpath%2F&id=1').status_code == 200
|
assert self.get('/?uri=%2Fpath%2F&id=1').status_code == 200
|
||||||
assert self.get('/?uri=%2Fpath%2F&id=2').status_code == 200
|
assert self.get('/?uri=%2Fpath%2F&id=2').status_code == 200
|
||||||
@ -175,11 +180,11 @@ class TestComments(unittest.TestCase):
|
|||||||
paths = ['/sub/path/', '/path.html', '/sub/path.html', 'path', '/']
|
paths = ['/sub/path/', '/path.html', '/sub/path.html', 'path', '/']
|
||||||
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
assert self.post('/new?' + urllib.urlencode({'uri': path}),
|
assert self.post('/new?' + urlencode({'uri': path}),
|
||||||
data=json.dumps({'text': '...'})).status_code == 201
|
data=json.dumps({'text': '...'})).status_code == 201
|
||||||
|
|
||||||
for i, path in enumerate(paths):
|
for i, path in enumerate(paths):
|
||||||
assert self.get('/?' + urllib.urlencode({'uri': path})).status_code == 200
|
assert self.get('/?' + urlencode({'uri': path})).status_code == 200
|
||||||
assert self.get('/id/%i' % (i + 1)).status_code == 200
|
assert self.get('/id/%i' % (i + 1)).status_code == 200
|
||||||
|
|
||||||
def testDeleteAndCreateByDifferentUsersButSamePostId(self):
|
def testDeleteAndCreateByDifferentUsersButSamePostId(self):
|
||||||
@ -201,9 +206,9 @@ class TestComments(unittest.TestCase):
|
|||||||
c = self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "Ccc", "email": "..."}))
|
c = self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "Ccc", "email": "..."}))
|
||||||
|
|
||||||
assert a.status_code == b.status_code == c.status_code == 201
|
assert a.status_code == b.status_code == c.status_code == 201
|
||||||
a = json.loads(a.data)
|
a = loads(a.data)
|
||||||
b = json.loads(b.data)
|
b = loads(b.data)
|
||||||
c = json.loads(c.data)
|
c = loads(c.data)
|
||||||
|
|
||||||
assert a['hash'] != '192.168.1.1'
|
assert a['hash'] != '192.168.1.1'
|
||||||
assert a['hash'] == b['hash']
|
assert a['hash'] == b['hash']
|
||||||
@ -214,12 +219,12 @@ class TestComments(unittest.TestCase):
|
|||||||
rv = self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "..."}))
|
rv = self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "..."}))
|
||||||
assert rv.status_code == 201
|
assert rv.status_code == 201
|
||||||
|
|
||||||
rv = json.loads(rv.data)
|
rv = loads(rv.data)
|
||||||
|
|
||||||
for key in comment.FIELDS:
|
for key in comment.FIELDS:
|
||||||
rv.pop(key)
|
rv.pop(key)
|
||||||
|
|
||||||
assert rv.keys() == []
|
assert not any(rv.keys())
|
||||||
|
|
||||||
def testCounts(self):
|
def testCounts(self):
|
||||||
|
|
||||||
@ -228,14 +233,14 @@ class TestComments(unittest.TestCase):
|
|||||||
|
|
||||||
rv = self.get('/count?uri=%2Fpath%2F')
|
rv = self.get('/count?uri=%2Fpath%2F')
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data) == 1
|
assert loads(rv.data) == 1
|
||||||
|
|
||||||
for x in range(3):
|
for x in range(3):
|
||||||
self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "..."}))
|
self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "..."}))
|
||||||
|
|
||||||
rv = self.get('/count?uri=%2Fpath%2F')
|
rv = self.get('/count?uri=%2Fpath%2F')
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data) == 4
|
assert loads(rv.data) == 4
|
||||||
|
|
||||||
for x in range(4):
|
for x in range(4):
|
||||||
self.delete('/id/%i' % (x + 1))
|
self.delete('/id/%i' % (x + 1))
|
||||||
@ -247,7 +252,7 @@ class TestComments(unittest.TestCase):
|
|||||||
self.post('/new?uri=test', data=json.dumps({"text": "Tpyo"}))
|
self.post('/new?uri=test', data=json.dumps({"text": "Tpyo"}))
|
||||||
|
|
||||||
self.put('/id/1', data=json.dumps({"text": "Tyop"}))
|
self.put('/id/1', data=json.dumps({"text": "Tyop"}))
|
||||||
assert json.loads(self.get('/id/1').data)["text"] == "<p>Tyop</p>\n"
|
assert loads(self.get('/id/1').data)["text"] == "<p>Tyop</p>\n"
|
||||||
|
|
||||||
self.put('/id/1', data=json.dumps({"text": "Typo"}))
|
self.put('/id/1', data=json.dumps({"text": "Typo"}))
|
||||||
assert json.loads(self.get('/id/1').data)["text"] == "<p>Typo</p>\n"
|
assert loads(self.get('/id/1').data)["text"] == "<p>Typo</p>\n"
|
||||||
|
@ -14,6 +14,8 @@ from isso import Isso, notify, utils, core
|
|||||||
utils.heading = lambda *args: "Untitled."
|
utils.heading = lambda *args: "Untitled."
|
||||||
utils.urlexists = lambda *args: True
|
utils.urlexists = lambda *args: True
|
||||||
|
|
||||||
|
loads = lambda data: json.loads(data.decode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
class FakeIP(object):
|
class FakeIP(object):
|
||||||
|
|
||||||
@ -51,7 +53,7 @@ class TestVote(unittest.TestCase):
|
|||||||
def testZeroLikes(self):
|
def testZeroLikes(self):
|
||||||
|
|
||||||
rv = self.makeClient("127.0.0.1").post("/new?uri=test", data=json.dumps({"text": "..."}))
|
rv = self.makeClient("127.0.0.1").post("/new?uri=test", data=json.dumps({"text": "..."}))
|
||||||
assert json.loads(rv.data)['likes'] == json.loads(rv.data)['dislikes'] == 0
|
assert loads(rv.data)['likes'] == loads(rv.data)['dislikes'] == 0
|
||||||
|
|
||||||
def testSingleLike(self):
|
def testSingleLike(self):
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ class TestVote(unittest.TestCase):
|
|||||||
rv = self.makeClient("0.0.0.0").post("/id/1/like")
|
rv = self.makeClient("0.0.0.0").post("/id/1/like")
|
||||||
|
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data)["likes"] == 1
|
assert loads(rv.data)["likes"] == 1
|
||||||
|
|
||||||
def testSelfLike(self):
|
def testSelfLike(self):
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ class TestVote(unittest.TestCase):
|
|||||||
rv = bob.post('/id/1/like')
|
rv = bob.post('/id/1/like')
|
||||||
|
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data)["likes"] == 0
|
assert loads(rv.data)["likes"] == 0
|
||||||
|
|
||||||
def testMultipleLikes(self):
|
def testMultipleLikes(self):
|
||||||
|
|
||||||
@ -76,12 +78,12 @@ class TestVote(unittest.TestCase):
|
|||||||
for num in range(15):
|
for num in range(15):
|
||||||
rv = self.makeClient("1.2.%i.0" % num).post('/id/1/like')
|
rv = self.makeClient("1.2.%i.0" % num).post('/id/1/like')
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data)["likes"] == num + 1
|
assert loads(rv.data)["likes"] == num + 1
|
||||||
|
|
||||||
def testVoteOnNonexistentComment(self):
|
def testVoteOnNonexistentComment(self):
|
||||||
rv = self.makeClient("1.2.3.4").post('/id/1/like')
|
rv = self.makeClient("1.2.3.4").post('/id/1/like')
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data) == None
|
assert loads(rv.data) == None
|
||||||
|
|
||||||
def testTooManyLikes(self):
|
def testTooManyLikes(self):
|
||||||
|
|
||||||
@ -91,14 +93,14 @@ class TestVote(unittest.TestCase):
|
|||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
|
|
||||||
if num >= 142:
|
if num >= 142:
|
||||||
assert json.loads(rv.data)["likes"] == 142
|
assert loads(rv.data)["likes"] == 142
|
||||||
else:
|
else:
|
||||||
assert json.loads(rv.data)["likes"] == num + 1
|
assert loads(rv.data)["likes"] == num + 1
|
||||||
|
|
||||||
def testDislike(self):
|
def testDislike(self):
|
||||||
self.makeClient("127.0.0.1").post("/new?uri=test", data=json.dumps({"text": "..."}))
|
self.makeClient("127.0.0.1").post("/new?uri=test", data=json.dumps({"text": "..."}))
|
||||||
rv = self.makeClient("1.2.3.4").post('/id/1/dislike')
|
rv = self.makeClient("1.2.3.4").post('/id/1/dislike')
|
||||||
|
|
||||||
assert rv.status_code == 200
|
assert rv.status_code == 200
|
||||||
assert json.loads(rv.data)['likes'] == 0
|
assert loads(rv.data)['likes'] == 0
|
||||||
assert json.loads(rv.data)['dislikes'] == 1
|
assert loads(rv.data)['dislikes'] == 1
|
||||||
|
Loading…
Reference in New Issue
Block a user