Skip to content
This repository has been archived by the owner on Apr 10, 2022. It is now read-only.

Commit

Permalink
Merge pull request #192 from python/develop
Browse files Browse the repository at this point in the history
Merge develop into master
  • Loading branch information
vkurup committed Sep 5, 2013
2 parents e146375 + 4fcc323 commit b3dda53
Show file tree
Hide file tree
Showing 30 changed files with 312 additions and 130 deletions.
10 changes: 10 additions & 0 deletions docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Raspberry IO Changelog
======================

Version 0.3 (2013-09-05)
------------------------

* Improve coverage to near 100% (excepting aggregator)
* Add DISQUS comments to project detail page
* Add link to RaspberryIO Twitter account
* Improve pagination throughout site
* Fabfile fixes


Version 0.2 - Open Source Release (2013-08-06)
----------------------------------------------

Expand Down
13 changes: 13 additions & 0 deletions docs/developer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,16 @@ this flattened representation of the latest revision in its own table,
and should be used in the future for any other models with a similar
structure. Using something in MPTT or similar might be better than the
current "flatten and copy" behavior, but this is what we have for now.

Comments:
---------

We use `Disqus <http://disqus.com/>`_ to allow users to comment on
individual projects. The ``DISQUS_HOSTNAME`` (in Django settings) is
set to ``http://raspberry.io` so that non-production sites can see the
commenting functionality. ``DISQUS_SHORTNAME`` is set to
``raspberryio`` for production and ``raspberryio-staging`` for the
staging site. If local developers wish to test commenting for some
reason, then they should create a DISQUS account, set up a new
shortname and use that for ``DISQUS_SHORTNAME`` in
``raspberryio.settings.local``.
4 changes: 1 addition & 3 deletions fabfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def production():
# Provided machine uses default port
env.ssh_port = 22
setup_path()
env.db = 'psf_rpi'


def setup_path():
Expand All @@ -88,12 +87,11 @@ def create_users():
user_dir = os.path.join(CONF_ROOT, "users")
for username in os.listdir(user_dir):
key_file = os.path.normpath(os.path.join(user_dir, username))
system.create_user(username, groups=['dev', 'login', ], key_file=key_file)
system.create_user(username, groups=['dev', 'login', 'admin', ], key_file=key_file)
with open(key_file, 'rt') as f:
ssh_key = f.read()
# Add ssh key for project user
files.append('%s/authorized_keys' % ssh_dir, ssh_key, use_sudo=True)
files.append(u'/etc/sudoers', r'%dev ALL=(ALL) NOPASSWD:ALL', use_sudo=True)
sudo('chown -R %s:%s %s' % (env.project_user, env.project_user, ssh_dir))


Expand Down
21 changes: 17 additions & 4 deletions raspberryio/aggregator/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
# https://docs.djangoproject.com/en/dev/topics/testing/#email-services
from __future__ import absolute_import

import datetime

from mock import patch

from django.conf import settings
Expand All @@ -12,11 +10,12 @@
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.client import Client

from django.utils.timezone import now
from django_push.subscriber.models import SubscriptionManager

from .management.commands import send_pending_approval_email
from . import models
from . import utils


class MockResponse(object):
Expand Down Expand Up @@ -60,7 +59,7 @@ def setUp(self):
for feed in [self.approved_feed, self.denied_feed, self.pending_feed, self.defunct_feed]:
feed.save()
feed_item = models.FeedItem(feed=feed, title="%s Item" % feed.title, link=feed.public_url,
date_modified=datetime.datetime.now(), guid=feed.title)
date_modified=now(), guid=feed.title)
feed_item.save()

self.client = Client()
Expand All @@ -80,3 +79,17 @@ def test_management_command_sends_email_with_pending_feeds(self):
send_pending_approval_email.Command().handle_noargs()
self.assertEqual(1, len(mail.outbox))
self.assertEqual(mail.outbox[0].to, [self.user.email])

def test_feed_type_items(self):
# 4 items were created in our default feed_type in setUp
self.assertEqual(len(self.feed_type.items()), 4)

def test_unicode_method(self):
self.assertEqual(self.approved_feed.__unicode__(), 'Approved')


class UtilsTests(TestCase):

def test_push_credentials(self):
settings.SUPERFEEDR_CREDS = ['testid', 'testsecret']
self.assertEqual(utils.push_credentials(''), ('testid', 'testsecret'))
20 changes: 20 additions & 0 deletions raspberryio/project/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@
class ProjectFormTestCase(ProjectBaseTestCase):

def setUp(self):
self.request_factory = RequestFactory()
self.project = self.create_project()

def test_placeholder_labels(self):
request = self.request_factory.get('/')
form = ProjectStepForm()
# first assert that label is shown
self.assertEqual(form.fields['title'].label, 'Title')
form.Meta.remove_labels = True
form = ProjectStepForm(request.GET, instance=self.project)
# now assert that Meta attribute removes it
self.assertEqual(form.fields['title'].label, '')

class ProjectStepFormTestCase(ProjectBaseTestCase):

Expand Down Expand Up @@ -99,6 +109,16 @@ def test_multiple_images_valid(self):
else:
self.fail('Form should be valid')

def test_bad_video_url(self):
post_data = {
'title': self.get_random_string(),
'content': self.get_random_string(),
'video': 'http://example.com/badurl',
}
request = self.request_factory.post('/', post_data)
form = ProjectStepForm(request.POST, instance=self.project_step)
self.assertFalse(form.is_valid())


class ProjectImageFormTestCase(ProjectBaseTestCase):

Expand Down
28 changes: 28 additions & 0 deletions raspberryio/project/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import timedelta

from django.core.urlresolvers import reverse
from django.test.client import RequestFactory

from mezzanine.utils.timezone import now
Expand Down Expand Up @@ -42,6 +43,15 @@ def test_is_published_false(self):
def test_default_draft(self):
self.assertEqual(self.project.status, CONTENT_STATUS_DRAFT)

def test_video_params(self):
# first test that garbage input doesn't work
self.assertEqual(self.project.embed_url, None)
# now test a real video URL
video_id = "6BbufUp_HNs"
video_url = "http://www.youtube.com/watch?v=%s" % video_id
project = self.create_project(featured_video=video_url)
self.assertEqual(project.video_id, video_id)
self.assertEqual(project.embed_url, 'http://www.youtube.com/embed/%s?wmode=transparent' % video_id)

class ProjectStepTestCase(ProjectBaseTestCase):

Expand Down Expand Up @@ -117,3 +127,21 @@ def test_order_number(self):
self.assertEqual(project1_step1._order, 1)
self.assertEqual(project2_step0._order, 0)
self.assertEqual(project2_step1._order, 1)

def test_absolute_url(self):
self.assertEqual(self.project_step.get_absolute_url(),
reverse('project-detail', args=[self.project.slug]))

def test_video_params(self):
# first test that garbage input doesn't work
self.assertEqual(self.project_step.embed_url, None)
# now test a real video URL
video_id = "6BbufUp_HNs"
video_url = "http://www.youtube.com/watch?v=%s" % video_id
project_step = self.create_project_step(video=video_url)
self.assertEqual(project_step.video_id, video_id)
self.assertEqual(project_step.embed_url, 'http://www.youtube.com/embed/%s?wmode=transparent' % video_id)

def test_unicode_method(self):
unicode = 'Step %d of project %s' % (self.project_step._order, self.project.title)
self.assertEqual(self.project_step.__unicode__(), unicode)
3 changes: 3 additions & 0 deletions raspberryio/project/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib.auth.decorators import login_required
from django.views.generic.list_detail import object_list
from django.core.cache import cache
from django.conf import settings

from actstream import action

Expand Down Expand Up @@ -39,6 +40,8 @@ def project_detail(request, project_slug):
raise Http404('There is no project here')
return render(request, 'project/project_detail.html', {
'project': project,
'DISQUS_SHORTNAME': settings.DISQUS_SHORTNAME,
'DISQUS_HOSTNAME': settings.DISQUS_HOSTNAME,
})


Expand Down
7 changes: 7 additions & 0 deletions raspberryio/qanda/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ def setUp(self):
question=self.question, user=self.answer_user
)

def test_unicode_method(self):
title = 'My title'
q = self.create_question(title=title)
a = self.create_answer(question=q)
self.assertEqual(q.__unicode__(), title)
self.assertEqual(a.__unicode__(), title)

def test_default_score(self):
self.assertEqual(self.answer.score, 0)

Expand Down
15 changes: 14 additions & 1 deletion raspberryio/qanda/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
from raspberryio.qanda.models import Question, Answer


class IndexViewTestCase(ViewTestMixin, QandaBaseTestCase):
url_name = 'community-index'

def setUp(self):
super(IndexViewTestCase, self).setUp()

def test_index_page(self):
question = self.create_question()
response = self.client.get(self.url)
result = response.context['questions']
self.assertEqual(set(result), set([question]))


class QuestionListViewTestCase(ViewTestMixin, QandaBaseTestCase):
url_name = 'question-list'

Expand All @@ -19,7 +32,7 @@ def test_results(self):
question3 = self.create_question()
expected_questions = set([question1, question2, question3])
response = self.client.get(self.url)
result_questions = response.context['questions']
result_questions = response.context['question_list']
self.assertEqual(set(result_questions), expected_questions)


Expand Down
6 changes: 3 additions & 3 deletions raspberryio/qanda/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import Site
from django.views.generic.list_detail import object_list

from hilbert.decorators import ajax_only
from mezzanine.utils.sites import current_site_id
Expand Down Expand Up @@ -29,9 +30,8 @@ def index(request):
@cache_on_auth(60 * 2)
def question_list(request):
questions = Question.objects.all()
return render(request, 'qanda/question_list.html', {
'questions': questions,
})
return object_list(request, queryset=questions, paginate_by=20,
template_object_name='question')


def question_detail(request, question_slug):
Expand Down
4 changes: 4 additions & 0 deletions raspberryio/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,7 @@
pass
else:
set_dynamic_settings(globals())

# Disqus
DISQUS_SHORTNAME = 'raspberryio-dev'
DISQUS_HOSTNAME = 'http://raspberry.io'
2 changes: 1 addition & 1 deletion raspberryio/settings/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

TEST_RUNNER = 'hilbert.test.CoverageRunner'

DEFAULT_TEST_LABELS = ['project', 'userprofile', 'search', 'qanda']
DEFAULT_TEST_LABELS = ['project', 'userprofile', 'search', 'qanda', 'aggregator', ]

COVERAGE_MODULES = (
'forms',
Expand Down
3 changes: 3 additions & 0 deletions raspberryio/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@
pass

EMAIL_SUBJECT_PREFIX = '[Raspberryio Prod] '

# Disqus
DISQUS_SHORTNAME = 'raspberryio'
3 changes: 3 additions & 0 deletions raspberryio/settings/staging.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@
SECRET_KEY = json.loads(config.get('secrets', 'SECRET_KEY'))
except:
pass

# Disqus
DISQUS_SHORTNAME = 'raspberryio-staging'
3 changes: 3 additions & 0 deletions raspberryio/static/js/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ $(function() {
}
});
});

// Twitter button JS
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
6 changes: 5 additions & 1 deletion raspberryio/static/less/site.less
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
@greenMedium: #8FAC3C;
@grayLightest: #edebeb;
@raspberry: #c03939;
@paginationActiveBackground: #BBBBBB;

/* Mixins
================= */
Expand Down Expand Up @@ -524,7 +525,7 @@ hr {
}
footer {
text-align: center;
font-size: 9px;
font-size: 10px;
color: @white;
padding: 3px 0;
background: url('/static/img/background.jpg');
Expand All @@ -533,6 +534,9 @@ hr {
a {
color: @white !important;
}
li {
line-height: 12px;
}
}
}

Expand Down
21 changes: 15 additions & 6 deletions raspberryio/templates/accounts/account_profile_related.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@
{% block title %}{{ user.username }}{% endblock %}
{% block body_id %}user-listing{% endblock %}

{% block main%}
{% block main %}
<header>
<div class="row">
<div class="nav-actions span12">
<a class="{% if "following" in request.get_full_path %}active{% endif %}" href="{% url 'profile-related' username=user relation='following' %}">Following</a>
<a class=" {% if "followers" in request.get_full_path %}active{% endif %}" href="{% url 'profile-related' username=user relation='followers' %}">Followers</a>
<a class=" {% if "followers" in request.get_full_path %}active{% endif %}" href="{% url 'profile-related' username=user relation='followers' %}">Followers</a>
</div>
</div>
</header>
<div class="user-list">

{% if related_users.has_other_pages %}
{% include "includes/pagination.html" with page_obj=related_users %}
{% endif %}

<div class="row user-list">
<ul>
{% for related_user in related_users %}
{% if related_user %}
Expand All @@ -25,18 +30,22 @@
{% avatar profile 150 %}
{% endwith %}
</a>
<div class="userinfo">

<div class="userinfo">
<p><a class="username" href="{{ related_user.get_absolute_url }}">{{ related_user.username }}</a></p>
{% include 'includes/relationship-status.html' with profile_user=related_user %}
</div>
</li>
{% endif %}
{% endfor %}
</ul>
{% endblock %}
</div>

{% if related_users.has_other_pages %}
{% include "includes/pagination.html" with page_obj=related_users %}
{% endif %}
{% endblock %}

{% block extra_js %}
<script src="{{ STATIC_URL }}js/update_relationship.min.js"></script>
{% endblock %}
Loading

0 comments on commit b3dda53

Please sign in to comment.