Skip to content

Commit

Permalink
Merge 7f5f606 into 089e21a
Browse files Browse the repository at this point in the history
  • Loading branch information
josh committed Dec 9, 2019
2 parents 089e21a + 7f5f606 commit b7be8eb
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 161 deletions.
78 changes: 28 additions & 50 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,62 +1,40 @@
sudo: false
dist: xenial
language: python
python:
- "2.6"
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "pypy"
- "pypy3"
env:
matrix:
- DJANGO="Django>=1.4,<1.5"
- DJANGO="Django>=1.5,<1.6"
- DJANGO="Django>=1.6,<1.7"
- DJANGO="Django>=1.7,<1.8"
- DJANGO="Django>=1.8,<1.9"
- DJANGO="Django>=1.9,<1.10"
- DJANGO="--pre django"
install:
- pip install $DJANGO
- pip install coveralls
- pip install -r dev-requirements.txt
- pip install --upgrade -r dev-requirements.txt
script:
- inv test
after_success:
- coveralls
matrix:
fast_finish: true
exclude:
- python: "2.6"
env: DJANGO="Django>=1.7,<1.8"
- python: "2.6"
env: DJANGO="Django>=1.8,<1.9"
- python: "2.6"
include:
- python: "2.7"
name: 'Linter (Python 2.7)'
install:
- pip install --upgrade -r dev-requirements.txt
script: flake8 sudo tests
- python: "3.7"
name: 'Linter (Python 3.7)'
install:
- pip install --upgrade -r dev-requirements.txt
script: flake8 sudo tests
- python: "2.7"
name: "Python 2.7, Django 1.9"
env: DJANGO="Django>=1.9,<1.10"
- python: "2.6"
env: DJANGO="--pre django"
- python: "3.3"
env: DJANGO="Django>=1.4,<1.5"
- python: "3.3"
- python: "2.7"
name: "Python 2.7, Django 1.10"
env: DJANGO="Django>=1.10,<1.11"
- python: "3.6"
name: "Python 3.6, Django 1.9"
env: DJANGO="Django>=1.9,<1.10"
- python: "3.3"
env: DJANGO="--pre django"
- python: "3.4"
env: DJANGO="Django>=1.4,<1.5"
- python: "3.5"
env: DJANGO="Django>=1.4,<1.5"
- python: "3.5"
env: DJANGO="Django>=1.5,<1.6"
- python: "3.5"
env: DJANGO="Django>=1.6,<1.7"
- python: "3.5"
env: DJANGO="Django>=1.7,<1.8"
- python: "pypy3"
env: DJANGO="Django>=1.4,<1.5"
- python: "pypy3"
- python: "3.6"
name: "Python 3.6, Django 1.10"
env: DJANGO="Django>=1.10,<1.11"
- python: "3.7"
name: "Python 3.7, Django 1.9"
env: DJANGO="Django>=1.9,<1.10"
- python: "pypy3"
env: DJANGO="--pre django"
allow_failures:
- env: DJANGO="--pre django"
- python: "3.7"
name: "Python 3.7, Django 1.10"
env: DJANGO="Django>=1.10,<1.11"
5 changes: 2 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ Installation
Compatibility
~~~~~~~~~~~~~
* Django 1.4-1.9
* Python 2.6-3.5
* pypy
* Django 1.9-1.10
* Python 2.7, 3.6-3.7

Resources
~~~~~~~~~
Expand Down
8 changes: 4 additions & 4 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
-e .
flake8<3.0
flake8>=3.7.0,<3.8.0
invoke>=0.11.1,<0.12
pytest
pytest-cov
pytest-django
pytest==4.6.5
pytest-cov==2.5.1
pytest-django==3.5.1
sphinx
sphinx_rtd_theme
tox
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[pytest]
[tool:pytest]
python_files = tests/*.py

[flake8]
max-line-length = 100
max-line-length = 110

[wheel]
universal = 1
34 changes: 2 additions & 32 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,13 @@
:license: BSD, see LICENSE for more details.
"""
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand

install_requires = []

tests_require = [
'pytest',
'pytest-cov',
'pytest-django',
'flake8',
]


with open('README.rst') as f:
long_description = f.read()


class PyTest(TestCommand):
def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_suite = True

def run_tests(self):
# import here, cause outside the eggs aren't loaded
import pytest
import sys
errno = pytest.main(self.test_args)
sys.exit(errno)


setup(
name='django-sudo',
version='2.1.0',
Expand All @@ -48,11 +25,6 @@ def run_tests(self):
long_description=long_description,
packages=find_packages(exclude=['tests']),
install_requires=install_requires,
tests_require=tests_require,
cmdclass={'test': PyTest},
extras_require={
'tests': tests_require,
},
zip_safe=True,
classifiers=[
'Development Status :: 5 - Production/Stable',
Expand All @@ -61,12 +33,10 @@ def run_tests(self):
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python',
'Topic :: Software Development',
],
Expand Down
1 change: 1 addition & 0 deletions sudo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:copyright: (c) 2014 by Matt Robenolt.
:license: BSD, see LICENSE for more details.
"""

try:
VERSION = __import__('pkg_resources') \
.get_distribution('sudo').version
Expand Down
5 changes: 1 addition & 4 deletions sudo/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ def __init__(self, user, *args, **kwargs):
super(SudoForm, self).__init__(*args, **kwargs)

def clean_password(self):
try:
username = self.user.get_username() # Django 1.5 and above
except AttributeError: # pragma: nocover
username = self.user.username # Django 1.4
username = self.user.get_username()
if auth.authenticate(username=username, password=self.data['password']):
return self.data['password']
raise forms.ValidationError(_('Incorrect password'))
49 changes: 10 additions & 39 deletions sudo/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,22 @@
from urlparse import urlparse, urlunparse # noqa

from django.contrib.auth.decorators import login_required
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponseRedirect, QueryDict
from django.shortcuts import resolve_url
from django.template.response import TemplateResponse
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.views.generic import View
from django.utils.decorators import method_decorator
from django.utils.module_loading import import_string

from sudo.settings import (REDIRECT_FIELD_NAME, REDIRECT_URL,
REDIRECT_TO_FIELD_NAME, URL)
from sudo.utils import grant_sudo_privileges, is_safe_url
from sudo.forms import SudoForm

try:
from django.shortcuts import resolve_url
except ImportError: # pragma: no cover
# Django <1.5 doesn't have `resolve_url`
from django.core import urlresolvers

# resolve_url yanked from Django 1.5.5
def resolve_url(to, *args, **kwargs):
"""
Return a URL appropriate for the arguments passed.
The arguments could be:
* A model: the model's `get_absolute_url()` function will be called.
* A view name, possibly with arguments: `urlresolvers.reverse()` will
be used to reverse-resolve the name.
* A URL, which will be returned as-is.
"""
# If it's a model, use get_absolute_url()
if hasattr(to, 'get_absolute_url'):
return to.get_absolute_url()

# Next try a reverse URL resolution.
try:
return urlresolvers.reverse(to, args=args, kwargs=kwargs)
except urlresolvers.NoReverseMatch:
# If this is a callable, re-raise.
if callable(to):
raise
# If this doesn't "feel" like a URL, re-raise.
if '/' not in to and '.' not in to:
raise

# Finally, fall back and assume it's a URL
return to


class SudoView(View):
"""
Expand Down Expand Up @@ -128,6 +92,13 @@ def redirect_to_sudo(next_url, sudo_url=None):
if sudo_url is None:
sudo_url = URL

try:
# django 1.10 and greater can't resolve the string 'sudo.views.sudo' to a URL
# https://docs.djangoproject.com/en/1.10/releases/1.10/#removed-features-1-10
sudo_url = import_string(sudo_url)
except (ImportError, ImproperlyConfigured):
pass # wasn't a dotted path

sudo_url_parts = list(urlparse(resolve_url(sudo_url)))

querystring = QueryDict(sudo_url_parts[4], mutable=True)
Expand Down
5 changes: 1 addition & 4 deletions tests/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
try:
from django.utils import unittest
except ImportError:
import unittest
import unittest

from django.test import RequestFactory
from django.contrib.auth.models import User, AnonymousUser
Expand Down
1 change: 1 addition & 0 deletions tests/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class FooView(SudoMixin, generic.View):
def get(self, request):
return HttpResponse()


foo = FooView.as_view()


Expand Down
13 changes: 2 additions & 11 deletions tests/models.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import django
from django.db import models
try:
from django.contrib.auth.models import AbstractBaseUser
except ImportError:
# Django 1.4 doesn't properly support custom user models, but a User is
# close enough to AbstractBaseUser for our tests to work in 1.4.
from django.contrib.auth.models import User as AbstractBaseUser
from django.contrib.auth.models import AbstractBaseUser


class EmailUser(AbstractBaseUser):
if django.VERSION >= (1, 5):
# Skip on Django 1.4, since we're inheriting from User, which already
# has an email address.
email = models.CharField(max_length=254, unique=True)
email = models.CharField(max_length=254, unique=True)

USERNAME_FIELD = 'email'

Expand Down
14 changes: 6 additions & 8 deletions tests/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
try:
from django.conf.urls import url, patterns
except ImportError:
from django.conf.urls.defaults import url, patterns # noqa
from django.conf.urls import url

from sudo import views

urlpatterns = patterns(
'',
url(r'^sudo/', 'sudo.views.sudo', name='sudo'),
)

urlpatterns = [
url(r'^sudo/', views.sudo, name='sudo'),
]
4 changes: 2 additions & 2 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def assertRequestHasToken(self, request, max_age):
token = request.session[COOKIE_NAME]

self.assertRegexpMatches(
token, '^\w{12}$'
token, r'^\w{12}$'
)
self.assertTrue(request._sudo)
self.assertEqual(request._sudo_token, token)
Expand Down Expand Up @@ -123,7 +123,7 @@ def test_failure(self):
('http://mattrobenolt.com/', 'example.com'),
('///example.com/', None),
('ftp://example.com', 'example.com'),
('http://example.com\@mattrobenolt.com', 'example.com'),
('http://example.com\@mattrobenolt.com', 'example.com'), # noqa: W605
('http:///example.com', 'example.com'),
('\x08//example.com', 'example.com'),
)
Expand Down
4 changes: 2 additions & 2 deletions tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test_redirect_fix_bad_url(self):
response = sudo(self.request)
self.assertEqual(response['Location'], REDIRECT_URL)
self.request.GET = {
REDIRECT_FIELD_NAME: 'http://%s\@mattrobenolt.com' % self.request.get_host(),
REDIRECT_FIELD_NAME: 'http://%s\@mattrobenolt.com' % self.request.get_host(), # noqa: W605
}
response = sudo(self.request)
self.assertEqual(response['Location'], REDIRECT_URL)
Expand Down Expand Up @@ -114,7 +114,7 @@ def test_session_based_redirect_bad_url(self):
self.assertEqual(response['Location'], REDIRECT_URL)
self.assertFalse('redirect_to' in self.request.session)
self.request.session[REDIRECT_TO_FIELD_NAME] = (
'http://%s\@mattrobenolt.com' % self.request.get_host()
'http://%s\@mattrobenolt.com' % self.request.get_host() # noqa: W605
)
response = sudo(self.request)
self.assertEqual(response['Location'], REDIRECT_URL)
Expand Down

0 comments on commit b7be8eb

Please sign in to comment.