diff --git a/.travis.yml b/.travis.yml index 3084b3440..a5f478fbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,34 +1,33 @@ -language: python sudo: false -install: - - pip install tox codecov -script: - - tox +language: python +python: + - "2.7" + - "3.4" + - "3.5" + - "3.6" env: - - TOXENV=py27-django18 - - TOXENV=py27-django110 - - TOXENV=py27-django111 - - TOXENV=py34-django18 - - TOXENV=py34-django110 - - TOXENV=py34-django111 - - TOXENV=py34-django_master - - TOXENV=py35-django18 - - TOXENV=py35-django110 - - TOXENV=py35-django111 - - TOXENV=py35-django_master + - DJANGO="1.11" + - DJANGO="2.0" + - DJANGO="master" matrix: allow_failures: - - env: TOXENV=py27-django111 - - env: TOXENV=py34-django111 - - env: TOXENV=py35-django111 - - env: TOXENV=py34-django_master - - env: TOXENV=py35-django_master -after_success: - - codecov -addons: - apt: - sources: - - deadsnakes - packages: - - python3.5 - - python3.5-dev + - python: "3.4" + env: DJANGO="2.0" + - python: "3.4" + env: DJANGO="master" + - python: "3.5" + env: DJANGO="2.0" + - python: "3.5" + env: DJANGO="master" + - python: "3.6" + env: DJANGO="2.0" + - python: "3.6" + env: DJANGO="master" + exclude: + - python: "2.7" + env: DJANGO="2.0" + - python: "2.7" + env: DJANGO="master" +after_success: codecov +install: pip install tox-travis codecov +script: tox diff --git a/payments/cybersource/forms.py b/payments/cybersource/forms.py index 0293b5a7b..5fedde0e4 100644 --- a/payments/cybersource/forms.py +++ b/payments/cybersource/forms.py @@ -13,7 +13,8 @@ class FingerprintWidget(forms.HiddenInput): def render(self, name, value, attrs=None): - final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) + final_attrs = dict(attrs or {}, type=self.input_type, name=name) + final_attrs.update(self.attrs) final_attrs['session_id'] = value return render_to_string( 'payments/cybersource_fingerprint.html', final_attrs) diff --git a/payments/stripe/widgets.py b/payments/stripe/widgets.py index f313b4fba..fe2566dbf 100644 --- a/payments/stripe/widgets.py +++ b/payments/stripe/widgets.py @@ -31,8 +31,8 @@ def __init__(self, provider, payment, *args, **kwargs): def render(self, name, value, attrs=None): if value is None: value = '' - final_attrs = self.build_attrs( - attrs, src="https://checkout.stripe.com/checkout.js") + final_attrs = dict(attrs or {}, src='https://checkout.stripe.com/checkout.js') + final_attrs.update(self.attrs) del final_attrs['id'] if value != '': # Only add the 'value' attribute if a value is non-empty. @@ -46,6 +46,6 @@ class Media: js = ['https://js.stripe.com/v2/', 'js/payments/stripe.js'] - def build_attrs(self, extra_attrs=None, **kwargs): - extra_attrs = dict(extra_attrs or {}, id='id_stripe_token') - return super(StripeWidget, self).build_attrs(extra_attrs, **kwargs) + def __init__(self, attrs=None): + attrs = dict(attrs or {}, id='id_stripe_token') + super(StripeWidget, self).__init__(attrs) diff --git a/payments/templates/payments/credit_card_expiry_widget.html b/payments/templates/payments/credit_card_expiry_widget.html index 68fd7eda7..ab09159b7 100644 --- a/payments/templates/payments/credit_card_expiry_widget.html +++ b/payments/templates/payments/credit_card_expiry_widget.html @@ -1,3 +1,7 @@ - {{ month }} / {{ year }} + {% with widget.subwidgets.0 as month %} + {% with widget.subwidgets.1 as year %} + {% include month.template_name with widget=month %} / {% include year.template_name with widget=year %} + {% endwith %} + {% endwith %} \ No newline at end of file diff --git a/payments/templates/payments/sensitive_select.html b/payments/templates/payments/sensitive_select.html new file mode 100644 index 000000000..a22fd82e2 --- /dev/null +++ b/payments/templates/payments/sensitive_select.html @@ -0,0 +1,5 @@ + diff --git a/payments/templates/payments/sensitive_text_input.html b/payments/templates/payments/sensitive_text_input.html new file mode 100644 index 000000000..3133edbcc --- /dev/null +++ b/payments/templates/payments/sensitive_text_input.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/payments/widgets.py b/payments/widgets.py index a843cbe75..795906fee 100644 --- a/payments/widgets.py +++ b/payments/widgets.py @@ -1,12 +1,6 @@ import re -from django import VERSION as DJANGO_VERSION -from django.forms.utils import flatatt from django.forms.widgets import TextInput, MultiWidget, Select -from django.template.loader import render_to_string -from django.utils.encoding import force_text -from django.utils.html import format_html -from django.utils.safestring import mark_safe class CreditCardNumberWidget(TextInput): @@ -28,43 +22,19 @@ def render(self, name, value, attrs=None): # http://www.djangosnippets.org/snippets/907/ class CreditCardExpiryWidget(MultiWidget): """MultiWidget for representing credit card expiry date.""" + + template_name = 'payments/credit_card_expiry_widget.html' + def decompress(self, value): if value: return [value.month, value.year] else: return [None, None] - def format_output(self, rendered_widgets): - ctx = {'month': rendered_widgets[0], 'year': rendered_widgets[1]} - return render_to_string('payments/credit_card_expiry_widget.html', ctx) - class SensitiveTextInput(TextInput): - - def render(self, name, value, attrs=None): - # Explicitly skip parent implementation and exclude - # 'name' from attrs - if value is None: - value = '' - final_attrs = self.build_attrs(attrs, type=self.input_type) - if value != '': - # Only add the 'value' attribute if a value is non-empty. - final_attrs['value'] = force_text(self.format_value(value)) - return format_html('', flatatt(final_attrs)) + template_name = 'payments/sensitive_text_input.html' class SensitiveSelect(Select): - - def render(self, name, value, attrs=None): - if value is None: - value = '' - final_attrs = self.build_attrs(attrs) - output = [format_html('', flatatt(final_attrs))] - if DJANGO_VERSION <= (1, 10, 0): - options = self.render_options([], [value]) - else: - options = self.render_options([value]) - if options: - output.append(options) - output.append('') - return mark_safe('\n'.join(output)) + template_name = 'payments/sensitive_select.html' diff --git a/setup.py b/setup.py index 422758ee9..3874b1889 100755 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ REQUIREMENTS = [ 'braintree>=3.14.0', - 'Django>=1.5', + 'Django>=1.11', 'cryptography>=1.1.0', 'PyJWT>=1.3.0', 'requests>=1.2.0', @@ -69,6 +69,7 @@ def run_tests(self): 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Framework :: Django', 'Topic :: Software Development :: Libraries :: Application Frameworks', 'Topic :: Software Development :: Libraries :: Python Modules'], diff --git a/tox.ini b/tox.ini index 22a5672f8..63f22717b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,12 @@ [tox] -envlist = py{27,34,35}-django{18,110,111} py{34,35}-django_master +envlist = py27-django111, py{34,35,36}-django{111,20,_master} [testenv] usedevelop=True deps= coverage - django18: django>=1.8,<1.9a0 - django110: django>=1.10,<1.11a0 django111: django>=1.11a1,<1.12 + django20: Django>=2.0a1,<2.1 django_master: https://github.com/django/django/archive/master.tar.gz mock pytest @@ -17,3 +16,17 @@ commands=coverage run setup.py test [pytest] testpaths = payments DJANGO_SETTINGS_MODULE = test_settings + +[travis] +python = + 2.7: py27 + 3.4: py34 + 3.5: py35 + 3.6: py36 +unignore_outcomes = True + +[travis:env] +DJANGO = + 1.11: django111 + 2.0: django2.0 + master: django_master