Skip to content

Release 0.5.0 : Code cleanup, linting & coverage. #2

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[run]
source = async_messages
branch = 1

[report]
omit = *tests*
30 changes: 13 additions & 17 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
dist: bionic
language: python
sudo: required
dist: xenial

python:
- 2.7
- 3.6
- 3.7
- 3.8

env:
- DJANGO=1.11
- DJANGO=2.1
- DJANGO=2.2
stages:
- lint
- tests

matrix:
exclude:
- python: 2.7
env: DJANGO=2.1
- python: 2.7
env: DJANGO=2.2
- python: 3.7
env: DJANGO=1.11
jobs:
include:
- stage: lint
python: 3.6
env: TOXENV=lint

install:
- pip install Django==$DJANGO
- python setup.py develop
- pip install tox
- pip install -q tox-travis
script:
- python manage.py test tests
- tox
File renamed without changes.
8 changes: 8 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,16 @@ MIT_
Changelog
=========

0.5.0
-----

* Support for Django 2.2 & 3.0
* Code cleanup
* Add linting & coverage

0.4.1
-----

* Improvements to Django 2+ and Python 3+ support

0.4.0
Expand Down
2 changes: 1 addition & 1 deletion async_messages/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.core.cache import cache
from django.contrib.messages import constants
from django.core.cache import cache


class AsyncMessageException(Exception):
Expand Down
2 changes: 2 additions & 0 deletions async_messages/messages.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.contrib.messages import constants

from . import message_user


"""
Mimic the django.contrib.messages API
"""
Expand Down
28 changes: 5 additions & 23 deletions async_messages/middleware.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,10 @@
from distutils.version import StrictVersion

from django.contrib import messages

try:
from django.utils.version import get_version
except ImportError:
from django import VERSION as DJANGO_VERSION

def get_version():
return ".".join(str(n) for n in DJANGO_VERSION[:3])
from django.utils.deprecation import MiddlewareMixin

from async_messages import get_messages

if StrictVersion(get_version()) >= StrictVersion("1.10.0"):
from django.utils.deprecation import MiddlewareMixin as _MiddlewareBase

def _is_user_authenticated(user):
return bool(user.is_authenticated)
else:
_MiddlewareBase = object

def _is_user_authenticated(user):
return user.is_authenticated()


class AsyncMiddleware(_MiddlewareBase):
class AsyncMiddleware(MiddlewareMixin):
# In Django>=1.10 User.is_authenticated is a property, not a method but a
# strange one : CallbableBool.
# - If default User is used you can use it as a boolean either a method.
Expand All @@ -33,7 +13,7 @@ class AsyncMiddleware(_MiddlewareBase):

def is_authenticated(self, request):
if hasattr(request, "session") and hasattr(request, "user"):
return _is_user_authenticated(request.user)
return bool(request.user.is_authenticated)
else:
return False

Expand All @@ -44,7 +24,9 @@ def process_response(self, request, response):
"""
if self.is_authenticated(request):
msgs = get_messages(request.user)

if msgs:
for msg, level in msgs:
messages.add_message(request, level, msg)

return response
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
django-nose>=1.1
nose>=1.1.2
django-nose>=1.2.1
nose>=1.3.6
pinocchio>=0.3.1
51 changes: 39 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
#!/usr/bin/env python
from setuptools import setup, find_packages

setup(name='django-async-messages-redux',
version='0.4.1',
url='https://github.com/maurizi/django-async-messages',
author='Michael Maurizi',
author_email='[email protected]',
description="Send asynchronous messages to users (eg from offline scripts). Useful for integration with Celery.",
long_description=open('README.rst').read(),
packages=find_packages(exclude=['tests']),
install_requires=['django>=1.4'],
)
from setuptools import find_packages, setup


def readfile(path):
with open(path) as fd:
return fd.read()


setup(
name='django-async-messages-redux',
version='0.5.0',
url='https://github.com/maurizi/django-async-messages',
author='Michael Maurizi',
author_email='[email protected]',
description="Send asynchronous messages to users (eg from offline scripts). Useful for integration with Celery.",
long_description=readfile('README.rst'),
packages=find_packages(exclude=['tests']),
install_requires=[
'django>=1.11,<3.1'
],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Topic :: Utilities',
],
)
70 changes: 27 additions & 43 deletions tests/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import django
from os import path

DEBUG = False
Expand All @@ -23,52 +22,37 @@
]


if django.VERSION >= (1, 10):
MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'async_messages.middleware.AsyncMiddleware'
)
else:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'async_messages.middleware.AsyncMiddleware'
)
MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'async_messages.middleware.AsyncMiddleware'
)

SITE_ID = 1

if django.VERSION >= (1, 8):
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
path.join(path.dirname(__file__), "templates"),
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
path.join(path.dirname(__file__), "templates"),
],
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]
else:
TEMPLATE_DIRS = (
path.join(path.dirname(__file__), "templates"),
)
},
]

SECRET_KEY = 'foobarbaz'
79 changes: 61 additions & 18 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,69 @@
from django.contrib.messages import constants
from django.test import TestCase
from django.test.client import Client
from django.test.utils import override_settings
from django.utils.encoding import force_text

from async_messages import (
message_user, message_users, messages, AsyncMessageException,
)
from async_messages import (AsyncMessageException, get_messages, message_user,
message_users, messages)


class MiddlewareTests(TestCase):

def setUp(self):
username, password = 'david', 'password'
self.user = User.objects.create_user(username, "[email protected]", password)
self.user = User.objects.create_user('david', "[email protected]", 'password')
self.userB = User.objects.create_user('johnathan', "[email protected]", 'password')

self.client = Client()
self.client.login(username=username, password=password)
self.client.login(username='david', password='password')

self.clientB = Client()
self.clientB.login(username='johnathan', password='password')

def test_message_appears_for_user(self):
message_user(self.user, "Hello")
message_user(self.user, "Hello david")
message_user(self.userB, "Hello john")

response = self.client.get('/')
msgs = list(response.context['messages'])
self.assertEqual(1, len((msgs)))
self.assertEqual('Hello', str((msgs)[0]))
self.assertEqual(
['Hello david'],
[force_text(m) for m in response.context['messages']]
)

response = self.clientB.get('/')
self.assertEqual(
['Hello john'],
[force_text(m) for m in response.context['messages']]
)

def test_message_appears_all_users(self):
message_users(User.objects.all(), "Hello")

response = self.client.get('/')
msgs = list(response.context['messages'])
self.assertEqual(1, len((msgs)))
self.assertEqual('Hello', str((msgs)[0]))
self.assertEqual(
['Hello'],
[force_text(m) for m in response.context['messages']]
)

response = self.clientB.get('/')
self.assertEqual(
['Hello'],
[force_text(m) for m in response.context['messages']]
)

def test_message_queue(self):
message_user(self.user, "First Message")
message_user(self.user, "Second Message")

response = self.client.get('/')
msgs = list(response.context['messages'])
self.assertEqual(2, len((msgs)))
self.assertEqual('Second Message', str((msgs)[1]))
self.assertEqual(
['First Message', 'Second Message'],
[force_text(m) for m in response.context['messages']]
)

def test_message_queue_empty(self):
response = self.client.get('/')
self.assertEqual([], [force_text(m) for m in response.context['messages']])

class AnonynousUserTests(TestCase):
def test_anonymous(self):
Expand All @@ -54,9 +81,25 @@ def test_anonymous_message(self):
with self.assertRaises(AsyncMessageException) as e:
message_user(user, "Second Message")

self.assertEqual(str(e.exception),
self.assertEqual(force_text(e.exception),
'Anonymous users cannot send messages.')

def test_get_messages_anonymous(self):
client = Client()
user = auth.get_user(client)

self.assertIsNone(user.id)
self.assertIsNone(get_messages(user))

@override_settings(MIDDLEWARE=[
'django.middleware.common.CommonMiddleware',
'async_messages.middleware.AsyncMiddleware'
])
def test_no_session(self):
client = Client()
response = client.get('/')
self.assertEqual([], [force_text(m) for m in response.context['messages']])


class TestMessagesApi(TestCase):
def setUp(self):
Expand All @@ -69,7 +112,7 @@ def assertMessageOk(self, level):
response = self.client.get('/')
msgs = list(response.context['messages'])
self.assertEqual(1, len((msgs)))
self.assertEqual('Hello', str((msgs)[0]))
self.assertEqual('Hello', force_text((msgs)[0]))

def test_info(self):
messages.info(self.user, "Hello")
Expand Down
Loading