diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a30f6af --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: python +install: + - pip install tox coveralls +script: + - tox +env: + - TOXENV=py27-1.7 + - TOXENV=py32-1.7 + - TOXENV=py33-1.7 + - TOXENV=py27-master + - TOXENV=py32-master + - TOXENV=py33-master +after_success: coveralls diff --git a/formtools/__init__.py b/formtools/__init__.py index b82588d..6c3a1cf 100644 --- a/formtools/__init__.py +++ b/formtools/__init__.py @@ -1 +1,3 @@ -default_app_config = 'django.contrib.formtools.apps.FormToolsConfig' +__version__ = '1.0' + +default_app_config = 'formtools.apps.FormToolsConfig' diff --git a/formtools/apps.py b/formtools/apps.py index 9b76766..66cb0e7 100644 --- a/formtools/apps.py +++ b/formtools/apps.py @@ -1,8 +1,7 @@ from django.apps import AppConfig - from django.utils.translation import ugettext_lazy as _ class FormToolsConfig(AppConfig): - name = 'django.contrib.formtools' + name = 'formtools' verbose_name = _("Form Tools") diff --git a/formtools/preview.py b/formtools/preview.py index 02e6f27..0761ea2 100644 --- a/formtools/preview.py +++ b/formtools/preview.py @@ -1,12 +1,12 @@ """ Formtools Preview application. """ - from django.http import Http404 from django.shortcuts import render_to_response from django.template.context import RequestContext from django.utils.crypto import constant_time_compare -from django.contrib.formtools.utils import form_hmac + +from .utils import form_hmac AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter. @@ -22,7 +22,10 @@ class FormPreview(object): self.form, self.state = form, {} def __call__(self, request, *args, **kwargs): - stage = {'1': 'preview', '2': 'post'}.get(request.POST.get(self.unused_name('stage')), 'preview') + stage = { + '1': 'preview', + '2': 'post', + }.get(request.POST.get(self.unused_name('stage')), 'preview') self.parse_params(*args, **kwargs) try: method = getattr(self, stage + '_' + request.method.lower()) @@ -48,38 +51,47 @@ class FormPreview(object): def preview_get(self, request): "Displays the form" - f = self.form(auto_id=self.get_auto_id(), initial=self.get_initial(request)) + f = self.form(auto_id=self.get_auto_id(), + initial=self.get_initial(request)) return render_to_response(self.form_template, self.get_context(request, f), context_instance=RequestContext(request)) def preview_post(self, request): - "Validates the POST data. If valid, displays the preview page. Else, redisplays form." + """ + Validates the POST data. If valid, displays the preview page. + Else, redisplays form. + """ f = self.form(request.POST, auto_id=self.get_auto_id()) context = self.get_context(request, f) if f.is_valid(): self.process_preview(request, f, context) context['hash_field'] = self.unused_name('hash') context['hash_value'] = self.security_hash(request, f) - return render_to_response(self.preview_template, context, context_instance=RequestContext(request)) + return render_to_response(self.preview_template, context, + context_instance=RequestContext(request)) else: - return render_to_response(self.form_template, context, context_instance=RequestContext(request)) + return render_to_response(self.form_template, context, + context_instance=RequestContext(request)) def _check_security_hash(self, token, request, form): expected = self.security_hash(request, form) return constant_time_compare(token, expected) def post_post(self, request): - "Validates the POST data. If valid, calls done(). Else, redisplays form." - f = self.form(request.POST, auto_id=self.get_auto_id()) - if f.is_valid(): - if not self._check_security_hash(request.POST.get(self.unused_name('hash'), ''), - request, f): + """ + Validates the POST data. If valid, calls done(). Else, redisplays form. + """ + form = self.form(request.POST, auto_id=self.get_auto_id()) + if form.is_valid(): + if not self._check_security_hash( + request.POST.get(self.unused_name('hash'), ''), + request, form): return self.failed_hash(request) # Security hash failed. - return self.done(request, f.cleaned_data) + return self.done(request, form.cleaned_data) else: return render_to_response(self.form_template, - self.get_context(request, f), + self.get_context(request, form), context_instance=RequestContext(request)) # METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ######################## @@ -100,7 +112,11 @@ class FormPreview(object): def get_context(self, request, form): "Context for template rendering." - return {'form': form, 'stage_field': self.unused_name('stage'), 'state': self.state} + return { + 'form': form, + 'stage_field': self.unused_name('stage'), + 'state': self.state, + } def parse_params(self, *args, **kwargs): """ @@ -127,7 +143,8 @@ class FormPreview(object): def security_hash(self, request, form): """ - Calculates the security hash for the given HttpRequest and Form instances. + Calculates the security hash for the given HttpRequest and Form + instances. Subclasses may want to take into account request-specific information, such as the IP address. @@ -145,4 +162,5 @@ class FormPreview(object): Does something with the cleaned_data and returns an HttpResponseRedirect. """ - raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__) + raise NotImplementedError('You must define a done() method on your ' + '%s subclass.' % self.__class__.__name__) diff --git a/formtools/tests/wizard/test_loadstorage.py b/formtools/tests/wizard/test_loadstorage.py deleted file mode 100644 index f0f350e..0000000 --- a/formtools/tests/wizard/test_loadstorage.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.test import TestCase - -from django.contrib.formtools.wizard.storage import get_storage, MissingStorage -from django.contrib.formtools.wizard.storage.base import BaseStorage - - -class TestLoadStorage(TestCase): - def test_load_storage(self): - self.assertEqual( - type(get_storage('django.contrib.formtools.wizard.storage.base.BaseStorage', 'wizard1')), - BaseStorage) - - def test_missing_storage(self): - self.assertRaises(MissingStorage, get_storage, - 'django.contrib.formtools.wizard.storage.idontexist.IDontExistStorage', 'wizard1') - self.assertRaises(MissingStorage, get_storage, - 'django.contrib.formtools.wizard.storage.base.IDontExistStorage', 'wizard1') diff --git a/formtools/wizard/storage/__init__.py b/formtools/wizard/storage/__init__.py index 71a21f8..66aa9ea 100644 --- a/formtools/wizard/storage/__init__.py +++ b/formtools/wizard/storage/__init__.py @@ -1,8 +1,7 @@ from django.utils.module_loading import import_string -from django.contrib.formtools.wizard.storage.base import BaseStorage -from django.contrib.formtools.wizard.storage.exceptions import ( - MissingStorage, NoFileStorageConfigured) +from .base import BaseStorage +from .exceptions import MissingStorage, NoFileStorageConfigured __all__ = [ "BaseStorage", "MissingStorage", "NoFileStorageConfigured", "get_storage", diff --git a/formtools/wizard/storage/base.py b/formtools/wizard/storage/base.py index a0c0ac0..91b28c8 100644 --- a/formtools/wizard/storage/base.py +++ b/formtools/wizard/storage/base.py @@ -3,7 +3,7 @@ from django.utils.datastructures import MultiValueDict from django.utils.functional import lazy_property from django.utils import six -from django.contrib.formtools.wizard.storage.exceptions import NoFileStorageConfigured +from .exceptions import NoFileStorageConfigured class BaseStorage(object): diff --git a/formtools/wizard/storage/cookie.py b/formtools/wizard/storage/cookie.py index c05741c..55f19b1 100644 --- a/formtools/wizard/storage/cookie.py +++ b/formtools/wizard/storage/cookie.py @@ -1,9 +1,9 @@ import json -from django.contrib.formtools.wizard import storage +from .base import BaseStorage -class CookieStorage(storage.BaseStorage): +class CookieStorage(BaseStorage): encoder = json.JSONEncoder(separators=(',', ':')) def __init__(self, *args, **kwargs): @@ -21,6 +21,7 @@ class CookieStorage(storage.BaseStorage): def update_response(self, response): super(CookieStorage, self).update_response(response) if self.data: - response.set_signed_cookie(self.prefix, self.encoder.encode(self.data)) + response.set_signed_cookie(self.prefix, + self.encoder.encode(self.data)) else: response.delete_cookie(self.prefix) diff --git a/formtools/wizard/storage/session.py b/formtools/wizard/storage/session.py index 9cfae50..d8de26d 100644 --- a/formtools/wizard/storage/session.py +++ b/formtools/wizard/storage/session.py @@ -1,7 +1,7 @@ -from django.contrib.formtools.wizard import storage +from .base import BaseStorage -class SessionStorage(storage.BaseStorage): +class SessionStorage(BaseStorage): def __init__(self, *args, **kwargs): super(SessionStorage, self).__init__(*args, **kwargs) diff --git a/formtools/wizard/views.py b/formtools/wizard/views.py index 46bd309..981d0d2 100644 --- a/formtools/wizard/views.py +++ b/formtools/wizard/views.py @@ -10,9 +10,9 @@ from django.utils.decorators import classonlymethod from django.utils.translation import ugettext as _ from django.utils import six -from django.contrib.formtools.wizard.storage import get_storage -from django.contrib.formtools.wizard.storage.exceptions import NoFileStorageConfigured -from django.contrib.formtools.wizard.forms import ManagementForm +from .storage import get_storage +from .storage.exceptions import NoFileStorageConfigured +from .forms import ManagementForm def normalize_name(name): @@ -125,7 +125,7 @@ class WizardView(TemplateView): def get_initkwargs(cls, form_list=None, initial_dict=None, instance_dict=None, condition_dict=None, *args, **kwargs): """ - Creates a dict with all needed parameters for the form wizard instances. + Creates a dict with all needed parameters for the form wizard instances * `form_list` - is a list of forms. The list entries can be single form classes or tuples of (`step_name`, `form_class`). If you pass a list @@ -246,7 +246,7 @@ class WizardView(TemplateView): If a GET request reaches this point, the wizard assumes that the user just starts at the first step or wants to restart the process. - The data of the wizard will be resetted before rendering the first step. + The data of the wizard will be resetted before rendering the first step """ self.storage.reset() @@ -289,8 +289,10 @@ class WizardView(TemplateView): # and try to validate if form.is_valid(): # if the form is valid, store the cleaned data and files. - self.storage.set_step_data(self.steps.current, self.process_step(form)) - self.storage.set_step_files(self.steps.current, self.process_step_files(form)) + self.storage.set_step_data(self.steps.current, + self.process_step(form)) + self.storage.set_step_files(self.steps.current, + self.process_step_files(form)) # check if the current step is the last step if self.steps.current == self.steps.last: @@ -342,13 +344,17 @@ class WizardView(TemplateView): data=self.storage.get_step_data(form_key), files=self.storage.get_step_files(form_key)) if not form_obj.is_valid(): - return self.render_revalidation_failure(form_key, form_obj, **kwargs) + return self.render_revalidation_failure(form_key, + form_obj, + **kwargs) final_forms[form_key] = form_obj # render the done view and reset the wizard before returning the # response. This is needed to prevent from rendering done with the # same data twice. - done_response = self.done(final_forms.values(), form_dict=final_forms, **kwargs) + done_response = self.done(final_forms.values(), + form_dict=final_forms, + **kwargs) self.storage.reset() return done_response @@ -408,7 +414,8 @@ class WizardView(TemplateView): 'prefix': self.get_form_prefix(step, form_class), 'initial': self.get_form_initial(step), }) - if issubclass(form_class, (forms.ModelForm, forms.models.BaseInlineFormSet)): + if issubclass(form_class, (forms.ModelForm, + forms.models.BaseInlineFormSet)): # If the form is based on ModelForm or InlineFormSet, # add instance if available and not previously set. kwargs.setdefault('instance', self.get_form_instance(step)) @@ -544,7 +551,8 @@ class WizardView(TemplateView): class MyWizard(WizardView): def get_context_data(self, form, **kwargs): - context = super(MyWizard, self).get_context_data(form=form, **kwargs) + context = super(MyWizard, self).get_context_data(form=form, + **kwargs) if self.steps.current == 'my_step_name': context.update({'another_var': True}) return context @@ -581,14 +589,14 @@ class SessionWizardView(WizardView): """ A WizardView with pre-configured SessionStorage backend. """ - storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' class CookieWizardView(WizardView): """ A WizardView with pre-configured CookieStorage backend. """ - storage_name = 'django.contrib.formtools.wizard.storage.cookie.CookieStorage' + storage_name = 'formtools.wizard.storage.cookie.CookieStorage' class NamedUrlWizardView(WizardView): @@ -604,16 +612,19 @@ class NamedUrlWizardView(WizardView): We require a url_name to reverse URLs later. Additionally users can pass a done_step_name to change the URL name of the "done" view. """ - assert 'url_name' in kwargs, 'URL name is needed to resolve correct wizard URLs' + assert 'url_name' in kwargs, \ + 'URL name is needed to resolve correct wizard URLs' extra_kwargs = { 'done_step_name': kwargs.pop('done_step_name', 'done'), 'url_name': kwargs.pop('url_name'), } - initkwargs = super(NamedUrlWizardView, cls).get_initkwargs(*args, **kwargs) + initkwargs = super(NamedUrlWizardView, cls).get_initkwargs(*args, + **kwargs) initkwargs.update(extra_kwargs) assert initkwargs['done_step_name'] not in initkwargs['form_list'], \ - 'step name "%s" is reserved for "done" view' % initkwargs['done_step_name'] + 'step name "%s" is reserved for "done" view' % \ + initkwargs['done_step_name'] return initkwargs def get_step_url(self, step): @@ -679,7 +690,8 @@ class NamedUrlWizardView(WizardView): NamedUrlWizardView provides the url_name of this wizard in the context dict `wizard`. """ - context = super(NamedUrlWizardView, self).get_context_data(form=form, **kwargs) + context = super(NamedUrlWizardView, self).get_context_data(form=form, + **kwargs) context['wizard']['url_name'] = self.url_name return context @@ -722,11 +734,11 @@ class NamedUrlSessionWizardView(NamedUrlWizardView): """ A NamedUrlWizardView with pre-configured SessionStorage backend. """ - storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' class NamedUrlCookieWizardView(NamedUrlWizardView): """ A NamedUrlFormWizard with pre-configured CookieStorageBackend. """ - storage_name = 'django.contrib.formtools.wizard.storage.cookie.CookieStorage' + storage_name = 'formtools.wizard.storage.cookie.CookieStorage' diff --git a/tasks.py b/tasks.py new file mode 100644 index 0000000..dc6488b --- /dev/null +++ b/tasks.py @@ -0,0 +1,38 @@ +import os +import os.path +import sys +from invoke import run, task + + +@task +def clean(): + run('git clean -Xfd') + + +@task +def test(): + print('Python version: ' + sys.version) + test_cmd = 'coverage run `which django-admin.py` test --settings=tests.settings' + flake_cmd = 'flake8 --ignore=W801,E128,E501,W402' + + # Fix issue #49 + cwp = os.path.dirname(os.path.abspath(__name__)) + pythonpath = os.environ.get('PYTHONPATH', '').split(os.pathsep) + pythonpath.append(os.path.join(cwp, 'tests')) + os.environ['PYTHONPATH'] = os.pathsep.join(pythonpath) + + run('{0} formtools'.format(flake_cmd)) + run('{0} tests'.format(test_cmd)) + run('coverage report') + + +@task +def translations(pull=False): + if pull: + run('tx pull -a') + run('cd formtools; django-admin.py makemessages -a; django-admin.py compilemessages; cd ..') + + +@task +def docs(): + run('cd docs; make html; cd ..') diff --git a/formtools/tests/__init__.py b/tests/__init__.py similarity index 100% rename from formtools/tests/__init__.py rename to tests/__init__.py diff --git a/formtools/tests/forms.py b/tests/forms.py similarity index 100% rename from formtools/tests/forms.py rename to tests/forms.py diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..7885ef2 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,6 @@ +# invoke +# temporary fix for invoke on Python 3.2 +invoke==0.9.0 +coverage==3.7.1 +flake8==2.2.3 +six==1.8.0 diff --git a/tests/settings.py b/tests/settings.py new file mode 100644 index 0000000..afb2541 --- /dev/null +++ b/tests/settings.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } +} + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'formtools', + 'tests.wizard.wizardtests', +] + +SECRET_KEY = 'spam-spam-spam-spam' + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + 'LOCATION': 'spam-and-eggs' + } +} + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', +) diff --git a/formtools/tests/templates/404.html b/tests/templates/404.html similarity index 100% rename from formtools/tests/templates/404.html rename to tests/templates/404.html diff --git a/formtools/tests/templates/base.html b/tests/templates/base.html similarity index 100% rename from formtools/tests/templates/base.html rename to tests/templates/base.html diff --git a/formtools/tests/templates/forms/wizard.html b/tests/templates/forms/wizard.html similarity index 100% rename from formtools/tests/templates/forms/wizard.html rename to tests/templates/forms/wizard.html diff --git a/formtools/tests/tests.py b/tests/tests.py similarity index 97% rename from formtools/tests/tests.py rename to tests/tests.py index eb8043e..727201e 100644 --- a/formtools/tests/tests.py +++ b/tests/tests.py @@ -7,13 +7,12 @@ import unittest import warnings from django import http -from django.contrib.formtools import preview, utils from django.test import TestCase, override_settings from django.utils._os import upath -from django.contrib.formtools.tests.forms import ( - HashTestBlankForm, HashTestForm, TestForm, -) +from formtools import preview, utils + +from .forms import HashTestBlankForm, HashTestForm, TestForm success_string = "Done was called!" success_string_encoded = success_string.encode() @@ -36,7 +35,7 @@ class TestFormPreview(preview.FormPreview): TEMPLATE_DIRS=( os.path.join(os.path.dirname(upath(__file__)), 'templates'), ), - ROOT_URLCONF='django.contrib.formtools.tests.urls', + ROOT_URLCONF='tests.urls', ) class PreviewTests(TestCase): diff --git a/formtools/tests/urls.py b/tests/urls.py similarity index 61% rename from formtools/tests/urls.py rename to tests/urls.py index 2811ce4..ed3ba99 100644 --- a/formtools/tests/urls.py +++ b/tests/urls.py @@ -3,9 +3,9 @@ This is a URLconf to be loaded by tests.py. Add any URLs needed for tests only. """ from django.conf.urls import url -from django.contrib.formtools.tests.tests import TestFormPreview -from django.contrib.formtools.tests.forms import TestForm +from .tests import TestFormPreview +from .forms import TestForm urlpatterns = [ diff --git a/formtools/tests/wizard/__init__.py b/tests/wizard/__init__.py similarity index 100% rename from formtools/tests/wizard/__init__.py rename to tests/wizard/__init__.py diff --git a/formtools/tests/wizard/namedwizardtests/__init__.py b/tests/wizard/namedwizardtests/__init__.py similarity index 100% rename from formtools/tests/wizard/namedwizardtests/__init__.py rename to tests/wizard/namedwizardtests/__init__.py diff --git a/formtools/tests/wizard/namedwizardtests/forms.py b/tests/wizard/namedwizardtests/forms.py similarity index 86% rename from formtools/tests/wizard/namedwizardtests/forms.py rename to tests/wizard/namedwizardtests/forms.py index 6e38a8a..0cf1495 100644 --- a/formtools/tests/wizard/namedwizardtests/forms.py +++ b/tests/wizard/namedwizardtests/forms.py @@ -9,7 +9,7 @@ from django.template import Template, Context from django.contrib.auth.models import User -from django.contrib.formtools.wizard.views import NamedUrlWizardView +from formtools.wizard.views import NamedUrlWizardView temp_storage_location = tempfile.mkdtemp(dir=os.environ.get('DJANGO_TEST_TEMP_DIR')) temp_storage = FileSystemStorage(location=temp_storage_location) @@ -51,8 +51,8 @@ class ContactWizard(NamedUrlWizardView): class SessionContactWizard(ContactWizard): - storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' class CookieContactWizard(ContactWizard): - storage_name = 'django.contrib.formtools.wizard.storage.cookie.CookieStorage' + storage_name = 'formtools.wizard.storage.cookie.CookieStorage' diff --git a/formtools/tests/wizard/namedwizardtests/tests.py b/tests/wizard/namedwizardtests/tests.py similarity index 96% rename from formtools/tests/wizard/namedwizardtests/tests.py rename to tests/wizard/namedwizardtests/tests.py index 6a03361..759f21e 100644 --- a/formtools/tests/wizard/namedwizardtests/tests.py +++ b/tests/wizard/namedwizardtests/tests.py @@ -10,11 +10,11 @@ from django.utils._os import upath from django.contrib.auth.models import User from django.contrib.auth.tests.utils import skipIfCustomUser -from django.contrib.formtools.wizard.views import (NamedUrlSessionWizardView, - NamedUrlCookieWizardView) -from django.contrib.formtools.tests.wizard.test_forms import get_request, Step1, Step2 +from formtools.wizard.views import (NamedUrlSessionWizardView, + NamedUrlCookieWizardView) from .forms import temp_storage +from ..test_forms import get_request, Step1, Step2 # On Python 2, __file__ may end with .pyc @@ -308,7 +308,7 @@ class NamedWizardTests(object): @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.namedwizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.namedwizardtests.urls') class NamedSessionWizardTests(NamedWizardTests, TestCase): wizard_urlname = 'nwiz_session' wizard_step_1_data = { @@ -341,7 +341,7 @@ class NamedSessionWizardTests(NamedWizardTests, TestCase): @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.namedwizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.namedwizardtests.urls') class NamedCookieWizardTests(NamedWizardTests, TestCase): wizard_urlname = 'nwiz_cookie' wizard_step_1_data = { @@ -402,14 +402,14 @@ class TestNamedUrlCookieWizardView(NamedUrlCookieWizardView): @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.namedwizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.namedwizardtests.urls') class NamedSessionFormTests(NamedFormTests, TestCase): formwizard_class = TestNamedUrlSessionWizardView wizard_urlname = 'nwiz_session' @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.namedwizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.namedwizardtests.urls') class NamedCookieFormTests(NamedFormTests, TestCase): formwizard_class = TestNamedUrlCookieWizardView wizard_urlname = 'nwiz_cookie' diff --git a/formtools/tests/wizard/namedwizardtests/urls.py b/tests/wizard/namedwizardtests/urls.py similarity index 85% rename from formtools/tests/wizard/namedwizardtests/urls.py rename to tests/wizard/namedwizardtests/urls.py index 0cf9224..df93692 100644 --- a/formtools/tests/wizard/namedwizardtests/urls.py +++ b/tests/wizard/namedwizardtests/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -from django.contrib.formtools.tests.wizard.namedwizardtests.forms import ( - SessionContactWizard, CookieContactWizard, Page1, Page2, Page3, Page4) +from .forms import (SessionContactWizard, CookieContactWizard, + Page1, Page2, Page3, Page4) def get_named_session_wizard(): diff --git a/formtools/tests/wizard/storage.py b/tests/wizard/storage.py similarity index 100% rename from formtools/tests/wizard/storage.py rename to tests/wizard/storage.py diff --git a/formtools/tests/wizard/test_cookiestorage.py b/tests/wizard/test_cookiestorage.py similarity index 91% rename from formtools/tests/wizard/test_cookiestorage.py rename to tests/wizard/test_cookiestorage.py index e5377e9..2a80b15 100644 --- a/formtools/tests/wizard/test_cookiestorage.py +++ b/tests/wizard/test_cookiestorage.py @@ -3,8 +3,9 @@ from django.core import signing from django.http import HttpResponse from django.contrib.auth.tests.utils import skipIfCustomUser -from django.contrib.formtools.wizard.storage.cookie import CookieStorage -from django.contrib.formtools.tests.wizard.storage import get_request, TestStorage +from formtools.wizard.storage.cookie import CookieStorage + +from .storage import get_request, TestStorage @skipIfCustomUser diff --git a/formtools/tests/wizard/test_forms.py b/tests/wizard/test_forms.py similarity index 96% rename from formtools/tests/wizard/test_forms.py rename to tests/wizard/test_forms.py index 9ae99cc..d94ef92 100644 --- a/formtools/tests/wizard/test_forms.py +++ b/tests/wizard/test_forms.py @@ -10,9 +10,9 @@ from django.template.response import TemplateResponse from django.contrib.auth.models import User -from django.contrib.formtools.wizard.views import (WizardView, - SessionWizardView, - CookieWizardView) +from formtools.wizard.views import (WizardView, + SessionWizardView, + CookieWizardView) class DummyRequest(http.HttpRequest): @@ -69,7 +69,7 @@ TestModelFormSet = forms.models.modelformset_factory(TestModel, form=TestModelFo class TestWizard(WizardView): - storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' def dispatch(self, request, *args, **kwargs): response = super(TestWizard, self).dispatch(request, *args, **kwargs) diff --git a/tests/wizard/test_loadstorage.py b/tests/wizard/test_loadstorage.py new file mode 100644 index 0000000..e753fb6 --- /dev/null +++ b/tests/wizard/test_loadstorage.py @@ -0,0 +1,17 @@ +from django.test import TestCase + +from formtools.wizard.storage import get_storage, MissingStorage +from formtools.wizard.storage.base import BaseStorage + + +class TestLoadStorage(TestCase): + def test_load_storage(self): + self.assertEqual( + type(get_storage('formtools.wizard.storage.base.BaseStorage', 'wizard1')), + BaseStorage) + + def test_missing_storage(self): + self.assertRaises(MissingStorage, get_storage, + 'formtools.wizard.storage.idontexist.IDontExistStorage', 'wizard1') + self.assertRaises(MissingStorage, get_storage, + 'formtools.wizard.storage.base.IDontExistStorage', 'wizard1') diff --git a/formtools/tests/wizard/test_sessionstorage.py b/tests/wizard/test_sessionstorage.py similarity index 60% rename from formtools/tests/wizard/test_sessionstorage.py rename to tests/wizard/test_sessionstorage.py index 0bd9fd8..2116881 100644 --- a/formtools/tests/wizard/test_sessionstorage.py +++ b/tests/wizard/test_sessionstorage.py @@ -1,8 +1,9 @@ from django.test import TestCase from django.contrib.auth.tests.utils import skipIfCustomUser -from django.contrib.formtools.tests.wizard.storage import TestStorage -from django.contrib.formtools.wizard.storage.session import SessionStorage +from formtools.wizard.storage.session import SessionStorage + +from .storage import TestStorage @skipIfCustomUser diff --git a/formtools/tests/wizard/wizardtests/__init__.py b/tests/wizard/wizardtests/__init__.py similarity index 100% rename from formtools/tests/wizard/wizardtests/__init__.py rename to tests/wizard/wizardtests/__init__.py diff --git a/formtools/tests/wizard/wizardtests/forms.py b/tests/wizard/wizardtests/forms.py similarity index 89% rename from formtools/tests/wizard/wizardtests/forms.py rename to tests/wizard/wizardtests/forms.py index 5e4617c..a44710e 100644 --- a/formtools/tests/wizard/wizardtests/forms.py +++ b/tests/wizard/wizardtests/forms.py @@ -9,7 +9,7 @@ from django.forms.models import modelformset_factory from django.http import HttpResponse from django.template import Template, Context -from django.contrib.formtools.wizard.views import WizardView +from formtools.wizard.views import WizardView temp_storage_location = tempfile.mkdtemp(dir=os.environ.get('DJANGO_TEST_TEMP_DIR')) @@ -65,8 +65,8 @@ UserFormSet = modelformset_factory(User, form=UserForm) class SessionContactWizard(ContactWizard): - storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' class CookieContactWizard(ContactWizard): - storage_name = 'django.contrib.formtools.wizard.storage.cookie.CookieStorage' + storage_name = 'formtools.wizard.storage.cookie.CookieStorage' diff --git a/formtools/tests/models.py b/tests/wizard/wizardtests/models.py similarity index 100% rename from formtools/tests/models.py rename to tests/wizard/wizardtests/models.py diff --git a/formtools/tests/wizard/wizardtests/templates/other_wizard_form.html b/tests/wizard/wizardtests/templates/other_wizard_form.html similarity index 100% rename from formtools/tests/wizard/wizardtests/templates/other_wizard_form.html rename to tests/wizard/wizardtests/templates/other_wizard_form.html diff --git a/formtools/tests/wizard/wizardtests/tests.py b/tests/wizard/wizardtests/tests.py similarity index 97% rename from formtools/tests/wizard/wizardtests/tests.py rename to tests/wizard/wizardtests/tests.py index b880dcb..2b4d960 100644 --- a/formtools/tests/wizard/wizardtests/tests.py +++ b/tests/wizard/wizardtests/tests.py @@ -9,10 +9,11 @@ from django.test.client import RequestFactory from django.conf import settings from django.contrib.auth.models import User from django.contrib.auth.tests.utils import skipIfCustomUser -from django.contrib.formtools.wizard.views import CookieWizardView from django.utils._os import upath -from django.contrib.formtools.tests.models import Poet, Poem +from formtools.wizard.views import CookieWizardView + +from .models import Poet, Poem from .forms import temp_storage @@ -233,7 +234,7 @@ class WizardTests(object): @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.wizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.wizardtests.urls') class SessionWizardTests(WizardTests, TestCase): wizard_url = '/wiz_session/' wizard_step_1_data = { @@ -266,7 +267,7 @@ class SessionWizardTests(WizardTests, TestCase): @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.wizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.wizardtests.urls') class CookieWizardTests(WizardTests, TestCase): wizard_url = '/wiz_cookie/' wizard_step_1_data = { @@ -299,7 +300,7 @@ class CookieWizardTests(WizardTests, TestCase): @skipIfCustomUser -@override_settings(ROOT_URLCONF='django.contrib.formtools.tests.wizard.wizardtests.urls') +@override_settings(ROOT_URLCONF='tests.wizard.wizardtests.urls') class WizardTestKwargs(TestCase): wizard_url = '/wiz_other_template/' wizard_step_1_data = { diff --git a/formtools/tests/wizard/wizardtests/urls.py b/tests/wizard/wizardtests/urls.py similarity index 80% rename from formtools/tests/wizard/wizardtests/urls.py rename to tests/wizard/wizardtests/urls.py index 300ac13..2b978e3 100644 --- a/formtools/tests/wizard/wizardtests/urls.py +++ b/tests/wizard/wizardtests/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -from django.contrib.formtools.tests.wizard.wizardtests.forms import ( - SessionContactWizard, CookieContactWizard, Page1, Page2, Page3, Page4) +from .forms import (SessionContactWizard, CookieContactWizard, + Page1, Page2, Page3, Page4) urlpatterns = [ url(r'^wiz_session/$', SessionContactWizard.as_view( diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..cd8a425 --- /dev/null +++ b/tox.ini @@ -0,0 +1,47 @@ +[tox] +args_are_paths = false +envlist = + py27-1.7, py27-master, + py32-1.7, py32-master, + py33-1.7, py33-master + +[testenv] +usedevelop = true +commands = + invoke test {posargs} +django15 = + Django>=1.5,<1.6 + -r{toxinidir}/tests/requirements.txt +django16 = + Django>=1.6,<1.7 + -r{toxinidir}/tests/requirements.txt +django17 = + Django>=1.7,<1.8 + -r{toxinidir}/tests/requirements.txt +djangomaster = + https://github.com/django/django/archive/master.zip + -r{toxinidir}/tests/requirements.txt + +[testenv:py27-1.7] +basepython = python2.7 +deps = {[testenv]django17} + +[testenv:py27-master] +basepython = python2.7 +deps = {[testenv]djangomaster} + +[testenv:py32-1.7] +basepython = python3.2 +deps = {[testenv]django17} + +[testenv:py32-master] +basepython = python3.2 +deps = {[testenv]djangomaster} + +[testenv:py33-1.7] +basepython = python3.3 +deps = {[testenv]django17} + +[testenv:py33-master] +basepython = python3.3 +deps = {[testenv]djangomaster}