Skip to content

Commit 3527283

Browse files
committed
Updates include:
- Add badges to README - Add docs for current items - Add testing support in tox and a travis build file - Fixed some import calls in tests - Added a new test for active tag where class_name can be set - Added template dict to settings of testapp so it works correctly
1 parent 77120e3 commit 3527283

File tree

12 files changed

+219
-31
lines changed

12 files changed

+219
-31
lines changed

.travis.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
language: python
2+
3+
python:
4+
- 3.5
5+
6+
sudo: false
7+
8+
env:
9+
- TOX_ENV=py27-dj18
10+
- TOX_ENV=py27-dj19
11+
- TOX_ENV=py27-djmaster
12+
- TOX_ENV=py34-dj18
13+
- TOX_ENV=py34-dj19
14+
- TOX_ENV=py34-djmaster
15+
- TOX_ENV=py35-dj18
16+
- TOX_ENV=py35-dj19
17+
- TOX_ENV=py35-djmaster
18+
19+
matrix:
20+
fast_finish: true
21+
allow_failures:
22+
- env: TOX_ENV=py27-djmaster
23+
- env: TOX_ENV=py35-djmaster
24+
- env: TOX_ENV=py34-djmaster
25+
26+
install:
27+
- pip install "virtualenv<14.0.0" tox coveralls
28+
29+
script:
30+
- tox -e $TOX_ENV
31+
32+
after_success:
33+
- coveralls

README.rst

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,33 @@
22
Django Toolset
33
==============
44

5+
.. image:: https://img.shields.io/pypi/l/django-toolset.svg
6+
:target: https://raw.githubusercontent.com/codezeus/django-toolset/master/LICENSE
7+
8+
.. image:: https://secure.travis-ci.org/codezeus/django-toolset.png?branch=master
9+
:alt: Build Status
10+
:target: http://travis-ci.org/codezeus/django-toolset
11+
12+
.. image:: https://img.shields.io/pypi/v/django-toolset.svg
13+
:target: https://pypi.python.org/pypi/django-toolset/
14+
:alt: Latest PyPI version
15+
16+
.. image:: https://img.shields.io/pypi/dm/django-toolset.svg
17+
:target: https://pypi.python.org/pypi/django-toolset/
18+
:alt: Number of PyPI downloads
19+
20+
.. image:: https://coveralls.io/repos/github/codezeus/django-toolset/badge.svg?branch=master
21+
:target: https://coveralls.io/github/codezeus/django-toolset?branch=master
22+
:alt: Coverage
23+
524
Django Toolset is a simple package with a few useful models, views,
625
templatetags, and other functions that can be used to save time when writing a
726
Django application.
827

28+
For specific information about what's included, view the `docs`_.
29+
30+
.. _docs: docs/
31+
932
Requirements
1033
============
1134

@@ -14,11 +37,9 @@ Django Toolset requires Django 1.8 or later.
1437
Getting It
1538
==========
1639

17-
You can get Django Toolset by using pip or easy_install::
40+
You can get Django Toolset by using pip::
1841

1942
$ pip install django-toolset
20-
or
21-
$ easy_install django-toolset
2243

2344
If you want to install it from source, grab the git repository from GitHub and run setup.py::
2445

django_toolset/templatetags/custom_tags.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,21 @@ def active(context, pattern_or_urlname, class_name='active'):
1717
Usage:
1818
1919
{% load custom_tags %}
20-
<nav><ul>
21-
<li class="nav-home {% active 'url-name' %}"><a href="#">Home</a></li>
22-
<li class="nav-blog {% active '^/regex/' %}"><a href="#">Blog</a></li>
23-
</ul></nav>
20+
<nav>
21+
<ul>
22+
<li class="nav-home {% active 'url-name' %}"><a href="#">Home</a></li>
23+
<li class="nav-blog {% active '^/regex/' %}"><a href="#">Blog</a></li>
24+
</ul>
25+
</nav>
26+
27+
or
28+
29+
<nav>
30+
<ul>
31+
<li class="nav-home {% active 'url-name' class_name='current' %}"><a href="#">Home</a></li>
32+
<li class="nav-blog {% active '^/regex/' class_name='current' %}"><a href="#">Blog</a></li>
33+
</ul>
34+
</nav>
2435
2536
"""
2637
request = context.dicts[1].get('request')

docs/decorators.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Decorators
2+
==========
3+
4+
* *authenticated_redirect* - authenticated_redirect provides a way to redirect
5+
a user from pages they shouldn't visit when they have been authenticated.
6+
For instance, if a user is logged in then they shouldn't visit the "login"
7+
page. By default, this will redirect users to a URL named "dashboard" but
8+
this can be overwritten with the settings variable
9+
`DEFAULT_AUTHENTICATED_PATH`. If you wish to set the path explicitly for
10+
each view you can do so by passing the `path` kwarg to the decorator::
11+
12+
settings.py
13+
14+
DEFAULT_AUTHENTICATED_PATH = 'admin'
15+
16+
views.py
17+
18+
@authenticated_redirect
19+
def my_view(request):
20+
"""This redirects to `admin` if logged in"""
21+
...
22+
23+
@authenticated_redirect(path='some_other_page')
24+
def my_other_view(request):
25+
"""This redirects to `some_other_page` if logged in"""
26+
...

docs/template_filters.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Template Filters
2+
================
3+
4+
* *Method Calling* - A set of filters are provided for calling a method on an
5+
object in the template. This is useful for cases where you want to run a
6+
method from the template itself and act on it rather than in the view. While
7+
it's best practice to not put this type of logic in the template, there are
8+
cases where you may want to do so.::
9+
10+
{% load custom_filters %}
11+
{% if foo|method:"has_access"|with:user|with:group|call %}
12+
13+
This will invoke foo.has_access(user, group)

docs/template_tags.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Template Tags
2+
=============
3+
4+
* *active* - The active template tag is an easy way to output a class name for
5+
the currently active link. This is useful if you're creating a navigation
6+
component and want to give the active URL a specific class for UI purposes.
7+
It will accept a named URL or a regex pattern.::
8+
9+
{% load custom_tags %}
10+
<nav>
11+
<ul>
12+
<li class="nav-home {% active 'url-name' %}"><a href="#">Home</a></li>
13+
<li class="nav-blog {% active '^/regex/' %}"><a href="#">Blog</a></li>
14+
</ul>
15+
</nav>
16+
17+
or
18+
19+
<nav>
20+
<ul>
21+
<li class="nav-home {% active 'url-name' class_name='current' %}"><a href="#">Home</a></li>
22+
<li class="nav-blog {% active '^/regex/' class_name='current' %}"><a href="#">Blog</a></li>
23+
</ul>
24+
</nav>

setup.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,37 @@
1-
import os
1+
import os, sys
22
from setuptools import find_packages, setup
33

44
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
55
README = readme.read()
66

7+
try:
8+
from setuptools.command.test import test as TestCommand
9+
10+
class PyTest(TestCommand):
11+
user_options = [('pytest-args=', 'a', "Arguments to pass into py.test")]
12+
13+
def initialize_options(self):
14+
TestCommand.initialize_options(self)
15+
self.pytest_args = []
16+
17+
def finalize_options(self):
18+
TestCommand.finalize_options(self)
19+
self.test_args = []
20+
self.test_suite = True
21+
22+
def run_tests(self):
23+
import pytest
24+
25+
errno = pytest.main(self.pytest_args)
26+
sys.exit(errno)
27+
28+
except ImportError:
29+
PyTest = None
30+
31+
cmdclasses = {}
32+
if PyTest:
33+
cmdclasses['test'] = PyTest
34+
735
# allow setup.py to be run from any path
836
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
937

@@ -18,10 +46,12 @@
1846
description='A set of helper functions and utilities for a Django application',
1947
download_url = 'https://github.com/codezeus/django-toolset/tarball/0.1.3',
2048
long_description=README,
49+
cmdclass=cmdclasses,
2150
url='https://github.com/codezeus/django-toolset',
22-
author='Dan Sackett',
23-
author_email='danesackett@gmail.com',
24-
tests_require=['Django', 'pytest', 'coverage', 'mock'],
51+
author='CodeZeus',
52+
maintainer='Dan Sackett',
53+
maintainer_email='danesackett@gmail.com',
54+
tests_require=['Django', 'pytest', 'pytest-cov', 'coverage', 'mock'],
2555
classifiers=[
2656
'Environment :: Web Environment',
2757
'Framework :: Django',
@@ -32,7 +62,6 @@
3262
'Programming Language :: Python',
3363
'Programming Language :: Python :: 2',
3464
'Programming Language :: Python :: 2.7',
35-
'Topic :: Internet :: WWW/HTTP',
36-
'Topic :: Internet :: WWW/HTTP :: Dynamic Content'
65+
'Topic :: Utilities',
3766
],
3867
)

tests/test_decorators.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import pytest
2-
import mock
2+
from mock import Mock, MagicMock
33

44
from django_toolset.decorators import authenticated_redirect
55

6-
@pytest.mark.urls('utils.tests.test_urls')
6+
@pytest.mark.urls('tests.testapp.urls')
77
class DescribeAuthenticatedRedirect:
88
"""Test the authenticated_redirect decorator"""
99
@classmethod
1010
def setup_class(cls):
11-
cls.request = mock.Mock()
11+
cls.request = Mock()
1212
cls.request.path = '/login/'
1313

1414
def it_works_without_kwargs(self):
1515
@authenticated_redirect
1616
def my_function(request):
1717
return True
1818

19-
self.request.user.is_authenticated = mock.MagicMock(return_value=True)
19+
self.request.user.is_authenticated = MagicMock(return_value=True)
2020
result = my_function(self.request)
2121
assert result.url == '/dashboard/'
2222

@@ -25,7 +25,7 @@ def it_works_with_kwargs_authenticated(self):
2525
def my_function(request):
2626
return True
2727

28-
self.request.user.is_authenticated = mock.MagicMock(return_value=True)
28+
self.request.user.is_authenticated = MagicMock(return_value=True)
2929
result = my_function(self.request)
3030
assert result.url == '/'
3131

@@ -34,7 +34,7 @@ def it_works_with_kwargs_unauthenticated(self):
3434
def my_function(request):
3535
return True
3636

37-
self.request.user.is_authenticated = mock.MagicMock(return_value=False)
37+
self.request.user.is_authenticated = MagicMock(return_value=False)
3838
result = my_function(self.request)
3939
assert result is True
4040

@@ -43,6 +43,6 @@ def it_avoids_redirect_loop(self):
4343
def my_function(request):
4444
return True
4545

46-
self.request.user.is_authenticated = mock.MagicMock(return_value=True)
46+
self.request.user.is_authenticated = MagicMock(return_value=True)
4747
result = my_function(self.request)
4848
assert result.url == '/dashboard/'

tests/test_filters.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import pytest
2-
import mock
2+
from mock import Mock
33

44
from django.template import Template, Context
55

66
class DescribeMethodFilter:
77
"""Tests for the `method` filter"""
88
@classmethod
99
def setup_class(cls):
10-
cls.request = mock.Mock()
10+
cls.request = Mock()
1111
cls.template = Template('''
1212
{% load custom_filters %}
1313
{{ test|method:"test_method" }}
@@ -20,7 +20,7 @@ def test_method(self):
2020

2121
context = Context({ 'test': Test() })
2222
template = self.template.render(context)
23-
assert 'bound method Test.test_method' in template
23+
assert 'Test.test_method' in template
2424

2525
def it_recognizes_not_callable(self):
2626
class Test:
@@ -34,7 +34,7 @@ class DescribeWithFilter:
3434
"""Tests for the `with` filter"""
3535
@classmethod
3636
def setup_class(cls):
37-
cls.request = mock.Mock()
37+
cls.request = Mock()
3838
cls.template = Template('''
3939
{% load custom_filters %}
4040
{{ test|method:"test_method"|with:my_string }}
@@ -62,7 +62,7 @@ class DescribeCallFilter:
6262
"""Tests for the `call` filter"""
6363
@classmethod
6464
def setup_class(cls):
65-
cls.request = mock.Mock()
65+
cls.request = Mock()
6666
cls.template = Template('''
6767
{% load custom_filters %}
6868
{{ test|method:"test_method"|call }}

tests/test_tags.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import pytest
2-
import mock
2+
from mock import Mock
33

44
from django.core.urlresolvers import NoReverseMatch
55
from django.template import Template, Context
66

7-
@pytest.mark.urls('utils.tests.test_urls')
7+
@pytest.mark.urls('tests.testapp.urls')
88
class DescribeActiveTag:
99
"""Tests for the `active` templatetag"""
1010
@classmethod
1111
def setup_class(cls):
12-
cls.request = mock.Mock()
12+
cls.request = Mock()
1313
cls.request.path = '/login/'
1414
cls.context = Context({ 'request': cls.request, })
1515

@@ -28,6 +28,7 @@ def it_knows_page_is_current_from_regex(self):
2828
template = self.make_template_for('^/login/$').render(self.context)
2929
assert template == 'active'
3030

31-
def it_knows_page_is_current_from_regex(self):
32-
template = self.make_template_for('^/login/$').render(self.context)
33-
assert template == 'active'
31+
def it_can_customize_class_name(self):
32+
template = Template("{% load custom_tags %}{% active 'login' class_name='current' %}")
33+
template = template.render(self.context)
34+
assert template == 'current'

0 commit comments

Comments
 (0)