[Python-modules-commits] [django-simple-captcha] 01/03: New upstream version 0.5.6
Brian May
bam at debian.org
Tue Dec 12 07:45:45 UTC 2017
This is an automated email from the git hooks/post-receive script.
bam pushed a commit to branch debian/master
in repository django-simple-captcha.
commit 4cc2e2169920ed22c87bf23d7721a2bb84d1a059
Author: Brian May <bam at debian.org>
Date: Tue Dec 12 18:41:35 2017 +1100
New upstream version 0.5.6
---
CHANGES | 12 +
PKG-INFO | 3 +-
README.rst | 2 +-
captcha/__init__.py | 24 +-
captcha/conf/settings.py | 1 +
captcha/fields.py | 15 +-
captcha/helpers.py | 18 +-
captcha/models.py | 8 +-
captcha/tests/tests.py | 17 +-
captcha/urls.py | 2 +-
captcha/views.py | 48 +-
django_simple_captcha.egg-info/PKG-INFO | 3 +-
django_simple_captcha.egg-info/SOURCES.txt | 22 +-
django_simple_captcha.egg-info/requires.txt | 7 +-
docs/advanced.rst | 14 +
docs/conf.py | 4 +-
docs/usage.rst | 16 +-
setup.cfg | 1 -
setup.py | 3 +-
testproject/coverage.sh | 1 +
..._django-simple-captcha_captcha___init___py.html | 103 ++++
...go-simple-captcha_captcha_conf___init___py.html | 91 ++++
...go-simple-captcha_captcha_conf_settings_py.html | 207 ++++++++
...de_django-simple-captcha_captcha_fields_py.html | 473 +++++++++++++++++
...e_django-simple-captcha_captcha_helpers_py.html | 273 ++++++++++
...de_django-simple-captcha_captcha_models_py.html | 247 +++++++++
...Code_django-simple-captcha_captcha_urls_py.html | 109 ++++
...ode_django-simple-captcha_captcha_views_py.html | 415 +++++++++++++++
testproject/htmlcov/coverage_html.js | 584 +++++++++++++++++++++
testproject/htmlcov/index.html | 200 +++++++
.../htmlcov/jquery.ba-throttle-debounce.min.js | 9 +
testproject/htmlcov/jquery.hotkeys.js | 99 ++++
testproject/htmlcov/jquery.isonscreen.js | 53 ++
testproject/htmlcov/jquery.min.js | 4 +
testproject/htmlcov/jquery.tablesorter.min.js | 2 +
testproject/htmlcov/keybd_closed.png | Bin 0 -> 112 bytes
testproject/htmlcov/keybd_open.png | Bin 0 -> 112 bytes
testproject/htmlcov/status.json | 1 +
testproject/htmlcov/style.css | 375 +++++++++++++
testproject/settings.py | 9 +-
.../templates/captcha_test/image_html5_audio.html | 22 +
tox.ini | 8 +-
42 files changed, 3407 insertions(+), 98 deletions(-)
diff --git a/CHANGES b/CHANGES
index 2ce446d..ae24819 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,15 @@
+Version 0.5.6
+-------------
+* Updated render method to adapt for Django 2.1 (PR #120, thanks @skozan)
+* Improved compatibility with Django 2.0, tests against Django 2.0a1 (PR #121, thanks @Kondou-ger)
+* Dropped support for PIL (use Pillow instead)
+* Updated documentation (Fixes #122, thanks @claudep)
+* Test against Django 2.0b1
+* Return a Ranged Response when returning WAV audio to support Safari (Fixes #123, thanks @po5i)
+* Optionally inject brown noise into the generated WAV audio file, to avoid rainbow-table attacks (Fixes #124, thanks @appleorange1)
+* Test against Django 2.0
+
+
Version 0.5.5
-------------
* I messed the 0.5.4 release, re-releasing as 0.5.5
diff --git a/PKG-INFO b/PKG-INFO
index 48fb03c..7669864 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: django-simple-captcha
-Version: 0.5.5
+Version: 0.5.6
Summary: A very simple, yet powerful, Django captcha application
Home-page: https://github.com/mbi/django-simple-captcha
Author: Marco Bonetti
Author-email: mbonetti at gmail.com
License: MIT
+Description-Content-Type: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
diff --git a/README.rst b/README.rst
index 03a74c8..b5d1af7 100644
--- a/README.rst
+++ b/README.rst
@@ -22,7 +22,7 @@ Features
Requirements
++++++++++++
-* Django 1.7+
+* Django 1.8+
* A recent version of the Pillow compiled with FreeType support
* Flite is required for text-to-speech (audio) output, but not mandatory
diff --git a/captcha/__init__.py b/captcha/__init__.py
index e0acc65..3739629 100644
--- a/captcha/__init__.py
+++ b/captcha/__init__.py
@@ -1,28 +1,6 @@
-import re
-
-VERSION = (0, 5, 5)
+VERSION = (0, 5, 6)
def get_version(svn=False):
"Return the version as a human-format string."
return '.'.join([str(i) for i in VERSION])
-
-
-def pillow_required():
- def pil_version(version):
- try:
- return int(re.compile('[^\d]').sub('', version))
- except:
- return 116
-
- try:
- from PIL import Image, ImageDraw, ImageFont
- except ImportError:
- try:
- import Image
- import ImageDraw # NOQA
- import ImageFont # NOQA
- except ImportError:
- return True
-
- return pil_version(Image.VERSION) < 116
diff --git a/captcha/conf/settings.py b/captcha/conf/settings.py
index c8ab588..3d8f69d 100644
--- a/captcha/conf/settings.py
+++ b/captcha/conf/settings.py
@@ -12,6 +12,7 @@ CAPTCHA_FILTER_FUNCTIONS = getattr(settings, 'CAPTCHA_FILTER_FUNCTIONS', ('captc
CAPTCHA_WORDS_DICTIONARY = getattr(settings, 'CAPTCHA_WORDS_DICTIONARY', '/usr/share/dict/words')
CAPTCHA_PUNCTUATION = getattr(settings, 'CAPTCHA_PUNCTUATION', '''_"',.;:-''')
CAPTCHA_FLITE_PATH = getattr(settings, 'CAPTCHA_FLITE_PATH', None)
+CAPTCHA_SOX_PATH = getattr(settings, 'CAPTCHA_SOX_PATH', None)
CAPTCHA_TIMEOUT = getattr(settings, 'CAPTCHA_TIMEOUT', 5) # Minutes
CAPTCHA_LENGTH = int(getattr(settings, 'CAPTCHA_LENGTH', 4)) # Chars
# CAPTCHA_IMAGE_BEFORE_FIELD = getattr(settings, 'CAPTCHA_IMAGE_BEFORE_FIELD', True)
diff --git a/captcha/fields.py b/captcha/fields.py
index f442a2e..5273b7a 100644
--- a/captcha/fields.py
+++ b/captcha/fields.py
@@ -1,7 +1,11 @@
from captcha.conf import settings
from captcha.models import CaptchaStore
+import django
from django.core.exceptions import ImproperlyConfigured
-from django.core.urlresolvers import reverse, NoReverseMatch
+if django.VERSION < (1, 10): # NOQA
+ from django.core.urlresolvers import reverse, NoReverseMatch # NOQA
+else: # NOQA
+ from django.urls import reverse, NoReverseMatch # NOQA
from django.forms import ValidationError
from django.forms.fields import CharField, MultiValueField
from django.forms.widgets import TextInput, MultiWidget, HiddenInput
@@ -113,7 +117,7 @@ class CaptchaTextInput(BaseCaptchaTextInput):
}
return render_to_string(settings.CAPTCHA_FIELD_TEMPLATE, context)
- def render(self, name, value, attrs=None):
+ def render(self, name, value, attrs=None, renderer=None):
self.fetch_captcha_store(name, value, attrs, self._args.get('generator'))
context = {
@@ -129,7 +133,12 @@ class CaptchaTextInput(BaseCaptchaTextInput):
self.hidden_field = render_to_string(settings.CAPTCHA_HIDDEN_FIELD_TEMPLATE, context)
self.text_field = render_to_string(settings.CAPTCHA_TEXT_FIELD_TEMPLATE, context)
- return super(CaptchaTextInput, self).render(name, self._value, attrs=attrs)
+ extra_kwargs = {}
+ if django.VERSION >= (1, 11):
+ # https://docs.djangoproject.com/en/1.11/ref/forms/widgets/#django.forms.Widget.render
+ extra_kwargs['renderer'] = renderer
+
+ return super(CaptchaTextInput, self).render(name, self._value, attrs=attrs, **extra_kwargs)
def _render(self, template_name, context, renderer=None):
return self.format_output(None)
diff --git a/captcha/helpers.py b/captcha/helpers.py
index f4a5ce1..c98aba6 100644
--- a/captcha/helpers.py
+++ b/captcha/helpers.py
@@ -1,7 +1,11 @@
# -*- coding: utf-8 -*-
import random
from captcha.conf import settings
-from django.core.urlresolvers import reverse
+import django
+if django.VERSION < (1, 10): # NOQA
+ from django.core.urlresolvers import reverse # NOQA
+else: # NOQA
+ from django.urls import reverse # NOQA
from six import u, text_type
@@ -78,13 +82,15 @@ def noise_null(draw, image):
def post_smooth(image):
- try:
- import ImageFilter
- except ImportError:
- from PIL import ImageFilter
+ from PIL import ImageFilter
return image.filter(ImageFilter.SMOOTH)
def captcha_image_url(key):
- """ Return url to image. Need for ajax refresh and, etc"""
+ """Return url to image. Need for ajax refresh and, etc"""
return reverse('captcha-image', args=[key])
+
+
+def captcha_audio_url(key):
+ """Return url to image. Need for ajax refresh and, etc"""
+ return reverse('captcha-audio', args=[key])
diff --git a/captcha/models.py b/captcha/models.py
index dd329fe..c2a5d6a 100644
--- a/captcha/models.py
+++ b/captcha/models.py
@@ -1,12 +1,13 @@
from captcha.conf import settings as captcha_settings
from django.db import models
from django.utils import timezone
+from django.utils.encoding import python_2_unicode_compatible
from django.utils.encoding import smart_text
import datetime
-import random
-import time
import hashlib
import logging
+import random
+import time
# Heavily based on session key generation in Django
@@ -20,6 +21,7 @@ MAX_RANDOM_KEY = 18446744073709551616 # 2 << 63
logger = logging.getLogger(__name__)
+ at python_2_unicode_compatible
class CaptchaStore(models.Model):
challenge = models.CharField(blank=False, max_length=32)
response = models.CharField(blank=False, max_length=32)
@@ -41,7 +43,7 @@ class CaptchaStore(models.Model):
del(key_)
super(CaptchaStore, self).save(*args, **kwargs)
- def __unicode__(self):
+ def __str__(self):
return self.challenge
def remove_expired(cls):
diff --git a/captcha/tests/tests.py b/captcha/tests/tests.py
index e2dbc8f..0426872 100644
--- a/captcha/tests/tests.py
+++ b/captcha/tests/tests.py
@@ -2,9 +2,13 @@
from captcha.conf import settings
from captcha.fields import CaptchaField, CaptchaTextInput
from captcha.models import CaptchaStore
+import django
from django.core import management
from django.core.exceptions import ImproperlyConfigured
-from django.core.urlresolvers import reverse
+if django.VERSION < (1, 10): # NOQA
+ from django.core.urlresolvers import reverse # NOQA
+else: # NOQA
+ from django.urls import reverse # NOQA
from django.test import TestCase, override_settings
from django.utils.translation import ugettext_lazy
from django.utils import timezone
@@ -20,11 +24,7 @@ except ImportError:
from io import BytesIO as StringIO
from six import u, text_type
-
-try:
- from PIL import Image
-except ImportError:
- import Image # NOQA
+from PIL import Image
@override_settings(ROOT_URLCONF='captcha.tests.urls')
@@ -73,9 +73,9 @@ class CaptchaCase(TestCase):
for key in (self.stores.get('math_store').hashkey, self.stores.get('math_store').hashkey, self.default_store.hashkey):
response = self.client.get(reverse('captcha-audio', kwargs=dict(key=key)))
self.assertEqual(response.status_code, 200)
- self.assertTrue(len(response.content) > 1024)
+ self.assertTrue(response.ranged_file.size > 1024)
self.assertTrue(response.has_header('content-type'))
- self.assertEqual(response._headers.get('content-type'), ('Content-Type', 'audio/x-wav'))
+ self.assertEqual(response._headers.get('content-type'), ('Content-Type', 'audio/wav'))
def test_form_submit(self):
r = self.client.get(reverse('captcha-test'))
@@ -223,6 +223,7 @@ class CaptchaCase(TestCase):
try:
new_data = json.loads(six.text_type(r.content, encoding='ascii'))
self.assertTrue('image_url' in new_data)
+ self.assertTrue('audio_url' in new_data)
except:
self.fail()
diff --git a/captcha/urls.py b/captcha/urls.py
index ba09c02..b80d263 100644
--- a/captcha/urls.py
+++ b/captcha/urls.py
@@ -4,6 +4,6 @@ from captcha import views
urlpatterns = [
url(r'image/(?P<key>\w+)/$', views.captcha_image, name='captcha-image', kwargs={'scale': 1}),
url(r'image/(?P<key>\w+)@2/$', views.captcha_image, name='captcha-image-2x', kwargs={'scale': 2}),
- url(r'audio/(?P<key>\w+)/$', views.captcha_audio, name='captcha-audio'),
+ url(r'audio/(?P<key>\w+).wav$', views.captcha_audio, name='captcha-audio'),
url(r'refresh/$', views.captcha_refresh, name='captcha-refresh'),
]
diff --git a/captcha/views.py b/captcha/views.py
index 28a8249..3b3b727 100644
--- a/captcha/views.py
+++ b/captcha/views.py
@@ -1,10 +1,10 @@
from captcha.conf import settings
-from captcha.helpers import captcha_image_url
+from captcha.helpers import captcha_image_url, captcha_audio_url
from captcha.models import CaptchaStore
from django.http import HttpResponse, Http404
from django.core.exceptions import ImproperlyConfigured
+from ranged_response import RangedFileResponse
import random
-import re
import tempfile
import os
import subprocess
@@ -15,21 +15,15 @@ try:
except ImportError:
from io import BytesIO as StringIO
-try:
- from PIL import Image, ImageDraw, ImageFont
-except ImportError:
- import Image
- import ImageDraw
- import ImageFont
+from PIL import Image, ImageDraw, ImageFont
try:
import json
except ImportError:
from django.utils import simplejson as json
-NON_DIGITS_RX = re.compile('[^\d]')
# Distance of the drawn text from the top of the captcha image
-from_top = 4
+DISTNACE_FROM_TOP = 4
def getsize(font, text):
@@ -75,11 +69,6 @@ def captcha_image(request, key, scale=1):
size = (size[0] * 2, int(size[1] * 1.4))
image = makeimg(size)
-
- try:
- PIL_VERSION = int(NON_DIGITS_RX.sub('', Image.VERSION))
- except:
- PIL_VERSION = 116
xpos = 2
charlist = []
@@ -94,14 +83,11 @@ def captcha_image(request, key, scale=1):
chardraw = ImageDraw.Draw(charimage)
chardraw.text((0, 0), ' %s ' % char, font=font, fill='#ffffff')
if settings.CAPTCHA_LETTER_ROTATION:
- if PIL_VERSION >= 116:
- charimage = charimage.rotate(random.randrange(*settings.CAPTCHA_LETTER_ROTATION), expand=0, resample=Image.BICUBIC)
- else:
- charimage = charimage.rotate(random.randrange(*settings.CAPTCHA_LETTER_ROTATION), resample=Image.BICUBIC)
+ charimage = charimage.rotate(random.randrange(*settings.CAPTCHA_LETTER_ROTATION), expand=0, resample=Image.BICUBIC)
charimage = charimage.crop(charimage.getbbox())
maskimage = Image.new('L', size)
- maskimage.paste(charimage, (xpos, from_top, xpos + charimage.size[0], from_top + charimage.size[1]))
+ maskimage.paste(charimage, (xpos, DISTNACE_FROM_TOP, xpos + charimage.size[0], DISTNACE_FROM_TOP + charimage.size[1]))
size = maskimage.size
image = Image.composite(fgimage, image, maskimage)
xpos = xpos + 2 + charimage.size[0]
@@ -109,7 +95,7 @@ def captcha_image(request, key, scale=1):
if settings.CAPTCHA_IMAGE_SIZE:
# centering captcha on the image
tmpimg = makeimg(size)
- tmpimg.paste(image, (int((size[0] - xpos) / 2), int((size[1] - charimage.size[1]) / 2 - from_top)))
+ tmpimg.paste(image, (int((size[0] - xpos) / 2), int((size[1] - charimage.size[1]) / 2 - DISTNACE_FROM_TOP)))
image = tmpimg.crop((0, 0, size[0], size[1]))
else:
image = image.crop((0, 0, xpos + 1, size[1]))
@@ -146,13 +132,20 @@ def captcha_audio(request, key):
text = ', '.join(list(text))
path = str(os.path.join(tempfile.gettempdir(), '%s.wav' % key))
subprocess.call([settings.CAPTCHA_FLITE_PATH, "-t", text, "-o", path])
+
+ # Add arbitrary noise if sox is installed
+ if settings.CAPTCHA_SOX_PATH:
+ arbnoisepath = str(os.path.join(tempfile.gettempdir(), '%s_arbitrary.wav') % key)
+ mergedpath = str(os.path.join(tempfile.gettempdir(), '%s_merged.wav') % key)
+ subprocess.call([settings.CAPTCHA_SOX_PATH, '-r', '8000', '-n', arbnoisepath, 'synth', '2', 'brownnoise', 'gain', '-15'])
+ subprocess.call([settings.CAPTCHA_SOX_PATH, '-m', arbnoisepath, path, '-t', 'wavpcm', '-b', '16', mergedpath])
+ os.remove(arbnoisepath)
+ os.remove(path)
+ os.rename(mergedpath, path)
+
if os.path.isfile(path):
- response = HttpResponse()
- f = open(path, 'rb')
- response['Content-Type'] = 'audio/x-wav'
- response.write(f.read())
- f.close()
- os.unlink(path)
+ response = RangedFileResponse(request, open(path, 'rb'), content_type='audio/wav')
+ response['Content-Disposition'] = 'attachment; filename="{}.wav"'.format(key)
return response
raise Http404
@@ -166,5 +159,6 @@ def captcha_refresh(request):
to_json_response = {
'key': new_key,
'image_url': captcha_image_url(new_key),
+ 'audio_url': captcha_audio_url(new_key) if settings.CAPTCHA_FLITE_PATH else None
}
return HttpResponse(json.dumps(to_json_response), content_type='application/json')
diff --git a/django_simple_captcha.egg-info/PKG-INFO b/django_simple_captcha.egg-info/PKG-INFO
index 48fb03c..7669864 100644
--- a/django_simple_captcha.egg-info/PKG-INFO
+++ b/django_simple_captcha.egg-info/PKG-INFO
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: django-simple-captcha
-Version: 0.5.5
+Version: 0.5.6
Summary: A very simple, yet powerful, Django captcha application
Home-page: https://github.com/mbi/django-simple-captcha
Author: Marco Bonetti
Author-email: mbonetti at gmail.com
License: MIT
+Description-Content-Type: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
diff --git a/django_simple_captcha.egg-info/SOURCES.txt b/django_simple_captcha.egg-info/SOURCES.txt
index cc4628d..9c92bb6 100644
--- a/django_simple_captcha.egg-info/SOURCES.txt
+++ b/django_simple_captcha.egg-info/SOURCES.txt
@@ -89,5 +89,25 @@ testproject/manage.py
testproject/settings.py
testproject/urls.py
testproject/views.py
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha___init___py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf___init___py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf_settings_py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_fields_py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_helpers_py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_models_py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_urls_py.html
+testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_views_py.html
+testproject/htmlcov/coverage_html.js
+testproject/htmlcov/index.html
+testproject/htmlcov/jquery.ba-throttle-debounce.min.js
+testproject/htmlcov/jquery.hotkeys.js
+testproject/htmlcov/jquery.isonscreen.js
+testproject/htmlcov/jquery.min.js
+testproject/htmlcov/jquery.tablesorter.min.js
+testproject/htmlcov/keybd_closed.png
+testproject/htmlcov/keybd_open.png
+testproject/htmlcov/status.json
+testproject/htmlcov/style.css
testproject/templates/home.html
-testproject/templates/captcha_test/image.html
\ No newline at end of file
+testproject/templates/captcha_test/image.html
+testproject/templates/captcha_test/image_html5_audio.html
\ No newline at end of file
diff --git a/django_simple_captcha.egg-info/requires.txt b/django_simple_captcha.egg-info/requires.txt
index 8839fe1..da1642e 100644
--- a/django_simple_captcha.egg-info/requires.txt
+++ b/django_simple_captcha.egg-info/requires.txt
@@ -1,4 +1,5 @@
setuptools
-six >=1.2.0
-Django >= 1.7
-Pillow >=2.2.2
+six>=1.2.0
+Django>=1.7
+Pillow>=2.2.2
+django-ranged-response==0.2.0
diff --git a/docs/advanced.rst b/docs/advanced.rst
index ca38124..8cba1cd 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -104,6 +104,20 @@ Full path to the ``flite`` executable. When defined, will automatically add audi
Defaults to: ``None`` (no audio output)
+CAPTCHA_SOX_PATH
+------------------------
+
+Full path to the ``sox`` executable. If audio output is enabled via ``CAPTCHA_FLITE_PATH``, the generated output audio file is identical across multiple generations (unlike CAPTCHA images which get different random noise each time they are rendered). User appleorange1_ has shown_ that this could be used to pre-generate a "rainbow-table" of all possible input strings and a hash of the generated output soundfile, thus rendering an attack on audio CAPTCHAs trivial.
+
+If sox_ is installed and used via this settings, random brown noise is injected into the generated audio file, rendering attacks via a rainbow table impossible.
+
+Defaults to: ``None`` (no audio output)
+
+.. _appleorange1: https://github.com/appleorange1
+.. _shown: https://github.com/appleorange1/django-simple-captcha-cracker-poc
+.. _sox: http://sox.sourceforge.net/
+
+
CAPTCHA_TIMEOUT
---------------
diff --git a/docs/conf.py b/docs/conf.py
index 6b62f62..45fe322 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -44,14 +44,14 @@ master_doc = 'index'
# General information about the project.
project = u('Django Simple Captcha')
-copyright = u('2011-2016 Marco Bonetti')
+copyright = u('2011-2017 Marco Bonetti')
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '0.5.5'
+version = '0.5.6'
# The full version, including alpha/beta/rc tags.
release = version
diff --git a/docs/usage.rst b/docs/usage.rst
index b5cc306..9cad3a1 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -4,22 +4,14 @@ Using django-simple-captcha
Installation
+++++++++++++
-1. Download ``django-simple-captcha`` using pip_ by running: ``pip install django-simple-captcha``
+1. Install ``django-simple-captcha`` via pip_: ``pip install django-simple-captcha``
2. Add ``captcha`` to the ``INSTALLED_APPS`` in your ``settings.py``
-3. Run ``python manage.py syncdb`` (or ``python manage.py migrate`` if you are managing database migrations via South) to create the required database tables
+3. Run ``python manage.py migrate``
4. Add an entry to your ``urls.py``::
- urlpatterns += patterns('',
+ urlpatterns += [
url(r'^captcha/', include('captcha.urls')),
- )
-
-
-Django-simple-captcha 0.4.3 and later supports both Django 1.7's new migrations and South migrations: if you are using South and Django < 1.7, you must define the following in your settings::
-
- SOUTH_MIGRATION_MODULES = {
- 'captcha': 'captcha.south_migrations',
- }
-
+ ]
.. _pip: http://pypi.python.org/pypi/pip
diff --git a/setup.cfg b/setup.cfg
index 6f08d0e..adf5ed7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,5 +4,4 @@ universal = 1
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff --git a/setup.py b/setup.py
index 05e9953..46662fe 100644
--- a/setup.py
+++ b/setup.py
@@ -31,7 +31,8 @@ install_requires = [
'setuptools',
'six >=1.2.0',
'Django >= 1.7',
- 'Pillow >=2.2.2'
+ 'Pillow >=2.2.2',
+ 'django-ranged-response == 0.2.0'
]
setup(
diff --git a/testproject/coverage.sh b/testproject/coverage.sh
index 52422e1..be54f03 100644
--- a/testproject/coverage.sh
+++ b/testproject/coverage.sh
@@ -1,5 +1,6 @@
#!/bin/bash
export CAPTCHA_FLITE_PATH=`which flite`
+export CAPTCHA_SOX_PATH=`which sox`
coverage run --rcfile .coveragerc manage.py test --failfast captcha
coverage xml
coverage html
diff --git a/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha___init___py.html b/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha___init___py.html
new file mode 100644
index 0000000..640f8ab
--- /dev/null
+++ b/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha___init___py.html
@@ -0,0 +1,103 @@
+
+
+
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+
+ <meta http-equiv="X-UA-Compatible" content="IE=emulateIE7" />
+ <title>Coverage for /Users/marco/Code/django-simple-captcha/captcha/__init__.py: 100.00%</title>
+ <link rel="stylesheet" href="style.css" type="text/css">
+
+ <script type="text/javascript" src="jquery.min.js"></script>
+ <script type="text/javascript" src="jquery.hotkeys.js"></script>
+ <script type="text/javascript" src="jquery.isonscreen.js"></script>
+ <script type="text/javascript" src="coverage_html.js"></script>
+ <script type="text/javascript">
+ jQuery(document).ready(coverage.pyfile_ready);
+ </script>
+</head>
+<body class="pyfile">
+
+<div id="header">
+ <div class="content">
+ <h1>Coverage for <b>/Users/marco/Code/django-simple-captcha/captcha/__init__.py</b> :
+ <span class="pc_cov">100.00%</span>
+ </h1>
+
+ <img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
+
+ <h2 class="stats">
+ 3 statements
+ <span class="run hide_run shortkey_r button_toggle_run">3 run</span>
+ <span class="mis shortkey_m button_toggle_mis">0 missing</span>
+ <span class="exc shortkey_x button_toggle_exc">0 excluded</span>
+
+
+ <span class="par run hide_run shortkey_p button_toggle_par">0 partial</span>
+
+ </h2>
+ </div>
+</div>
+
+<div class="help_panel">
+ <img id="panel_icon" src="keybd_open.png" alt="Hide keyboard shortcuts" />
+ <p class="legend">Hot-keys on this page</p>
+ <div>
+ <p class="keyhelp">
+ <span class="key">r</span>
+ <span class="key">m</span>
+ <span class="key">x</span>
+ <span class="key">p</span> toggle line displays
+ </p>
+ <p class="keyhelp">
+ <span class="key">j</span>
+ <span class="key">k</span> next/prev highlighted chunk
+ </p>
+ <p class="keyhelp">
+ <span class="key">0</span> (zero) top of page
+ </p>
+ <p class="keyhelp">
+ <span class="key">1</span> (one) first highlighted chunk
+ </p>
+ </div>
+</div>
+
+<div id="source">
+ <table>
+ <tr>
+ <td class="linenos">
+<p id="n1" class="stm run hide_run"><a href="#n1">1</a></p>
+<p id="n2" class="pln"><a href="#n2">2</a></p>
+<p id="n3" class="pln"><a href="#n3">3</a></p>
+<p id="n4" class="stm run hide_run"><a href="#n4">4</a></p>
+<p id="n5" class="pln"><a href="#n5">5</a></p>
+<p id="n6" class="stm run hide_run"><a href="#n6">6</a></p>
+
+ </td>
+ <td class="text">
+<p id="t1" class="stm run hide_run"><span class="nam">VERSION</span> <span class="op">=</span> <span class="op">(</span><span class="num">0</span><span class="op">,</span> <span class="num">5</span><span class="op">,</span> <span class="num">6</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t2" class="pln"><span class="strut"> </span></p>
+<p id="t3" class="pln"><span class="strut"> </span></p>
+<p id="t4" class="stm run hide_run"><span class="key">def</span> <span class="nam">get_version</span><span class="op">(</span><span class="nam">svn</span><span class="op">=</span><span class="key">False</span><span class="op">)</span><span class="op">:</span><span class="strut"> </span></p>
+<p id="t5" class="pln"> <span class="str">"Return the version as a human-format string."</span><span class="strut"> </span></p>
+<p id="t6" class="stm run hide_run"> <span class="key">return</span> <span class="str">'.'</span><span class="op">.</span><span class="nam">join</span><span class="op">(</span><span class="op">[</span><span class="nam">str</span><span class="op">(</span><span class="nam">i</span><span class="op">)</span> <span class="key">for</span> <span class="nam">i</span> <span class="key">in</span> <span class="nam">VERSION</span><span class="op">]</span><span class="op">)</span><span class="stru [...]
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id="footer">
+ <div class="content">
+ <p>
+ <a class="nav" href="index.html">« index</a> <a class="nav" href="https://coverage.readthedocs.io">coverage.py v4.4.2</a>,
+ created at 2017-11-08 13:41
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf___init___py.html b/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf___init___py.html
new file mode 100644
index 0000000..10f7d48
--- /dev/null
+++ b/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf___init___py.html
@@ -0,0 +1,91 @@
+
+
+
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+
+ <meta http-equiv="X-UA-Compatible" content="IE=emulateIE7" />
+ <title>Coverage for /Users/marco/Code/django-simple-captcha/captcha/conf/__init__.py: 100.00%</title>
+ <link rel="stylesheet" href="style.css" type="text/css">
+
+ <script type="text/javascript" src="jquery.min.js"></script>
+ <script type="text/javascript" src="jquery.hotkeys.js"></script>
+ <script type="text/javascript" src="jquery.isonscreen.js"></script>
+ <script type="text/javascript" src="coverage_html.js"></script>
+ <script type="text/javascript">
+ jQuery(document).ready(coverage.pyfile_ready);
+ </script>
+</head>
+<body class="pyfile">
+
+<div id="header">
+ <div class="content">
+ <h1>Coverage for <b>/Users/marco/Code/django-simple-captcha/captcha/conf/__init__.py</b> :
+ <span class="pc_cov">100.00%</span>
+ </h1>
+
+ <img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
+
+ <h2 class="stats">
+ 0 statements
+ <span class="run hide_run shortkey_r button_toggle_run">0 run</span>
+ <span class="mis shortkey_m button_toggle_mis">0 missing</span>
+ <span class="exc shortkey_x button_toggle_exc">0 excluded</span>
+
+
+ <span class="par run hide_run shortkey_p button_toggle_par">0 partial</span>
+
+ </h2>
+ </div>
+</div>
+
+<div class="help_panel">
+ <img id="panel_icon" src="keybd_open.png" alt="Hide keyboard shortcuts" />
+ <p class="legend">Hot-keys on this page</p>
+ <div>
+ <p class="keyhelp">
+ <span class="key">r</span>
+ <span class="key">m</span>
+ <span class="key">x</span>
+ <span class="key">p</span> toggle line displays
+ </p>
+ <p class="keyhelp">
+ <span class="key">j</span>
+ <span class="key">k</span> next/prev highlighted chunk
+ </p>
+ <p class="keyhelp">
+ <span class="key">0</span> (zero) top of page
+ </p>
+ <p class="keyhelp">
+ <span class="key">1</span> (one) first highlighted chunk
+ </p>
+ </div>
+</div>
+
+<div id="source">
+ <table>
+ <tr>
+ <td class="linenos">
+
+ </td>
+ <td class="text">
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id="footer">
+ <div class="content">
+ <p>
+ <a class="nav" href="index.html">« index</a> <a class="nav" href="https://coverage.readthedocs.io">coverage.py v4.4.2</a>,
+ created at 2017-11-08 13:41
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf_settings_py.html b/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf_settings_py.html
new file mode 100644
index 0000000..1cbccae
--- /dev/null
+++ b/testproject/htmlcov/_Users_marco_Code_django-simple-captcha_captcha_conf_settings_py.html
@@ -0,0 +1,207 @@
+
+
+
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+
+ <meta http-equiv="X-UA-Compatible" content="IE=emulateIE7" />
+ <title>Coverage for /Users/marco/Code/django-simple-captcha/captcha/conf/settings.py: 88.46%</title>
+ <link rel="stylesheet" href="style.css" type="text/css">
+
+ <script type="text/javascript" src="jquery.min.js"></script>
+ <script type="text/javascript" src="jquery.hotkeys.js"></script>
+ <script type="text/javascript" src="jquery.isonscreen.js"></script>
+ <script type="text/javascript" src="coverage_html.js"></script>
+ <script type="text/javascript">
+ jQuery(document).ready(coverage.pyfile_ready);
+ </script>
+</head>
+<body class="pyfile">
+
+<div id="header">
+ <div class="content">
+ <h1>Coverage for <b>/Users/marco/Code/django-simple-captcha/captcha/conf/settings.py</b> :
+ <span class="pc_cov">88.46%</span>
+ </h1>
+
+ <img id="keyboard_icon" src="keybd_closed.png" alt="Show keyboard shortcuts" />
+
+ <h2 class="stats">
+ 44 statements
+ <span class="run hide_run shortkey_r button_toggle_run">41 run</span>
+ <span class="mis shortkey_m button_toggle_mis">3 missing</span>
+ <span class="exc shortkey_x button_toggle_exc">0 excluded</span>
+
+
+ <span class="par run hide_run shortkey_p button_toggle_par">3 partial</span>
+
+ </h2>
+ </div>
+</div>
+
+<div class="help_panel">
+ <img id="panel_icon" src="keybd_open.png" alt="Hide keyboard shortcuts" />
+ <p class="legend">Hot-keys on this page</p>
+ <div>
+ <p class="keyhelp">
+ <span class="key">r</span>
+ <span class="key">m</span>
+ <span class="key">x</span>
+ <span class="key">p</span> toggle line displays
+ </p>
+ <p class="keyhelp">
+ <span class="key">j</span>
+ <span class="key">k</span> next/prev highlighted chunk
+ </p>
+ <p class="keyhelp">
+ <span class="key">0</span> (zero) top of page
+ </p>
+ <p class="keyhelp">
+ <span class="key">1</span> (one) first highlighted chunk
+ </p>
+ </div>
+</div>
+
+<div id="source">
+ <table>
+ <tr>
+ <td class="linenos">
+<p id="n1" class="stm run hide_run"><a href="#n1">1</a></p>
+<p id="n2" class="stm run hide_run"><a href="#n2">2</a></p>
+<p id="n3" class="pln"><a href="#n3">3</a></p>
+<p id="n4" class="stm run hide_run"><a href="#n4">4</a></p>
+<p id="n5" class="stm run hide_run"><a href="#n5">5</a></p>
+<p id="n6" class="stm run hide_run"><a href="#n6">6</a></p>
+<p id="n7" class="stm run hide_run"><a href="#n7">7</a></p>
+<p id="n8" class="stm run hide_run"><a href="#n8">8</a></p>
+<p id="n9" class="stm run hide_run"><a href="#n9">9</a></p>
+<p id="n10" class="stm run hide_run"><a href="#n10">10</a></p>
+<p id="n11" class="stm run hide_run"><a href="#n11">11</a></p>
+<p id="n12" class="stm run hide_run"><a href="#n12">12</a></p>
+<p id="n13" class="stm run hide_run"><a href="#n13">13</a></p>
+<p id="n14" class="stm run hide_run"><a href="#n14">14</a></p>
+<p id="n15" class="stm run hide_run"><a href="#n15">15</a></p>
+<p id="n16" class="stm run hide_run"><a href="#n16">16</a></p>
+<p id="n17" class="stm run hide_run"><a href="#n17">17</a></p>
+<p id="n18" class="pln"><a href="#n18">18</a></p>
+<p id="n19" class="stm run hide_run"><a href="#n19">19</a></p>
+<p id="n20" class="stm run hide_run"><a href="#n20">20</a></p>
+<p id="n21" class="stm run hide_run"><a href="#n21">21</a></p>
+<p id="n22" class="stm run hide_run"><a href="#n22">22</a></p>
+<p id="n23" class="stm run hide_run"><a href="#n23">23</a></p>
+<p id="n24" class="stm run hide_run"><a href="#n24">24</a></p>
+<p id="n25" class="stm run hide_run"><a href="#n25">25</a></p>
+<p id="n26" class="stm run hide_run"><a href="#n26">26</a></p>
+<p id="n27" class="stm run hide_run"><a href="#n27">27</a></p>
+<p id="n28" class="stm run hide_run"><a href="#n28">28</a></p>
+<p id="n29" class="stm run hide_run"><a href="#n29">29</a></p>
+<p id="n30" class="pln"><a href="#n30">30</a></p>
+<p id="n31" class="stm run hide_run"><a href="#n31">31</a></p>
+<p id="n32" class="pln"><a href="#n32">32</a></p>
+<p id="n33" class="pln"><a href="#n33">33</a></p>
+<p id="n34" class="stm par run hide_run"><a href="#n34">34</a></p>
+<p id="n35" class="stm mis"><a href="#n35">35</a></p>
+<p id="n36" class="pln"><a href="#n36">36</a></p>
+<p id="n37" class="pln"><a href="#n37">37</a></p>
+<p id="n38" class="stm run hide_run"><a href="#n38">38</a></p>
+<p id="n39" class="stm run hide_run"><a href="#n39">39</a></p>
+<p id="n40" class="stm run hide_run"><a href="#n40">40</a></p>
+<p id="n41" class="pln"><a href="#n41">41</a></p>
+<p id="n42" class="stm run hide_run"><a href="#n42">42</a></p>
+<p id="n43" class="pln"><a href="#n43">43</a></p>
+<p id="n44" class="pln"><a href="#n44">44</a></p>
+<p id="n45" class="stm run hide_run"><a href="#n45">45</a></p>
+<p id="n46" class="stm run hide_run"><a href="#n46">46</a></p>
+<p id="n47" class="pln"><a href="#n47">47</a></p>
+<p id="n48" class="pln"><a href="#n48">48</a></p>
+<p id="n49" class="stm run hide_run"><a href="#n49">49</a></p>
+<p id="n50" class="stm par run hide_run"><a href="#n50">50</a></p>
+<p id="n51" class="stm run hide_run"><a href="#n51">51</a></p>
+<p id="n52" class="stm mis"><a href="#n52">52</a></p>
+<p id="n53" class="pln"><a href="#n53">53</a></p>
+<p id="n54" class="pln"><a href="#n54">54</a></p>
+<p id="n55" class="stm run hide_run"><a href="#n55">55</a></p>
+<p id="n56" class="stm par run hide_run"><a href="#n56">56</a></p>
+<p id="n57" class="stm run hide_run"><a href="#n57">57</a></p>
+<p id="n58" class="stm mis"><a href="#n58">58</a></p>
+
+ </td>
+ <td class="text">
+<p id="t1" class="stm run hide_run"><span class="key">import</span> <span class="nam">os</span><span class="strut"> </span></p>
+<p id="t2" class="stm run hide_run"><span class="key">from</span> <span class="nam">django</span><span class="op">.</span><span class="nam">conf</span> <span class="key">import</span> <span class="nam">settings</span><span class="strut"> </span></p>
+<p id="t3" class="pln"><span class="strut"> </span></p>
+<p id="t4" class="stm run hide_run"><span class="nam">CAPTCHA_FONT_PATH</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_FONT_PATH'</span><span class="op">,</span> <span class="nam">os</span><span class="op">.</span><span class="nam">path</span><span class="op">.</span><span class="nam">normpath</span><span class="op">(</span><span class="nam">os</span><span clas [...]
+<p id="t5" class="stm run hide_run"><span class="nam">CAPTCHA_FONT_SIZE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_FONT_SIZE'</span><span class="op">,</span> <span class="num">22</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t6" class="stm run hide_run"><span class="nam">CAPTCHA_LETTER_ROTATION</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_LETTER_ROTATION'</span><span class="op">,</span> <span class="op">(</span><span class="op">-</span><span class="num">35</span><span class="op">,</span> <span class="num">35</span><span class="op">)</span><span class="op">)</span><span cla [...]
+<p id="t7" class="stm run hide_run"><span class="nam">CAPTCHA_BACKGROUND_COLOR</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_BACKGROUND_COLOR'</span><span class="op">,</span> <span class="str">'#ffffff'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t8" class="stm run hide_run"><span class="nam">CAPTCHA_FOREGROUND_COLOR</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_FOREGROUND_COLOR'</span><span class="op">,</span> <span class="str">'#001100'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t9" class="stm run hide_run"><span class="nam">CAPTCHA_CHALLENGE_FUNCT</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_CHALLENGE_FUNCT'</span><span class="op">,</span> <span class="str">'captcha.helpers.random_char_challenge'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t10" class="stm run hide_run"><span class="nam">CAPTCHA_NOISE_FUNCTIONS</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_NOISE_FUNCTIONS'</span><span class="op">,</span> <span class="op">(</span><span class="str">'captcha.helpers.noise_arcs'</span><span class="op">,</span> <span class="str">'captcha.helpers.noise_dots'</span><span class="op">,</span><span [...]
+<p id="t11" class="stm run hide_run"><span class="nam">CAPTCHA_FILTER_FUNCTIONS</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_FILTER_FUNCTIONS'</span><span class="op">,</span> <span class="op">(</span><span class="str">'captcha.helpers.post_smooth'</span><span class="op">,</span><span class="op">)</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t12" class="stm run hide_run"><span class="nam">CAPTCHA_WORDS_DICTIONARY</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_WORDS_DICTIONARY'</span><span class="op">,</span> <span class="str">'/usr/share/dict/words'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t13" class="stm run hide_run"><span class="nam">CAPTCHA_PUNCTUATION</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_PUNCTUATION'</span><span class="op">,</span> <span class="str">'''_"',.;:-'''</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t14" class="stm run hide_run"><span class="nam">CAPTCHA_FLITE_PATH</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_FLITE_PATH'</span><span class="op">,</span> <span class="key">None</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t15" class="stm run hide_run"><span class="nam">CAPTCHA_SOX_PATH</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_SOX_PATH'</span><span class="op">,</span> <span class="key">None</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t16" class="stm run hide_run"><span class="nam">CAPTCHA_TIMEOUT</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_TIMEOUT'</span><span class="op">,</span> <span class="num">5</span><span class="op">)</span> <span class="com"># Minutes</span><span class="strut"> </span></p>
+<p id="t17" class="stm run hide_run"><span class="nam">CAPTCHA_LENGTH</span> <span class="op">=</span> <span class="nam">int</span><span class="op">(</span><span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_LENGTH'</span><span class="op">,</span> <span class="num">4</span><span class="op">)</span><span class="op">)</span> <span class="com"># Chars</span><span class="strut"> </span></p>
+<p id="t18" class="pln"><span class="com"># CAPTCHA_IMAGE_BEFORE_FIELD = getattr(settings, 'CAPTCHA_IMAGE_BEFORE_FIELD', True)</span><span class="strut"> </span></p>
+<p id="t19" class="stm run hide_run"><span class="nam">CAPTCHA_DICTIONARY_MIN_LENGTH</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_DICTIONARY_MIN_LENGTH'</span><span class="op">,</span> <span class="num">0</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t20" class="stm run hide_run"><span class="nam">CAPTCHA_DICTIONARY_MAX_LENGTH</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_DICTIONARY_MAX_LENGTH'</span><span class="op">,</span> <span class="num">99</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t21" class="stm run hide_run"><span class="nam">CAPTCHA_IMAGE_SIZE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_IMAGE_SIZE'</span><span class="op">,</span> <span class="key">None</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t22" class="stm run hide_run"><span class="nam">CAPTCHA_IMAGE_TEMPLATE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_IMAGE_TEMPLATE'</span><span class="op">,</span> <span class="str">'captcha/image.html'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t23" class="stm run hide_run"><span class="nam">CAPTCHA_HIDDEN_FIELD_TEMPLATE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_HIDDEN_FIELD_TEMPLATE'</span><span class="op">,</span> <span class="str">'captcha/hidden_field.html'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t24" class="stm run hide_run"><span class="nam">CAPTCHA_TEXT_FIELD_TEMPLATE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_TEXT_FIELD_TEMPLATE'</span><span class="op">,</span> <span class="str">'captcha/text_field.html'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t25" class="stm run hide_run"><span class="nam">CAPTCHA_FIELD_TEMPLATE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_FIELD_TEMPLATE'</span><span class="op">,</span> <span class="str">'captcha/field.html'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t26" class="stm run hide_run"><span class="nam">CAPTCHA_OUTPUT_FORMAT</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_OUTPUT_FORMAT'</span><span class="op">,</span> <span class="key">None</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t27" class="stm run hide_run"><span class="nam">CAPTCHA_MATH_CHALLENGE_OPERATOR</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_MATH_CHALLENGE_OPERATOR'</span><span class="op">,</span> <span class="str">'*'</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t28" class="stm run hide_run"><span class="nam">CAPTCHA_GET_FROM_POOL</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_GET_FROM_POOL'</span><span class="op">,</span> <span class="key">False</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t29" class="stm run hide_run"><span class="nam">CAPTCHA_GET_FROM_POOL_TIMEOUT</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_GET_FROM_POOL_TIMEOUT'</span><span class="op">,</span> <span class="num">5</span><span class="op">)</span><span class="strut"> </span></p>
+<p id="t30" class="pln"><span class="strut"> </span></p>
+<p id="t31" class="stm run hide_run"><span class="nam">CAPTCHA_TEST_MODE</span> <span class="op">=</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CAPTCHA_TEST_MODE'</span><span class="op">,</span> <span class="nam">getattr</span><span class="op">(</span><span class="nam">settings</span><span class="op">,</span> <span class="str">'CATPCHA_TEST_MODE'</span><span class="op">,</span> <span class="k [...]
+<p id="t32" class="pln"><span class="strut"> </span></p>
+<p id="t33" class="pln"><span class="com"># Failsafe</span><span class="strut"> </span></p>
+<p id="t34" class="stm par run hide_run"><span class="annotate short">34 ↛ 35</span><span class="annotate long">line 34 didn't jump to line 35, because the condition on line 34 was never true</span><span class="key">if</span> <span class="nam">CAPTCHA_DICTIONARY_MIN_LENGTH</span> <span class="op">></span> <span class="nam">CAPTCHA_DICTIONARY_MAX_LENGTH</span><span class="op">:</span><span class="strut"> </span></p>
+<p id="t35" class="stm mis"> <span class="nam">CAPTCHA_DICTIONARY_MIN_LENGTH</span><span class="op">,</span> <span class="nam">CAPTCHA_DICTIONARY_MAX_LENGTH</span> <span class="op">=</span> <span class="nam">CAPTCHA_DICTIONARY_MAX_LENGTH</span><span class="op">,</span> <span class="nam">CAPTCHA_DICTIONARY_MIN_LENGTH</span><span class="strut"> </span></p>
+<p id="t36" class="pln"><span class="strut"> </span></p>
+<p id="t37" class="pln"><span class="strut"> </span></p>
+<p id="t38" class="stm run hide_run"><span class="key">def</span> <span class="nam">_callable_from_string</span><span class="op">(</span><span class="nam">string_or_callable</span><span class="op">)</span><span class="op">:</span><span class="strut"> </span></p>
+<p id="t39" class="stm run hide_run"> <span class="key">if</span> <span class="nam">callable</span><span class="op">(</span><span class="nam">string_or_callable</span><span class="op">)</span><span class="op">:</span><span class="strut"> </span></p>
+<p id="t40" class="stm run hide_run"> <span class="key">return</span> <span class="nam">string_or_callable</span><span class="strut"> </span></p>
+<p id="t41" class="pln"> <span class="key">else</span><span class="op">:</span><span class="strut"> </span></p>
... 3071 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-simple-captcha.git
More information about the Python-modules-commits
mailing list