Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Django 1.8 #1214

Open
wants to merge 14 commits into
base: migrate-to-django-popolo
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ And visit http://127.0.0.1.xip.io:8000 on your host machine to use WriteIt.

### Background jobs

./manage.py celery worker
celery -A writeit worker

This handles syncing contact details from remote sources. If you
have created a new instance and the contacts do not seem to be syncing
it is probably because a celery worker is not running.

### Scheduled jobs

./manage.py celery beat
celery -A writeit beat

This sends emails to recipients and periodically re-sync contacts from
remote sources.
Expand Down
2 changes: 1 addition & 1 deletion config_examples/email_sender.sh.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ LOGDIR=$(dirname $LOGFILE)
cd /home/ubuntu/writeit/write-it/
source /home/ubuntu/.virtualenvs/writeit/bin/activate
test -d $LOGDIR || mkdir -p $LOGDIR
exec python manage.py celery beat --logfile=$LOGFILE
exec celery -A writeit beat --logfile=$LOGFILE
2 changes: 1 addition & 1 deletion global_test_case.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re

from django.test import TestCase
from django.utils.unittest import skipUnless
from unittest import skipUnless
from django.core.management import call_command
from tastypie.test import ResourceTestCase
from django.conf import settings
Expand Down
4 changes: 2 additions & 2 deletions mailit/tests/email_logging_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_it_sends_a_mail_to_the_admins_when_receiving_a_mail(self):
with patch('sys.stdin') as stdin:
stdin.attach_mock(readlines1_mock, 'readlines')

call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)

self.assertEquals(len(mail.outbox), 1)
self.assertEquals(mail.outbox[0].to[0], '[email protected]')
Expand All @@ -46,6 +46,6 @@ def test_if_there_are_no_admins_does_not_send_emails(self):
with patch('sys.stdin') as stdin:
stdin.attach_mock(readlines1_mock, 'readlines')

call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)

self.assertEquals(len(mail.outbox), 0)
10 changes: 5 additions & 5 deletions mailit/tests/handle_mails_management_command_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def test_call_command(self):
with patch('sys.stdin') as stdin:
stdin.attach_mock(readlines1_mock, 'readlines')

call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)

the_answers = Answer.objects.filter(message=identifier.outbound_message.message)
self.assertEquals(the_answers.count(), 1)
Expand All @@ -137,7 +137,7 @@ def test_call_command_does_not_include_identifier_in_content(self):
with patch('sys.stdin') as stdin:
stdin.attach_mock(readlines2_mock, 'readlines')

call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)

the_answers = Answer.objects.filter(message=identifier.outbound_message.message)
self.assertEquals(the_answers.count(), 1)
Expand All @@ -147,7 +147,7 @@ def test_call_command_does_not_include_identifier_in_content(self):
def test_it_sends_an_email_to_the_admin_if_any_failure(self):
with patch('sys.stdin') as stdin:
stdin.attach_mock(readlines3_mock, 'readlines')
call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)
content_text = ''
for line in readlines3_mock():
content_text += line
Expand All @@ -161,7 +161,7 @@ def test_it_sends_an_email_to_the_admin_if_any_failure(self):
def test_mail_admins_if_theres_a_problem(self):
with patch('sys.stdin') as stdin:
stdin.attach_mock(killer_mail, 'readlines')
call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)
self.assertEquals(len(mail.outbox), 1)
self.assertNotIn(killer_mail(), mail.outbox[0].body)
self.assertEquals(mail.outbox[0].to[0], '[email protected]')
Expand All @@ -174,7 +174,7 @@ def test_it_correctly_parses_the_to_email(self):
identifier.save()
with patch('sys.stdin') as stdin:
stdin.attach_mock(readlines4_mock, 'readlines')
call_command('handleemail', 'mailit.tests.handle_mails_management_command.StdinMock', verbosity=0)
call_command('handleemail', verbosity=0)
the_answer = Answer.objects.get(message=identifier.outbound_message.message)
self.assertNotIn('Tony', the_answer.content)
self.assertNotIn('<eduskunta-', the_answer.content)
Expand Down
18 changes: 12 additions & 6 deletions mailit/tests/plugin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,16 @@ def test_smpt_error_code_500(self):
# I'm taking it as if we should not try to send this
# message again, but for example

def test_any_other_exception(self):
@patch('mailit.mail_admins')
def test_any_other_exception(self, mail_admins):
with patch("django.core.mail.EmailMultiAlternatives.send") as send_mail:
send_mail.side_effect = Exception(401, "Something very bad")
result_of_sending, fatal_error = self.channel.send(self.outbound_message1)
self.assertFalse(result_of_sending)
self.assertTrue(fatal_error)
mail_admins.assert_called_with(
'Problem sending an email',
u"Error with outbound id 1, contact '[email protected]' and message 'Subject 1 at instance 1' and the error was '(401, 'Something very bad')'")

def test_smpt_error_code_501(self):
# to handle this kind of error
Expand Down Expand Up @@ -493,14 +497,16 @@ def test_smpt_error_code_552(self):
self.assertFalse(result_of_sending)
self.assertFalse(fatal_error)

def test_extra_logging(self):
@patch('logging.info')
@patch('mailit.mail_admins')
def test_extra_logging(self, mail_admins, info):
with patch("django.core.mail.EmailMultiAlternatives.send") as send_mail:
send_mail.side_effect = Exception("Hey this is an exception")
with patch('logging.info') as info:
expected_log = u"Error with outbound id 1, contact '[email protected]' and message 'Subject 1 at instance 1' and the error was 'Hey this is an exception'"
self.channel.send(self.outbound_message1)
expected_log = u"Error with outbound id 1, contact '[email protected]' and message 'Subject 1 at instance 1' and the error was 'Hey this is an exception'"
self.channel.send(self.outbound_message1)

info.assert_called_with(expected_log)
info.assert_called_with(expected_log)
mail_admins.assert_called_with('Problem sending an email', expected_log)


class MailitTemplateUpdateTestCase(UserSectionTestCase):
Expand Down
4 changes: 2 additions & 2 deletions nuntium/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from contactos.models import Contact
from .plugins import OutputPlugin
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.fields import GenericForeignKey
import datetime
from djangoplugins.models import Plugin
from django.core.mail import EmailMultiAlternatives
Expand Down Expand Up @@ -52,7 +52,7 @@ class MessageRecord(models.Model):
datetime = models.DateField(default=now)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
content_object = GenericForeignKey('content_type', 'object_id')

def __unicode__(self):
outbound_message = self.content_object
Expand Down
16 changes: 9 additions & 7 deletions nuntium/tasks.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
from celery import task
from __future__ import absolute_import, unicode_literals

import logging

from celery import shared_task

from .management.commands.send_mails import send_mails
from instance.models import WriteitInstancePopitInstanceRecord
from popolo_sources.models import PopoloSource
import logging


logger = logging.getLogger(__name__)


@task()
@shared_task()
def send_mails_task():
send_mails()


@task()
@shared_task()
def pull_from_popolo_json(writeitinstance, popolo_source):
result = writeitinstance._load_persons_from_popolo_json(popolo_source)
logger.info(u'Resyncing {0} with {1}'.format(
writeitinstance, popolo_source))
return result


@task()
@shared_task()
def update_all_instances(periodicity='1W'):
all_records = WriteitInstancePopitInstanceRecord.objects.filter(periodicity=periodicity)
logger.info(u'Complete resync of all instances')
Expand Down
8 changes: 6 additions & 2 deletions nuntium/user_section/tests/delete_an_instance_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ def test_get_to_url(self):
url = reverse('delete_an_instance', subdomain=self.writeitinstance.slug)
request = self.factory.get(url)
request.user = self.writeitinstance.owner
response = WriteItDeleteView.as_view()(request)
view = WriteItDeleteView.as_view(
template_name="nuntium/profiles/writeitinstance_check_delete.html")
response = view(request)

self.assertEquals(response.status_code, 200)
self.assertTemplateUsed(response, 'nuntium/profiles/writeitinstance_check_delete.html')
self.assertEqual(
response.template_name,
['nuntium/profiles/writeitinstance_check_delete.html'])
# It's not yet deleted
self.assertTrue(WriteItInstance.objects.get(id=self.writeitinstance.id))

Expand Down
2 changes: 1 addition & 1 deletion nuntium/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.views.generic import TemplateView, DetailView, RedirectView, ListView
from subdomains.utils import reverse
from django.http import Http404, HttpResponseRedirect
from django.contrib.formtools.wizard.views import NamedUrlSessionWizardView
from formtools.wizard.views import NamedUrlSessionWizardView
from django.shortcuts import get_object_or_404, redirect

from haystack.views import SearchView
Expand Down
22 changes: 11 additions & 11 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@ amqp==1.4.9
anyjson==0.3.3
backport-collections==0.1
billiard==3.3.0.19
celery==3.1.23
celery-haystack==0.8
celery==3.1.25
celery-haystack==0.10
cffi==1.7.0
contextlib2==0.5.3
cryptography==1.4
dj-database-url==0.2.2
dj-static==0.0.6
Django==1.7.11
Django==1.8.17
django-admin-bootstrapped==2.3.6
django-annoying==0.8.1
django-annoying==0.10.3
django-appconf==1.0.2
django-autoslug==1.9.3
django-celery==3.1.17
django-celery==3.2.1
django-celery-transactions==0.1.3
django-dirtyfields==1.0
django-downloadview==1.6
django-extensions==1.6.7
django-formtools==1.0
django-haystack==2.4.0
django-markdown-deux==1.0.5
django-nose==1.4.3
Expand All @@ -43,25 +44,24 @@ mock==1.0.1
mysociety-django-popolo==0.0.8
ndg-httpsclient==0.4.1
nose==1.3.7
oauthlib==1.1.2
oauthlib==2.0.0
-e git://github.com/mysociety/[email protected]#egg=popit-django
multiple-django-popolo-sources==0.0.3
pyasn1==0.1.9
pycparser==2.14
PyJWT==1.4.0
PyJWT==1.4.2
pyOpenSSL==16.0.0
python-dateutil==2.5.3
python-mimeparse==1.5.2
python-openid==2.2.5
python-social-auth==0.2.3
python-social-auth==0.2.21
pytz==2016.4
PyYAML==3.11
requests==2.10.0
requests-oauthlib==0.6.1
requests==2.11.1
requests-oauthlib==0.7.0
simplejson==3.8.2
six==1.10.0
slumber==0.7.1
South==1.0.2
static==0.4
static3==0.7.0
transifex-client==0.12.1
Expand Down
4 changes: 2 additions & 2 deletions scripts/provision.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ Add some seed data to your instance with:
./manage.py loaddata example_data.yaml

Run a celery worker with:
./manage.py celery worker
celery -A writeit worker

Run celery beat with:
./manage.py celery beat
celery -A writeit beat

Run the tests with:
./manage.py test nuntium contactos mailit
Expand Down
22 changes: 22 additions & 0 deletions writeit/celery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from __future__ import absolute_import

import os

from celery import Celery

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'writeit.settings')

from django.conf import settings # noqa

app = Celery('writeit')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
19 changes: 13 additions & 6 deletions writeit/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-

from __future__ import absolute_import

# Django settings for writeit project.
import sys
import os
Expand Down Expand Up @@ -206,6 +209,7 @@
'social.apps.django_app.default',
'annoying',
'celery_haystack',
'djcelery',

'instance',
'nuntium',
Expand All @@ -225,7 +229,6 @@
'django_extensions',
# Searching.
'haystack',
'djcelery',
'pipeline',
# Uncomment the next line to enable the admin:
'django_admin_bootstrapped',
Expand All @@ -235,7 +238,7 @@
# 'django.contrib.admindocs',

# Multi-page form wizard
'django.contrib.formtools',
'formtools',
'subdomains',
)

Expand Down Expand Up @@ -335,9 +338,13 @@


# CELERY CONFIGURATION
import djcelery

CELERY_BROKER_URL = 'amqp://guest:guest@localhost//'
CELERY_ACCEPT_CONTENT = ['pickle']
CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend'

from celery.schedules import crontab
djcelery.setup_loader()

CELERYBEAT_SCHEDULE = {
# Sends emails every 2 minutes
Expand Down Expand Up @@ -410,10 +417,10 @@
API_BASED = False

if TESTING:
from testing_settings import * # noqa
from .testing_settings import * # noqa

try:
from local_settings import * # noqa
from .local_settings import * # noqa
INSTALLED_APPS += EXTRA_APPS
except ImportError:
pass
Expand Down