summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Bogdał <adam@bogdal.pl>2015-10-21 21:50:12 +0200
committerAdam Bogdał <adam@bogdal.pl>2015-10-21 21:50:12 +0200
commit2afa08e1f7142c8c5c3c09806e75a6cf9513ab82 (patch)
treec6b7ac89f86109d931a88e40510e293822f63c0e
parent62256b3ac37d74b120e9f3b7a8a7006b6447350a (diff)
downloaddjango-payments-taler-2afa08e1f7142c8c5c3c09806e75a6cf9513ab82.tar.gz
django-payments-taler-2afa08e1f7142c8c5c3c09806e75a6cf9513ab82.tar.bz2
django-payments-taler-2afa08e1f7142c8c5c3c09806e75a6cf9513ab82.zip
Make the package compatible with various django versions
-rw-r--r--.travis.yml34
-rw-r--r--payments/__init__.py149
-rw-r--r--payments/authorizenet/__init__.py3
-rw-r--r--payments/braintree/__init__.py3
-rw-r--r--payments/coinbase/__init__.py2
-rw-r--r--payments/coinbase/test_coinbase.py1
-rw-r--r--payments/core.py152
-rw-r--r--payments/cybersource/__init__.py5
-rw-r--r--payments/cybersource/test_cybersource.py2
-rw-r--r--payments/dotpay/__init__.py2
-rw-r--r--payments/dummy/__init__.py3
-rw-r--r--payments/dummy/test_dummy.py4
-rw-r--r--payments/fields.py2
-rw-r--r--payments/models.py2
-rw-r--r--payments/paypal/__init__.py4
-rw-r--r--payments/paypal/forms.py2
-rw-r--r--payments/paypal/test_paypal.py2
-rw-r--r--payments/sagepay/__init__.py2
-rw-r--r--payments/sofort/__init__.py3
-rw-r--r--payments/sofort/test_sofort.py2
-rw-r--r--payments/stripe/__init__.py4
-rw-r--r--payments/stripe/forms.py4
-rw-r--r--payments/stripe/test_stripe.py5
-rw-r--r--payments/stripe/widgets.py5
-rw-r--r--payments/templates/payments/sofort/new_transaction.xml2
-rw-r--r--payments/templates/payments/sofort/refund_transaction.xml2
-rw-r--r--payments/test_core.py2
-rw-r--r--payments/urls.py2
-rw-r--r--payments/wallet/__init__.py2
-rw-r--r--test_settings.py9
-rw-r--r--tox.ini6
31 files changed, 229 insertions, 193 deletions
diff --git a/.travis.yml b/.travis.yml
index 4e308b9..e8d72b2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,31 @@
language: python
-python:
- - 2.7
- - 3.3
- - 3.4
+sudo: false
install:
- - python setup.py install
- - pip install coverage
- - pip install codecov
+ - pip install tox codecov
script:
- - coverage run setup.py test
+ - tox
+env:
+ - TOXENV=py27-django14
+ - TOXENV=py27-django18
+ - TOXENV=py27-django19
+ - TOXENV=py27-django_master
+ - TOXENV=py34-django14
+ - TOXENV=py34-django18
+ - TOXENV=py34-django19
+ - TOXENV=py34-django_master
+ - TOXENV=py35-django18
+ - TOXENV=py35-django19
+ - TOXENV=py35-django_master
+matrix:
+ allow_failures:
+ - env: TOXENV=py27-django_master
+ - env: TOXENV=py34-django_master
+ - env: TOXENV=py35-django_master
after_success:
- codecov
+addons:
+ apt:
+ sources:
+ - deadsnakes
+ packages:
+ - python3.5 \ No newline at end of file
diff --git a/payments/__init__.py b/payments/__init__.py
index 9cd55b1..2aeae27 100644
--- a/payments/__init__.py
+++ b/payments/__init__.py
@@ -1,41 +1,9 @@
-from __future__ import unicode_literals
from collections import namedtuple
-import re
-try:
- from urllib.parse import urljoin, urlencode
-except ImportError:
- from urllib import urlencode
- from urlparse import urljoin
-
-from django.conf import settings
-from django.contrib.sites.models import Site
-from django.core.exceptions import ImproperlyConfigured
-from django.db.models import get_model
-
-PAYMENT_VARIANTS = {
- 'default': ('payments.dummy.DummyProvider', {})}
-
-PAYMENT_HOST = getattr(settings, 'PAYMENT_HOST', None)
-PAYMENT_USES_SSL = getattr(settings, 'PAYMENT_USES_SSL', False)
-
-if not PAYMENT_HOST:
- if not 'django.contrib.sites' in settings.INSTALLED_APPS:
- raise ImproperlyConfigured('The PAYMENT_HOST setting without '
- 'the sites app must not be empty.')
PurchasedItem = namedtuple('PurchasedItem',
'name, quantity, price, currency, sku')
-def get_base_url():
- protocol = 'https' if PAYMENT_USES_SSL else 'http'
- if not PAYMENT_HOST:
- current_site = Site.objects.get_current()
- domain = current_site.domain
- return '%s://%s' % (protocol, domain)
- return '%s://%s' % (protocol, PAYMENT_HOST)
-
-
class RedirectNeeded(Exception):
pass
@@ -46,120 +14,3 @@ class PaymentError(Exception):
class ExternalPostNeeded(Exception):
pass
-
-
-class BasicProvider(object):
- '''
- This class defines the provider API. It should not be instantiated
- directly. Use factory instead.
- '''
- _method = 'post'
-
- def get_action(self, payment):
- return self.get_return_url(payment)
-
- def __init__(self, capture=True):
- self._capture = capture
-
- def get_hidden_fields(self, payment):
- '''
- Converts a payment into a dict containing transaction data. Use
- get_form instead to get a form suitable for templates.
-
- When implementing a new payment provider, overload this method to
- transfer provider-specific data.
- '''
- raise NotImplementedError()
-
- def get_form(self, payment, data=None):
- '''
- Converts *payment* into a form suitable for Django templates.
- '''
- from .forms import PaymentForm
- return PaymentForm(self.get_hidden_fields(payment),
- self.get_action(payment), self._method)
-
- def process_data(self, payment, request):
- '''
- Process callback request from a payment provider.
- '''
- raise NotImplementedError()
-
- def get_token_from_request(self, payment, request):
- '''
- Return payment token from provider request.
- '''
- raise NotImplementedError()
-
- def get_return_url(self, payment, extra_data=None):
- payment_link = payment.get_process_url()
- url = urljoin(get_base_url(), payment_link)
- if extra_data:
- qs = urlencode(extra_data)
- return url + '?' + qs
- return url
-
- def capture(self, payment, amount=None):
- raise NotImplementedError()
-
- def release(self, payment):
- raise NotImplementedError()
-
- def refund(self, payment, amount=None):
- raise NotImplementedError()
-
-
-PROVIDER_CACHE = {}
-
-
-def provider_factory(variant):
- '''
- Return the provider instance based on variant
- '''
- variants = getattr(settings, 'PAYMENT_VARIANTS', PAYMENT_VARIANTS)
- handler, config = variants.get(variant, (None, None))
- if not handler:
- raise ValueError('Payment variant does not exist: %s' %
- (variant,))
- if variant not in PROVIDER_CACHE:
- module_path, class_name = handler.rsplit('.', 1)
- module = __import__(
- str(module_path), globals(), locals(), [str(class_name)])
- class_ = getattr(module, class_name)
- PROVIDER_CACHE[variant] = class_(**config)
- return PROVIDER_CACHE[variant]
-
-
-def get_payment_model():
- '''
- Return the Payment model that is active in this project
- '''
- try:
- app_label, model_name = settings.PAYMENT_MODEL.split('.')
- except (ValueError, AttributeError):
- raise ImproperlyConfigured('PAYMENT_MODEL must be of the form '
- '"app_label.model_name"')
- payment_model = get_model(app_label, model_name)
- if payment_model is None:
- msg = (
- 'PAYMENT_MODEL refers to model "%s" that has not been installed' %
- settings.PAYMENT_MODEL)
- raise ImproperlyConfigured(msg)
- return payment_model
-
-
-CARD_TYPES = [
- (r'^4[0-9]{12}(?:[0-9]{3})?$', 'visa', 'VISA'),
- (r'^5[1-5][0-9]{14}$', 'mastercard', 'MasterCard'),
- (r'^6(?:011|5[0-9]{2})[0-9]{12}$', 'discover', 'Discover'),
- (r'^3[47][0-9]{13}$', 'amex', 'American Express'),
- (r'^(?:(?:2131|1800|35\d{3})\d{11})$', 'jcb', 'JCB'),
- (r'^(?:3(?:0[0-5]|[68][0-9])[0-9]{11})$', 'diners', 'Diners Club'),
- (r'^(?:5[0678]\d\d|6304|6390|67\d\d)\d{8,15}$', 'maestro', 'Maestro')]
-
-
-def get_credit_card_issuer(number):
- for regexp, card_type, name in CARD_TYPES:
- if re.match(regexp, number):
- return card_type, name
- return None, None
diff --git a/payments/authorizenet/__init__.py b/payments/authorizenet/__init__.py
index 6a92a14..c910157 100644
--- a/payments/authorizenet/__init__.py
+++ b/payments/authorizenet/__init__.py
@@ -5,7 +5,8 @@ from django.http import HttpResponseForbidden
import requests
from .forms import PaymentForm
-from .. import BasicProvider, RedirectNeeded
+from .. import RedirectNeeded
+from ..core import BasicProvider
class AuthorizeNetProvider(BasicProvider):
diff --git a/payments/braintree/__init__.py b/payments/braintree/__init__.py
index 8552330..4d95cb2 100644
--- a/payments/braintree/__init__.py
+++ b/payments/braintree/__init__.py
@@ -4,7 +4,8 @@ import braintree
from django.core.exceptions import ImproperlyConfigured
from .forms import BraintreePaymentForm
-from .. import BasicProvider, RedirectNeeded
+from .. import RedirectNeeded
+from ..core import BasicProvider
class BraintreeProvider(BasicProvider):
diff --git a/payments/coinbase/__init__.py b/payments/coinbase/__init__.py
index 5348132..fea8b0a 100644
--- a/payments/coinbase/__init__.py
+++ b/payments/coinbase/__init__.py
@@ -10,7 +10,7 @@ from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponse, HttpResponseForbidden
import requests
-from .. import BasicProvider
+from ..core import BasicProvider
class CoinbaseProvider(BasicProvider):
diff --git a/payments/coinbase/test_coinbase.py b/payments/coinbase/test_coinbase.py
index e329581..40dcb30 100644
--- a/payments/coinbase/test_coinbase.py
+++ b/payments/coinbase/test_coinbase.py
@@ -9,7 +9,6 @@ from django.http import HttpResponse, HttpResponseForbidden
from mock import MagicMock, patch
from . import CoinbaseProvider
-from payments import RedirectNeeded
PAYMENT_TOKEN = '5a4dae68-2715-4b1e-8bb2-2c2dbe9255f6'
KEY = 'abc123'
diff --git a/payments/core.py b/payments/core.py
new file mode 100644
index 0000000..649fbae
--- /dev/null
+++ b/payments/core.py
@@ -0,0 +1,152 @@
+from __future__ import unicode_literals
+import re
+try:
+ from urllib.parse import urljoin, urlencode
+except ImportError:
+ from urllib import urlencode
+ from urlparse import urljoin
+try:
+ from django.db.models import get_model
+except ImportError:
+ from django.apps import apps
+ get_model = apps.get_model
+from django.conf import settings
+from django.contrib.sites.models import Site
+from django.core.exceptions import ImproperlyConfigured
+
+PAYMENT_VARIANTS = {
+ 'default': ('payments.dummy.DummyProvider', {})}
+
+PAYMENT_HOST = getattr(settings, 'PAYMENT_HOST', None)
+PAYMENT_USES_SSL = getattr(settings, 'PAYMENT_USES_SSL', False)
+
+if not PAYMENT_HOST:
+ if not 'django.contrib.sites' in settings.INSTALLED_APPS:
+ raise ImproperlyConfigured('The PAYMENT_HOST setting without '
+ 'the sites app must not be empty.')
+
+
+def get_base_url():
+ protocol = 'https' if PAYMENT_USES_SSL else 'http'
+ if not PAYMENT_HOST:
+ current_site = Site.objects.get_current()
+ domain = current_site.domain
+ return '%s://%s' % (protocol, domain)
+ return '%s://%s' % (protocol, PAYMENT_HOST)
+
+
+class BasicProvider(object):
+ '''
+ This class defines the provider API. It should not be instantiated
+ directly. Use factory instead.
+ '''
+ _method = 'post'
+
+ def get_action(self, payment):
+ return self.get_return_url(payment)
+
+ def __init__(self, capture=True):
+ self._capture = capture
+
+ def get_hidden_fields(self, payment):
+ '''
+ Converts a payment into a dict containing transaction data. Use
+ get_form instead to get a form suitable for templates.
+
+ When implementing a new payment provider, overload this method to
+ transfer provider-specific data.
+ '''
+ raise NotImplementedError()
+
+ def get_form(self, payment, data=None):
+ '''
+ Converts *payment* into a form suitable for Django templates.
+ '''
+ from .forms import PaymentForm
+ return PaymentForm(self.get_hidden_fields(payment),
+ self.get_action(payment), self._method)
+
+ def process_data(self, payment, request):
+ '''
+ Process callback request from a payment provider.
+ '''
+ raise NotImplementedError()
+
+ def get_token_from_request(self, payment, request):
+ '''
+ Return payment token from provider request.
+ '''
+ raise NotImplementedError()
+
+ def get_return_url(self, payment, extra_data=None):
+ payment_link = payment.get_process_url()
+ url = urljoin(get_base_url(), payment_link)
+ if extra_data:
+ qs = urlencode(extra_data)
+ return url + '?' + qs
+ return url
+
+ def capture(self, payment, amount=None):
+ raise NotImplementedError()
+
+ def release(self, payment):
+ raise NotImplementedError()
+
+ def refund(self, payment, amount=None):
+ raise NotImplementedError()
+
+
+PROVIDER_CACHE = {}
+
+
+def provider_factory(variant):
+ '''
+ Return the provider instance based on variant
+ '''
+ variants = getattr(settings, 'PAYMENT_VARIANTS', PAYMENT_VARIANTS)
+ handler, config = variants.get(variant, (None, None))
+ if not handler:
+ raise ValueError('Payment variant does not exist: %s' %
+ (variant,))
+ if variant not in PROVIDER_CACHE:
+ module_path, class_name = handler.rsplit('.', 1)
+ module = __import__(
+ str(module_path), globals(), locals(), [str(class_name)])
+ class_ = getattr(module, class_name)
+ PROVIDER_CACHE[variant] = class_(**config)
+ return PROVIDER_CACHE[variant]
+
+
+def get_payment_model():
+ '''
+ Return the Payment model that is active in this project
+ '''
+ try:
+ app_label, model_name = settings.PAYMENT_MODEL.split('.')
+ except (ValueError, AttributeError):
+ raise ImproperlyConfigured('PAYMENT_MODEL must be of the form '
+ '"app_label.model_name"')
+ payment_model = get_model(app_label, model_name)
+ if payment_model is None:
+ msg = (
+ 'PAYMENT_MODEL refers to model "%s" that has not been installed' %
+ settings.PAYMENT_MODEL)
+ raise ImproperlyConfigured(msg)
+ return payment_model
+
+
+CARD_TYPES = [
+ (r'^4[0-9]{12}(?:[0-9]{3})?$', 'visa', 'VISA'),
+ (r'^5[1-5][0-9]{14}$', 'mastercard', 'MasterCard'),
+ (r'^6(?:011|5[0-9]{2})[0-9]{12}$', 'discover', 'Discover'),
+ (r'^3[47][0-9]{13}$', 'amex', 'American Express'),
+ (r'^(?:(?:2131|1800|35\d{3})\d{11})$', 'jcb', 'JCB'),
+ (r'^(?:3(?:0[0-5]|[68][0-9])[0-9]{11})$', 'diners', 'Diners Club'),
+ (r'^(?:5[0678]\d\d|6304|6390|67\d\d)\d{8,15}$', 'maestro', 'Maestro')]
+
+
+def get_credit_card_issuer(number):
+ for regexp, card_type, name in CARD_TYPES:
+ if re.match(regexp, number):
+ return card_type, name
+ return None, None
diff --git a/payments/cybersource/__init__.py b/payments/cybersource/__init__.py
index a0ddf96..cad98a7 100644
--- a/payments/cybersource/__init__.py
+++ b/payments/cybersource/__init__.py
@@ -11,9 +11,8 @@ from suds.sudsobject import Object
import suds.wsse
from .forms import PaymentForm
-from .. import (
- BasicProvider, ExternalPostNeeded, get_credit_card_issuer, PaymentError,
- RedirectNeeded)
+from .. import ExternalPostNeeded, PaymentError, RedirectNeeded
+from ..core import BasicProvider, get_credit_card_issuer
from ..forms import PaymentForm as BaseForm
diff --git a/payments/cybersource/test_cybersource.py b/payments/cybersource/test_cybersource.py
index 1d8529f..ac16689 100644
--- a/payments/cybersource/test_cybersource.py
+++ b/payments/cybersource/test_cybersource.py
@@ -6,7 +6,7 @@ from mock import patch, MagicMock, Mock
from . import CyberSourceProvider, AUTHENTICATE_REQUIRED, ACCEPTED, \
TRANSACTION_SETTLED
-from payments import RedirectNeeded, ExternalPostNeeded, PurchasedItem
+from .. import RedirectNeeded, PurchasedItem
MERCHANT_ID = 'abcd1234'
PASSWORD = '1234abdd1234abcd'
diff --git a/payments/dotpay/__init__.py b/payments/dotpay/__init__.py
index fc3fd6d..6057db4 100644
--- a/payments/dotpay/__init__.py
+++ b/payments/dotpay/__init__.py
@@ -4,7 +4,7 @@ from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponse, HttpResponseForbidden
from .forms import ProcessPaymentForm
-from .. import BasicProvider
+from ..core import BasicProvider
CENTS = Decimal('0.01')
diff --git a/payments/dummy/__init__.py b/payments/dummy/__init__.py
index 99bab76..7774b27 100644
--- a/payments/dummy/__init__.py
+++ b/payments/dummy/__init__.py
@@ -10,7 +10,8 @@ except ImportError:
from django.http import HttpResponseRedirect
from .forms import DummyForm
-from .. import BasicProvider, RedirectNeeded, PaymentError
+from .. import RedirectNeeded, PaymentError
+from ..core import BasicProvider
class DummyProvider(BasicProvider):
diff --git a/payments/dummy/test_dummy.py b/payments/dummy/test_dummy.py
index d2bcbe8..a2733d0 100644
--- a/payments/dummy/test_dummy.py
+++ b/payments/dummy/test_dummy.py
@@ -10,10 +10,8 @@ try:
except ImportError:
from mock import MagicMock
-from payments import RedirectNeeded, PaymentError
-
from . import DummyProvider
-
+from .. import RedirectNeeded, PaymentError
VARIANT = 'dummy-3ds'
diff --git a/payments/fields.py b/payments/fields.py
index 9b5954e..55eb7b3 100644
--- a/payments/fields.py
+++ b/payments/fields.py
@@ -7,7 +7,7 @@ from django import forms
from django.core import validators
from django.utils.translation import ugettext_lazy as _
-from . import get_credit_card_issuer
+from .core import get_credit_card_issuer
from .widgets import CreditCardExpiryWidget, CreditCardNumberWidget
diff --git a/payments/models.py b/payments/models.py
index a20ea36..4d9e95a 100644
--- a/payments/models.py
+++ b/payments/models.py
@@ -7,7 +7,7 @@ from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy as _
-from . import provider_factory
+from .core import provider_factory
DEFAULT_PAYMENT_STATUS_CHOICES = (
('waiting', _('Waiting for confirmation')),
diff --git a/payments/paypal/__init__.py b/payments/paypal/__init__.py
index f2f955c..8a0da22 100644
--- a/payments/paypal/__init__.py
+++ b/payments/paypal/__init__.py
@@ -16,8 +16,8 @@ import requests
from requests.exceptions import HTTPError
from .forms import PaymentForm
-from .. import (
- BasicProvider, get_credit_card_issuer, PaymentError, RedirectNeeded)
+from .. import PaymentError, RedirectNeeded
+from ..core import BasicProvider, get_credit_card_issuer
# Get an instance of a logger
logger = logging.getLogger(__name__)
diff --git a/payments/paypal/forms.py b/payments/paypal/forms.py
index 5821528..8cda756 100644
--- a/payments/paypal/forms.py
+++ b/payments/paypal/forms.py
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
from requests.exceptions import HTTPError
from ..forms import CreditCardPaymentFormWithName
-from .. import get_credit_card_issuer
+from ..core import get_credit_card_issuer
class PaymentForm(CreditCardPaymentFormWithName):
diff --git a/payments/paypal/test_paypal.py b/payments/paypal/test_paypal.py
index 8db6aca..20221f7 100644
--- a/payments/paypal/test_paypal.py
+++ b/payments/paypal/test_paypal.py
@@ -5,10 +5,10 @@ from unittest import TestCase
from mock import patch, MagicMock, Mock
from django.utils import timezone
+from requests import HTTPError
from . import PaypalProvider, PaypalCardProvider
from .. import PurchasedItem, RedirectNeeded, PaymentError
-from requests import HTTPError
CLIENT_ID = 'abc123'
PAYMENT_TOKEN = '5a4dae68-2715-4b1e-8bb2-2c2dbe9255f6'
diff --git a/payments/sagepay/__init__.py b/payments/sagepay/__init__.py
index dfde2a4..9ec8fcb 100644
--- a/payments/sagepay/__init__.py
+++ b/payments/sagepay/__init__.py
@@ -5,7 +5,7 @@ from Crypto.Cipher import AES
from django.core.exceptions import ImproperlyConfigured
from django.shortcuts import redirect
-from .. import BasicProvider
+from ..core import BasicProvider
class SagepayProvider(BasicProvider):
diff --git a/payments/sofort/__init__.py b/payments/sofort/__init__.py
index 2a74c27..efde541 100644
--- a/payments/sofort/__init__.py
+++ b/payments/sofort/__init__.py
@@ -7,7 +7,8 @@ from django.utils.translation import get_language
import requests
import xmltodict
-from .. import BasicProvider, RedirectNeeded, PaymentError
+from .. import RedirectNeeded, PaymentError
+from ..core import BasicProvider
class SofortProvider(BasicProvider):
diff --git a/payments/sofort/test_sofort.py b/payments/sofort/test_sofort.py
index 996c79c..028b7f2 100644
--- a/payments/sofort/test_sofort.py
+++ b/payments/sofort/test_sofort.py
@@ -4,7 +4,7 @@ from mock import patch, MagicMock, Mock
import json
from . import SofortProvider
-from payments import RedirectNeeded
+from .. import RedirectNeeded
SECRET = 'abcd1234'
CLIENT_ID = '1234'
diff --git a/payments/stripe/__init__.py b/payments/stripe/__init__.py
index d6ebdf1..6a60f06 100644
--- a/payments/stripe/__init__.py
+++ b/payments/stripe/__init__.py
@@ -2,8 +2,10 @@ from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured
-from .. import BasicProvider, RedirectNeeded
+
from .forms import PaymentForm
+from .. import RedirectNeeded
+from ..core import BasicProvider
class StripeProvider(BasicProvider):
diff --git a/payments/stripe/forms.py b/payments/stripe/forms.py
index c19b5f1..5f4ea42 100644
--- a/payments/stripe/forms.py
+++ b/payments/stripe/forms.py
@@ -4,10 +4,10 @@ from django import forms
from django.utils.translation import ugettext as _
import stripe
+from .widgets import StripeWidget
+from .. import RedirectNeeded
from ..forms import PaymentForm as BasePaymentForm
from ..models import FRAUD_CHOICES
-from .widgets import StripeWidget
-from . import RedirectNeeded
class PaymentForm(BasePaymentForm):
diff --git a/payments/stripe/test_stripe.py b/payments/stripe/test_stripe.py
index 05bb47c..966d500 100644
--- a/payments/stripe/test_stripe.py
+++ b/payments/stripe/test_stripe.py
@@ -6,9 +6,8 @@ from mock import patch, Mock
from unittest import TestCase
import stripe
-from payments.stripe import StripeProvider
-
-from payments import RedirectNeeded
+from . import StripeProvider
+from .. import RedirectNeeded
SECRET_KEY = '1234abcd'
diff --git a/payments/stripe/widgets.py b/payments/stripe/widgets.py
index e8774a2..e7d5071 100644
--- a/payments/stripe/widgets.py
+++ b/payments/stripe/widgets.py
@@ -1,6 +1,9 @@
from __future__ import unicode_literals
-from django.forms.util import flatatt
+try:
+ from django.forms.utils import flatatt
+except ImportError:
+ from django.forms.util import flatatt
from django.forms.widgets import Input
from django.utils.html import format_html
from django.utils.encoding import force_text
diff --git a/payments/templates/payments/sofort/new_transaction.xml b/payments/templates/payments/sofort/new_transaction.xml
index d6b023e..5344715 100644
--- a/payments/templates/payments/sofort/new_transaction.xml
+++ b/payments/templates/payments/sofort/new_transaction.xml
@@ -1,4 +1,4 @@
-{% load l10n i18n %}{% load url from future %}{% localize off %}<?xml version="1.0" encoding="UTF-8"?>
+{% load l10n i18n %}{% localize off %}<?xml version="1.0" encoding="UTF-8"?>
<multipay>
<project_id>{{ project_id }}</project_id>
<language_code>{{ language_code }}</language_code>
diff --git a/payments/templates/payments/sofort/refund_transaction.xml b/payments/templates/payments/sofort/refund_transaction.xml
index e621d6e..fa75a7c 100644
--- a/payments/templates/payments/sofort/refund_transaction.xml
+++ b/payments/templates/payments/sofort/refund_transaction.xml
@@ -1,4 +1,4 @@
-{% load l10n i18n %}{% load url from future %}{% localize off %}<?xml version="1.0" encoding="UTF-8" ?>
+{% load l10n i18n %}{% localize off %}<?xml version="1.0" encoding="UTF-8" ?>
<refunds version="3">
<sender>
<holder>{{holder}}</holder>
diff --git a/payments/test_core.py b/payments/test_core.py
index 47f34dd..88c91dd 100644
--- a/payments/test_core.py
+++ b/payments/test_core.py
@@ -3,7 +3,7 @@ from decimal import Decimal
from unittest import TestCase
from mock import patch
-from . import provider_factory
+from .core import provider_factory
from .forms import CreditCardPaymentFormWithName, PaymentForm
from .models import BasePayment
diff --git a/payments/urls.py b/payments/urls.py
index 69e7200..a002222 100644
--- a/payments/urls.py
+++ b/payments/urls.py
@@ -14,7 +14,7 @@ except ImportError:
def atomic(func):
return func
-from . import get_payment_model, provider_factory
+from .core import get_payment_model, provider_factory
@csrf_exempt
diff --git a/payments/wallet/__init__.py b/payments/wallet/__init__.py
index 35cd181..8b4ddaf 100644
--- a/payments/wallet/__init__.py
+++ b/payments/wallet/__init__.py
@@ -6,7 +6,7 @@ from django.http import HttpResponseForbidden, HttpResponse
import jwt
from .forms import PaymentForm, ProcessPaymentForm
-from .. import BasicProvider
+from ..core import BasicProvider
class GoogleWalletProvider(BasicProvider):
diff --git a/test_settings.py b/test_settings.py
index 78f8258..b0e38e2 100644
--- a/test_settings.py
+++ b/test_settings.py
@@ -1,6 +1,13 @@
from __future__ import unicode_literals
+import os
+
+PROJECT_ROOT = os.path.normpath(
+ os.path.join(os.path.dirname(__file__), 'payments'))
+TEMPLATES = [{
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [os.path.join(PROJECT_ROOT, 'templates')]}]
SECRET_KEY = 'NOTREALLY'
PAYMENT_HOST = 'example.com'
-INSTALLED_APPS = ['payments']
+INSTALLED_APPS = ['payments', 'django.contrib.sites']
diff --git a/tox.ini b/tox.ini
index d14a9a4..0ec5c3a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,13 @@
[tox]
-envlist = py27,py33,py34
+envlist = py{27,34,35}-django{18,19,_master},py{27,34}-django14
[testenv]
usedevelop=True
deps=
+ django14: django>=1.4,<1.5a0
+ django18: django>=1.8,<1.9a0
+ django19: django>=1.9a1,<1.10a0
+ django_master: https://github.com/django/django/archive/master.tar.gz
mock
pytest
pytest-django