Updated supported versions of Python and Django

Dropped Python2.7/3.5 and Django 1.11 from test matrix

Removed Py2 code and updated for Py3 features

Replaced assertRaisesRegexp with AsserRaisesRegex

Updated setup.py for currently supported versions

Removed _timestamp
This commit is contained in:
David Smith 2020-11-25 22:07:00 +00:00
parent 3eb17007ad
commit 74ddb4f0e0
41 changed files with 32 additions and 116 deletions

View file

@ -8,7 +8,7 @@ jobs:
strategy:
max-parallel: 5
matrix:
python-version: ['2.7', '3.5', '3.6', '3.7', '3.8']
python-version: [3.6, 3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v2

View file

@ -2,8 +2,6 @@
Analytical template tags and filters.
"""
from __future__ import absolute_import
import logging
from django import template
@ -72,8 +70,7 @@ class AnalyticalNode(Node):
def _load_template_nodes():
template_nodes = dict((loc, dict((pos, []) for pos in TAG_POSITIONS))
for loc in TAG_LOCATIONS)
template_nodes = {loc: {pos: [] for pos in TAG_POSITIONS} for loc in TAG_LOCATIONS}
def add_node_cls(location, node, position=None):
template_nodes[location][position].append(node)

View file

@ -2,8 +2,6 @@
Chartbeat template tags and filters.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Clickmap template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
Clicky template tags and filters.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Crazy Egg template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -1,7 +1,6 @@
"""
Facebook Pixel template tags and filters.
"""
from __future__ import absolute_import
import re

View file

@ -2,8 +2,6 @@
Gaug.es template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -4,8 +4,6 @@ Google Analytics template tags and filters.
DEPRECATED
"""
from __future__ import absolute_import
import decimal
import re

View file

@ -2,8 +2,6 @@
Google Analytics template tags and filters, using the new analytics.js library.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
Google Analytics template tags and filters, using the new analytics.js library.
"""
from __future__ import absolute_import
import decimal
import re
from django.conf import settings
@ -134,7 +132,7 @@ class GoogleAnalyticsJsNode(Node):
try:
float(value)
except ValueError:
value = "'{}'".format(value)
value = f"'{value}'"
commands.append(CUSTOM_VAR_CODE.format(
name=name,
value=value,

View file

@ -2,8 +2,6 @@
GoSquared template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -1,7 +1,6 @@
"""
Hotjar template tags and filters.
"""
from __future__ import absolute_import
import re

View file

@ -2,8 +2,6 @@
HubSpot template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,14 +2,10 @@
intercom.io template tags and filters.
"""
from __future__ import absolute_import
import hashlib
import hmac
import json
import sys
import re
import time
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
@ -29,14 +25,6 @@ TRACKING_CODE = """
register = Library()
def _timestamp(when):
"""
Python 2 compatibility for `datetime.timestamp()`.
"""
return (time.mktime(when.timetuple()) if sys.version_info < (3,) else
when.timestamp())
def _hashable_bytes(data):
"""
Coerce strings to hashable bytes.
@ -109,7 +97,7 @@ class IntercomNode(Node):
params.setdefault('user_id', user.pk)
params['created_at'] = int(_timestamp(user.date_joined))
params['created_at'] = int(user.date_joined.timestamp())
else:
params['created_at'] = None

View file

@ -2,8 +2,6 @@
KISSinsights template tags.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
KISSmetrics template tags.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Matomo template tags and filters.
"""
from __future__ import absolute_import
from collections import namedtuple
from itertools import chain
import re

View file

@ -2,8 +2,6 @@
Mixpanel template tags and filters.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Olark template tags.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Optimizely template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
Performable template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
Piwik template tags and filters.
"""
from __future__ import absolute_import
from collections import namedtuple
from itertools import chain
import re

View file

@ -2,8 +2,6 @@
Rating@Mail.ru template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
SnapEngage template tags.
"""
from __future__ import absolute_import
import re
from django.conf import settings

View file

@ -2,8 +2,6 @@
Spring Metrics template tags and filters.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError

View file

@ -2,8 +2,6 @@
UserVoice template tags.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Woopra template tags and filters.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Yandex.Metrica template tags and filters.
"""
from __future__ import absolute_import
import json
import re

View file

@ -2,8 +2,6 @@
Dummy testing template tags and filters.
"""
from __future__ import absolute_import
from django.template import Library, Node, TemplateSyntaxError
from analytical.templatetags.analytical import TAG_LOCATIONS
@ -19,7 +17,7 @@ def _location_node(location):
return DummyNode
_location_nodes = dict((loc, _location_node(loc)) for loc in TAG_LOCATIONS)
_location_nodes = {loc: _location_node(loc) for loc in TAG_LOCATIONS}
def _location_tag(location):

View file

@ -14,7 +14,7 @@ class AnalyticsTagTestCase(TagTestCase):
"""
def setUp(self):
super(AnalyticsTagTestCase, self).setUp()
super().setUp()
self._tag_modules = analytical.TAG_MODULES
analytical.TAG_MODULES = ['analytical.tests.dummy']
analytical.template_nodes = analytical._load_template_nodes()
@ -22,7 +22,7 @@ class AnalyticsTagTestCase(TagTestCase):
def tearDown(self):
analytical.TAG_MODULES = self._tag_modules
analytical.template_nodes = analytical._load_template_nodes()
super(AnalyticsTagTestCase, self).tearDown()
super().tearDown()
def render_location_tag(self, location, vars=None):
if vars is None:

View file

@ -56,13 +56,13 @@ class FacebookPixelTagTestCase(TagTestCase):
self.assertEqual(expected_body_html, html)
def test_tags_take_no_args(self):
self.assertRaisesRegexp(
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'facebook_pixel_head' takes no arguments$",
lambda: (Template('{% load facebook_pixel %}{% facebook_pixel_head "arg" %}')
.render(Context({}))),
)
self.assertRaisesRegexp(
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'facebook_pixel_body' takes no arguments$",
lambda: (Template('{% load facebook_pixel %}{% facebook_pixel_body "arg" %}')
@ -72,15 +72,15 @@ class FacebookPixelTagTestCase(TagTestCase):
@override_settings(FACEBOOK_PIXEL_ID=None)
def test_no_id(self):
expected_pattern = r'^FACEBOOK_PIXEL_ID setting is not set$'
self.assertRaisesRegexp(AnalyticalException, expected_pattern, FacebookPixelHeadNode)
self.assertRaisesRegexp(AnalyticalException, expected_pattern, FacebookPixelBodyNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelHeadNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelBodyNode)
@override_settings(FACEBOOK_PIXEL_ID='invalid')
def test_invalid_id(self):
expected_pattern = (
r"^FACEBOOK_PIXEL_ID setting: must be \(a string containing\) a number: 'invalid'$")
self.assertRaisesRegexp(AnalyticalException, expected_pattern, FacebookPixelHeadNode)
self.assertRaisesRegexp(AnalyticalException, expected_pattern, FacebookPixelBodyNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelHeadNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelBodyNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self):

View file

@ -39,7 +39,7 @@ class HotjarTagTestCase(TagTestCase):
self.assertEqual(expected_html, html)
def test_tags_take_no_args(self):
self.assertRaisesRegexp(
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'hotjar' takes no arguments$",
lambda: (Template('{% load hotjar %}{% hotjar "arg" %}')
@ -49,13 +49,13 @@ class HotjarTagTestCase(TagTestCase):
@override_settings(HOTJAR_SITE_ID=None)
def test_no_id(self):
expected_pattern = r'^HOTJAR_SITE_ID setting is not set$'
self.assertRaisesRegexp(AnalyticalException, expected_pattern, HotjarNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, HotjarNode)
@override_settings(HOTJAR_SITE_ID='invalid')
def test_invalid_id(self):
expected_pattern = (
r"^HOTJAR_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$")
self.assertRaisesRegexp(AnalyticalException, expected_pattern, HotjarNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, HotjarNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self):

View file

@ -9,7 +9,7 @@ from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from analytical.templatetags.intercom import IntercomNode, intercom_user_hash, _timestamp
from analytical.templatetags.intercom import IntercomNode, intercom_user_hash
from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@ -123,7 +123,7 @@ class IntercomTagTestCase(TagTestCase):
) # type: User
attrs = IntercomNode()._get_custom_attrs(Context({'user': user}))
self.assertEqual({
'created_at': int(_timestamp(user.date_joined)),
'created_at': int(user.date_joined.timestamp()),
'email': 'test@example.com',
'name': '',
'user_hash': intercom_user_hash(str(user.pk)),

View file

@ -87,7 +87,7 @@ class OlarkTestCase(TagTestCase):
"introduction_messages",
"introduction_submit_button_text",
]
vars = dict(('olark_%s' % m, m) for m in messages)
vars = {'olark_%s' % m: m for m in messages}
r = OlarkNode().render(Context(vars))
for m in messages:
self.assertTrue("olark.configure('locale.%s', \"%s\");" % (m, m) in r, r)

View file

@ -27,17 +27,8 @@ class SettingDeletedTestCase(TestCase):
Make sure using get_required_setting fails in the right place.
"""
# available in python >= 3.2
if hasattr(self, 'assertRaisesRegex'):
with self.assertRaisesRegex(AnalyticalException, "^USER_ID setting is not set$"):
get_required_setting("USER_ID", r"\d+", "invalid USER_ID")
# available in python >= 2.7, deprecated in 3.2
elif hasattr(self, 'assertRaisesRegexp'):
with self.assertRaisesRegexp(AnalyticalException, "^USER_ID setting is not set$"):
get_required_setting("USER_ID", r"\d+", "invalid USER_ID")
else:
self.assertRaises(AnalyticalException,
get_required_setting, "USER_ID", r"\d+", "invalid USER_ID")
with self.assertRaisesRegex(AnalyticalException, "^USER_ID setting is not set$"):
get_required_setting("USER_ID", r"\d+", "invalid USER_ID")
class MyUser(AbstractBaseUser):

View file

@ -2,8 +2,6 @@
Testing utilities.
"""
from __future__ import with_statement
from django.template import Template, Context, RequestContext
from django.test.testcases import TestCase

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# This file is execfile()d with the current directory set to its containing
# directory.
@ -14,8 +13,8 @@ import analytical # noqa
# -- General configuration --------------------------------------------------
project = u'django-analytical'
copyright = u'2011-2016, Joost Cassee <joost@cassee.net>'
project = 'django-analytical'
copyright = '2011-2020, Joost Cassee <joost@cassee.net>'
release = analytical.__version__
# The short X.Y version.
@ -45,6 +44,6 @@ htmlhelp_basename = 'analyticaldoc'
# -- Options for LaTeX output -----------------------------------------------
latex_documents = [
('index', 'django-analytical.tex', u'Documentation for django-analytical',
u'Joost Cassee', 'manual'),
('index', 'django-analytical.tex', 'Documentation for django-analytical',
'Joost Cassee', 'manual'),
]

View file

@ -1 +1 @@
Django>=1.7.0
Django>=2.2.*

View file

@ -27,23 +27,20 @@ setup(
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Software Development :: Libraries :: Python Modules',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
],
platforms=['any'],
url='https://github.com/jazzband/django-analytical',

10
tox.ini
View file

@ -1,9 +1,7 @@
[tox]
envlist =
# Python/Django combinations that are officially supported
py{27,35,36,37}-django111
py{35,36,37,38}-django22
py{36,37,38}-django30
py{36,37,38,39}-django{22,30,31}
py37-{flake8,bandit,readme,docs}
[testenv]
@ -11,20 +9,20 @@ description = Unit tests
deps =
coverage
pytest-django
django111: Django>=1.11,<2.0
django22: Django>=2.2,<3.0
django30: Django>=3.0,<3.1
django31: Django>=3.1,<3.2
commands =
coverage run -m pytest
coverage xml
[gh-actions]
python =
2.7: py27
3.5: py35
3.6: py36
3.7: py37
3.8: py38
3.9: py39
[testenv:py37-bandit]
description = PyCQA security linter