Skip to content

Commit

Permalink
Merge pull request #57 from Alkalit/unit_tests
Browse files Browse the repository at this point in the history
Unit tests
  • Loading branch information
Arthur Koziel committed Mar 8, 2015
2 parents 173f01f + 02314e7 commit 20dc61a
Show file tree
Hide file tree
Showing 11 changed files with 733 additions and 129 deletions.
16 changes: 9 additions & 7 deletions disqus/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import urllib
import urllib2
import json

from django.utils.six.moves.urllib.parse import urlencode
from django.utils.six.moves.urllib.request import urlopen
from django.core.management.base import CommandError
from django.utils import simplejson as json
from django.conf import settings

from django.core.management.base import CommandError


def call(method, data, post=False):
"""
Expand All @@ -14,12 +16,12 @@ def call(method, data, post=False):
if post:
# POST request
url += "/"
data = urllib.urlencode(data)
data = urlencode(data)
else:
# GET request
url += "?%s" % urllib.urlencode(data)
url += "?%s" % urlencode(data)
data = ''
res = json.load(urllib2.urlopen(url, data))
res = json.load(urlopen(url, data))
if not res['succeeded']:
raise CommandError("'%s' failed: %s\nData: %s" % (method, res['code'], data))
return res['message']
37 changes: 21 additions & 16 deletions disqus/api.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
from urllib import urlencode
import urllib2
import json

try:
import json
except ImportError:
from django.utils import simplejson as json
from django.utils.six.moves.urllib.parse import urlencode
from django.utils.six.moves.urllib.error import URLError
from django.utils.six.moves.urllib.request import (
ProxyHandler,
Request,
urlopen,
build_opener,
install_opener
)


# A custom ProxyHandler that will not auto-detect proxy settings
proxy_support = ProxyHandler({})
opener = build_opener(proxy_support)
install_opener(opener)

# A custom ProxyHandler for the urllib2 module that will not
# auto-detect proxy settings
proxy_support = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_support)
urllib2.install_opener(opener)

class DisqusException(Exception):
"""Exception raised for errors with the DISQUS API."""
Expand Down Expand Up @@ -59,15 +64,15 @@ def call_method(**kwargs):

def _get_request(self, request_url, request_method, **params):
"""
Return a urllib2.Request object that has the GET parameters
Return a Request object that has the GET parameters
attached to the url or the POST data attached to the object.
"""
if request_method == 'GET':
if params:
request_url += '&%s' % urlencode(params)
request = urllib2.Request(request_url)
request = Request(request_url)
elif request_method == 'POST':
request = urllib2.Request(request_url, urlencode(params,doseq=1))
request = Request(request_url, urlencode(params, doseq=1))
return request

def call(self, method, **params):
Expand All @@ -79,8 +84,8 @@ def call(self, method, **params):
url = self.api_url % method
request = self._get_request(url, self.METHODS[method], **params)
try:
response = urllib2.urlopen(request)
except urllib2.URLError, e:
response = urlopen(request)
except URLError:
raise
else:
response_json = json.loads(response.read())
Expand Down
10 changes: 6 additions & 4 deletions disqus/management/commands/disqus_dumpdata.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import print_function

import json
from optparse import make_option

from django.core.management.base import NoArgsCommand, CommandError
from django.utils import simplejson as json

from disqus.api import DisqusClient

Expand All @@ -26,8 +28,8 @@ def handle(self, **options):
filter_ = options.get('filter')
exclude = options.get('exclude')

# Get a list of all forums for an API key. Each API key can have
# multiple forums associated. This application only supports the one
# Get a list of all forums for an API key. Each API key can have
# multiple forums associated. This application only supports the one
# set in the DISQUS_WEBSITE_SHORTNAME variable
forum_list = client.get_forum_list(user_api_key=settings.DISQUS_API_KEY)
try:
Expand All @@ -54,4 +56,4 @@ def handle(self, **options):
else:
start += step
posts.append(new_posts)
print json.dumps(posts, indent=indent)
print(json.dumps(posts, indent=indent))
31 changes: 19 additions & 12 deletions disqus/management/commands/disqus_export.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
from __future__ import print_function

import json
from optparse import make_option
import os.path

from django.conf import settings
from django.contrib import comments
from django.contrib.sites.models import Site
from django.core.management.base import NoArgsCommand
from django.utils import simplejson as json
from django.core.management.base import NoArgsCommand, CommandError
try:
from django.utils.encoding import force_text
except ImportError:
# Django < 1.5
from django.utils.encoding import force_unicode as force_text

from disqus.api import DisqusClient

Expand All @@ -27,7 +34,7 @@ def _get_comments_to_export(self, last_export_id=None):
qs = comments.get_model().objects.order_by('pk')\
.filter(is_public=True, is_removed=False)
if last_export_id is not None:
print "Resuming after comment %s" % str(last_export_id)
print("Resuming after comment %s" % str(last_export_id))
qs = qs.filter(id__gt=last_export_id)
return qs

Expand All @@ -37,7 +44,7 @@ def _get_last_state(self, state_file):
fp = open(state_file)
try:
state = int(fp.read())
print "Found previous state: %d" % (state,)
print("Found previous state: %d" % (state,))
finally:
fp.close()
return state
Expand All @@ -64,18 +71,18 @@ def handle(self, **options):
comments = self._get_comments_to_export(last_exported_id)
comments_count = comments.count()
if verbosity >= 1:
print "Exporting %d comment(s)" % comments_count
print("Exporting %d comment(s)" % comments_count)

# if this is a dry run, we output the comments and exit
if dry_run:
print comments
print("%s" % (comments,))
return
# if no comments were found we also exit
if not comments_count:
return

# Get a list of all forums for an API key. Each API key can have
# multiple forums associated. This application only supports the one
# Get a list of all forums for an API key. Each API key can have
# multiple forums associated. This application only supports the one
# set in the DISQUS_WEBSITE_SHORTNAME variable
forum_list = client.get_forum_list(user_api_key=settings.DISQUS_API_KEY)
try:
Expand All @@ -93,7 +100,7 @@ def handle(self, **options):

for comment in comments:
if verbosity >= 1:
print "Exporting comment '%s'" % comment
print("Exporting comment '%s'" % comment)

# Try to find a thread with the comments URL.
url = 'http://%s%s' % (
Expand All @@ -104,13 +111,13 @@ def handle(self, **options):
forum_api_key=forum_api_key)

# if no thread with the URL could be found, we create a new one.
# to do this, we first need to create the thread and then
# to do this, we first need to create the thread and then
# update the thread with a URL.
if not thread:
thread = client.thread_by_identifier(
forum_api_key=forum_api_key,
identifier=unicode(comment.content_object),
title=unicode(comment.content_object),
identifier=force_text(comment.content_object),
title=force_text(comment.content_object),
)['thread']
client.update_thread(
forum_api_key=forum_api_key,
Expand Down
6 changes: 6 additions & 0 deletions disqus/templates/disqus/disqus_dev.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% if disqus_url %}
<script type="text/javascript">
var disqus_developer = 1;
var disqus_url = '{{ disqus_url }}';
</script>
{% endif %}
6 changes: 6 additions & 0 deletions disqus/templates/disqus/disqus_sso.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script type="text/javascript">
var disqus_config = function() {
this.page.remote_auth_s3 = "{{ message }} {{ sig }} {{ timestamp }}";
this.page.api_key = "{{ pub_key }}";
}
</script>
82 changes: 48 additions & 34 deletions disqus/templatetags/disqus_tags.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import base64
import hashlib
import hmac
import simplejson
import json
import time

from django import template
from django.conf import settings
from django.contrib.sites.models import Site
from django.utils.functional import curry
from django.utils.encoding import force_unicode

register = template.Library()


# Set the disqus_developer variable to 0/1. Default is 0
@register.simple_tag(takes_context=True)
def set_disqus_developer(context, disqus_developer):
Expand Down Expand Up @@ -45,66 +44,81 @@ def set_disqus_category_id(context, disqus_category_id):

def get_config(context):
"""
return the formatted javascript for any disqus config variables
Return the formatted javascript for any disqus config variables.
"""
conf_vars = ['disqus_developer', 'disqus_identifier', 'disqus_url',
'disqus_title', 'disqus_category_id']

output = []
for item in conf_vars:
if item in context:
output.append('\tvar %s = "%s";' % (item, context[item]))

conf_vars = ['disqus_developer',
'disqus_identifier',
'disqus_url',
'disqus_title',
'disqus_category_id'
]

js = '\tvar {} = "{}";'

output = [js.format(item, context[item]) for item in conf_vars \
if item in context]

return '\n'.join(output)

@register.simple_tag(takes_context=True)
@register.inclusion_tag('disqus/disqus_dev.html', takes_context=True)
def disqus_dev(context):
"""
Return the HTML/js code to enable DISQUS comments on a local
development server if settings.DEBUG is True.
"""

if settings.DEBUG:
return """<script type="text/javascript">
var disqus_developer = 1;
var disqus_url = '//%s%s';
</script>""" % (Site.objects.get_current().domain, context['request'].path)
return ""
disqus_url = '//{}{}'.format(
Site.objects.get_current().domain,
context['request'].path
)

@register.simple_tag(takes_context=True)
return {'disqus_url': disqus_url}

return {}

@register.inclusion_tag('disqus/disqus_sso.html', takes_context=True)
def disqus_sso(context):
"""
Return the HTML/js code to enable DISQUS SSO - so logged in users on
your site can be logged in to disqus seemlessly.
"""
# we have to make it str rather than unicode or the HMAC blows up
DISQUS_SECRET_KEY = str(getattr(settings, 'DISQUS_SECRET_KEY', None))

DISQUS_SECRET_KEY = getattr(settings, 'DISQUS_SECRET_KEY', None)
if DISQUS_SECRET_KEY is None:
return "<p>You need to set DISQUS_SECRET_KEY before you can use SSO</p>"

DISQUS_PUBLIC_KEY = getattr(settings, 'DISQUS_PUBLIC_KEY', None)
if DISQUS_PUBLIC_KEY is None:
return "<p>You need to set DISQUS_PUBLIC_KEY before you can use SSO</p>"

user = context['user']

if user.is_anonymous():
return ""

# create a JSON packet of our data attributes
data = simplejson.dumps({
data = json.dumps({
'id': user.id,
'username': user.username,
'email': user.email,
})

# encode the data to base64
message = base64.b64encode(data)
message = base64.b64encode(data.encode('utf-8'))

# generate a timestamp for signing the message
timestamp = int(time.time())

key = DISQUS_SECRET_KEY.encode('utf-8')
msg = ('%s %s' % (message, timestamp)).encode('utf-8')
digestmod = hashlib.sha1

# generate our hmac signature
sig = hmac.HMAC(DISQUS_SECRET_KEY, '%s %s' % (message, timestamp), hashlib.sha1).hexdigest()

# return a script tag to insert the sso message
return """<script type="text/javascript">
var disqus_config = function() {
this.page.remote_auth_s3 = "%(message)s %(sig)s %(timestamp)s";
this.page.api_key = "%(pub_key)s";
}
</script>""" % dict(
sig = hmac.HMAC(key, msg, digestmod).hexdigest()

return dict(
message=message,
timestamp=timestamp,
sig=sig,
Expand All @@ -118,7 +132,7 @@ def disqus_num_replies(context, shortname=''):
#disqus_thread anchor into the threads comment count.
"""
shortname = getattr(settings, 'DISQUS_WEBSITE_SHORTNAME', shortname)

return {
'shortname': shortname,
'config': get_config(context),
Expand All @@ -128,10 +142,9 @@ def disqus_num_replies(context, shortname=''):
def disqus_recent_comments(context, shortname='', num_items=5, excerpt_length=200, hide_avatars=0, avatar_size=32):
"""
Return the HTML/js code which shows recent comments.
"""
shortname = getattr(settings, 'DISQUS_WEBSITE_SHORTNAME', shortname)

return {
'shortname': shortname,
'num_items': num_items,
Expand All @@ -147,6 +160,7 @@ def disqus_show_comments(context, shortname=''):
Return the HTML code to display DISQUS comments.
"""
shortname = getattr(settings, 'DISQUS_WEBSITE_SHORTNAME', shortname)

return {
'shortname': shortname,
'config': get_config(context),
Expand Down
Loading

0 comments on commit 20dc61a

Please sign in to comment.