mirror of
https://github.com/django/django.git
synced 2025-08-04 02:48:35 +00:00
Renamed some tests and removed references to modeltests/regressiontests.
This commit is contained in:
parent
737a5d71f0
commit
33836cf88d
224 changed files with 384 additions and 376 deletions
0
tests/utils_tests/__init__.py
Normal file
0
tests/utils_tests/__init__.py
Normal file
72
tests/utils_tests/archive.py
Normal file
72
tests/utils_tests/archive.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from django.utils import unittest
|
||||
|
||||
from django.utils.archive import Archive, extract
|
||||
from django.utils._os import upath
|
||||
|
||||
|
||||
TEST_DIR = os.path.join(os.path.dirname(upath(__file__)), 'archives')
|
||||
|
||||
|
||||
class ArchiveTester(object):
|
||||
archive = None
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Create temporary directory for testing extraction.
|
||||
"""
|
||||
self.old_cwd = os.getcwd()
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
self.addCleanup(shutil.rmtree, self.tmpdir)
|
||||
self.archive_path = os.path.join(TEST_DIR, self.archive)
|
||||
# Always start off in TEST_DIR.
|
||||
os.chdir(TEST_DIR)
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.old_cwd)
|
||||
|
||||
def test_extract_method(self):
|
||||
with Archive(self.archive) as archive:
|
||||
archive.extract(self.tmpdir)
|
||||
self.check_files(self.tmpdir)
|
||||
|
||||
def test_extract_method_no_to_path(self):
|
||||
os.chdir(self.tmpdir)
|
||||
with Archive(self.archive_path) as archive:
|
||||
archive.extract()
|
||||
self.check_files(self.tmpdir)
|
||||
|
||||
def test_extract_function(self):
|
||||
extract(self.archive_path, self.tmpdir)
|
||||
self.check_files(self.tmpdir)
|
||||
|
||||
def test_extract_function_no_to_path(self):
|
||||
os.chdir(self.tmpdir)
|
||||
extract(self.archive_path)
|
||||
self.check_files(self.tmpdir)
|
||||
|
||||
def check_files(self, tmpdir):
|
||||
self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, '1')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, '2')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'foo', '1')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'foo', '2')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'foo', 'bar', '1')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'foo', 'bar', '2')))
|
||||
|
||||
|
||||
class TestZip(ArchiveTester, unittest.TestCase):
|
||||
archive = 'foobar.zip'
|
||||
|
||||
|
||||
class TestTar(ArchiveTester, unittest.TestCase):
|
||||
archive = 'foobar.tar'
|
||||
|
||||
|
||||
class TestGzipTar(ArchiveTester, unittest.TestCase):
|
||||
archive = 'foobar.tar.gz'
|
||||
|
||||
|
||||
class TestBzip2Tar(ArchiveTester, unittest.TestCase):
|
||||
archive = 'foobar.tar.bz2'
|
BIN
tests/utils_tests/archives/foobar.tar
Normal file
BIN
tests/utils_tests/archives/foobar.tar
Normal file
Binary file not shown.
BIN
tests/utils_tests/archives/foobar.tar.bz2
Normal file
BIN
tests/utils_tests/archives/foobar.tar.bz2
Normal file
Binary file not shown.
BIN
tests/utils_tests/archives/foobar.tar.gz
Normal file
BIN
tests/utils_tests/archives/foobar.tar.gz
Normal file
Binary file not shown.
BIN
tests/utils_tests/archives/foobar.zip
Normal file
BIN
tests/utils_tests/archives/foobar.zip
Normal file
Binary file not shown.
42
tests/utils_tests/baseconv.py
Normal file
42
tests/utils_tests/baseconv.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
from unittest import TestCase
|
||||
from django.utils.baseconv import base2, base16, base36, base56, base62, base64, BaseConverter
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
class TestBaseConv(TestCase):
|
||||
|
||||
def test_baseconv(self):
|
||||
nums = [-10 ** 10, 10 ** 10] + list(xrange(-100, 100))
|
||||
for converter in [base2, base16, base36, base56, base62, base64]:
|
||||
for i in nums:
|
||||
self.assertEqual(i, converter.decode(converter.encode(i)))
|
||||
|
||||
def test_base11(self):
|
||||
base11 = BaseConverter('0123456789-', sign='$')
|
||||
self.assertEqual(base11.encode(1234), '-22')
|
||||
self.assertEqual(base11.decode('-22'), 1234)
|
||||
self.assertEqual(base11.encode(-1234), '$-22')
|
||||
self.assertEqual(base11.decode('$-22'), -1234)
|
||||
|
||||
def test_base20(self):
|
||||
base20 = BaseConverter('0123456789abcdefghij')
|
||||
self.assertEqual(base20.encode(1234), '31e')
|
||||
self.assertEqual(base20.decode('31e'), 1234)
|
||||
self.assertEqual(base20.encode(-1234), '-31e')
|
||||
self.assertEqual(base20.decode('-31e'), -1234)
|
||||
|
||||
def test_base64(self):
|
||||
self.assertEqual(base64.encode(1234), 'JI')
|
||||
self.assertEqual(base64.decode('JI'), 1234)
|
||||
self.assertEqual(base64.encode(-1234), '$JI')
|
||||
self.assertEqual(base64.decode('$JI'), -1234)
|
||||
|
||||
def test_base7(self):
|
||||
base7 = BaseConverter('cjdhel3', sign='g')
|
||||
self.assertEqual(base7.encode(1234), 'hejd')
|
||||
self.assertEqual(base7.decode('hejd'), 1234)
|
||||
self.assertEqual(base7.encode(-1234), 'ghejd')
|
||||
self.assertEqual(base7.decode('ghejd'), -1234)
|
||||
|
||||
def test_exception(self):
|
||||
self.assertRaises(ValueError, BaseConverter, 'abc', sign='a')
|
||||
self.assertTrue(isinstance(BaseConverter('abc', sign='d'), BaseConverter))
|
29
tests/utils_tests/checksums.py
Normal file
29
tests/utils_tests/checksums.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
import unittest
|
||||
|
||||
from django.utils import checksums
|
||||
|
||||
class TestUtilsChecksums(unittest.TestCase):
|
||||
|
||||
def check_output(self, function, value, output=None):
|
||||
"""
|
||||
Check that function(value) equals output. If output is None,
|
||||
check that function(value) equals value.
|
||||
"""
|
||||
if output is None:
|
||||
output = value
|
||||
self.assertEqual(function(value), output)
|
||||
|
||||
def test_luhn(self):
|
||||
f = checksums.luhn
|
||||
items = (
|
||||
(4111111111111111, True), ('4111111111111111', True),
|
||||
(4222222222222, True), (378734493671000, True),
|
||||
(5424000000000015, True), (5555555555554444, True),
|
||||
(1008, True), ('0000001008', True), ('000000001008', True),
|
||||
(4012888888881881, True), (1234567890123456789012345678909, True),
|
||||
(4111111111211111, False), (42222222222224, False),
|
||||
(100, False), ('100', False), ('0000100', False),
|
||||
('abc', False), (None, False), (object(), False),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
146
tests/utils_tests/crypto.py
Normal file
146
tests/utils_tests/crypto.py
Normal file
|
@ -0,0 +1,146 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import binascii
|
||||
import math
|
||||
import timeit
|
||||
import hashlib
|
||||
|
||||
from django.utils import unittest
|
||||
from django.utils.crypto import constant_time_compare, pbkdf2
|
||||
|
||||
|
||||
class TestUtilsCryptoMisc(unittest.TestCase):
|
||||
|
||||
def test_constant_time_compare(self):
|
||||
# It's hard to test for constant time, just test the result.
|
||||
self.assertTrue(constant_time_compare(b'spam', b'spam'))
|
||||
self.assertFalse(constant_time_compare(b'spam', b'eggs'))
|
||||
self.assertTrue(constant_time_compare('spam', 'spam'))
|
||||
self.assertFalse(constant_time_compare('spam', 'eggs'))
|
||||
|
||||
|
||||
class TestUtilsCryptoPBKDF2(unittest.TestCase):
|
||||
|
||||
# http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-06
|
||||
rfc_vectors = [
|
||||
{
|
||||
"args": {
|
||||
"password": "password",
|
||||
"salt": "salt",
|
||||
"iterations": 1,
|
||||
"dklen": 20,
|
||||
"digest": hashlib.sha1,
|
||||
},
|
||||
"result": "0c60c80f961f0e71f3a9b524af6012062fe037a6",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"password": "password",
|
||||
"salt": "salt",
|
||||
"iterations": 2,
|
||||
"dklen": 20,
|
||||
"digest": hashlib.sha1,
|
||||
},
|
||||
"result": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"password": "password",
|
||||
"salt": "salt",
|
||||
"iterations": 4096,
|
||||
"dklen": 20,
|
||||
"digest": hashlib.sha1,
|
||||
},
|
||||
"result": "4b007901b765489abead49d926f721d065a429c1",
|
||||
},
|
||||
# # this takes way too long :(
|
||||
# {
|
||||
# "args": {
|
||||
# "password": "password",
|
||||
# "salt": "salt",
|
||||
# "iterations": 16777216,
|
||||
# "dklen": 20,
|
||||
# "digest": hashlib.sha1,
|
||||
# },
|
||||
# "result": "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984",
|
||||
# },
|
||||
{
|
||||
"args": {
|
||||
"password": "passwordPASSWORDpassword",
|
||||
"salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt",
|
||||
"iterations": 4096,
|
||||
"dklen": 25,
|
||||
"digest": hashlib.sha1,
|
||||
},
|
||||
"result": "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"password": "pass\0word",
|
||||
"salt": "sa\0lt",
|
||||
"iterations": 4096,
|
||||
"dklen": 16,
|
||||
"digest": hashlib.sha1,
|
||||
},
|
||||
"result": "56fa6aa75548099dcc37d7f03425e0c3",
|
||||
},
|
||||
]
|
||||
|
||||
regression_vectors = [
|
||||
{
|
||||
"args": {
|
||||
"password": "password",
|
||||
"salt": "salt",
|
||||
"iterations": 1,
|
||||
"dklen": 20,
|
||||
"digest": hashlib.sha256,
|
||||
},
|
||||
"result": "120fb6cffcf8b32c43e7225256c4f837a86548c9",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"password": "password",
|
||||
"salt": "salt",
|
||||
"iterations": 1,
|
||||
"dklen": 20,
|
||||
"digest": hashlib.sha512,
|
||||
},
|
||||
"result": "867f70cf1ade02cff3752599a3a53dc4af34c7a6",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"password": "password",
|
||||
"salt": "salt",
|
||||
"iterations": 1000,
|
||||
"dklen": 0,
|
||||
"digest": hashlib.sha512,
|
||||
},
|
||||
"result": ("afe6c5530785b6cc6b1c6453384731bd5ee432ee"
|
||||
"549fd42fb6695779ad8a1c5bf59de69c48f774ef"
|
||||
"c4007d5298f9033c0241d5ab69305e7b64eceeb8d"
|
||||
"834cfec"),
|
||||
},
|
||||
# Check leading zeros are not stripped (#17481)
|
||||
{
|
||||
"args": {
|
||||
"password": b'\xba',
|
||||
"salt": "salt",
|
||||
"iterations": 1,
|
||||
"dklen": 20,
|
||||
"digest": hashlib.sha1,
|
||||
},
|
||||
"result": '0053d3b91a7f1e54effebd6d68771e8a6e0b2c5b',
|
||||
},
|
||||
]
|
||||
|
||||
def test_public_vectors(self):
|
||||
for vector in self.rfc_vectors:
|
||||
result = pbkdf2(**vector['args'])
|
||||
self.assertEqual(binascii.hexlify(result).decode('ascii'),
|
||||
vector['result'])
|
||||
|
||||
def test_regression_vectors(self):
|
||||
for vector in self.regression_vectors:
|
||||
result = pbkdf2(**vector['args'])
|
||||
self.assertEqual(binascii.hexlify(result).decode('ascii'),
|
||||
vector['result'])
|
306
tests/utils_tests/datastructures.py
Normal file
306
tests/utils_tests/datastructures.py
Normal file
|
@ -0,0 +1,306 @@
|
|||
"""
|
||||
Tests for stuff in django.utils.datastructures.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import pickle
|
||||
import warnings
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.datastructures import (DictWrapper, ImmutableList,
|
||||
MultiValueDict, MultiValueDictKeyError, MergeDict, SortedDict)
|
||||
from django.utils import six
|
||||
|
||||
|
||||
class SortedDictTests(SimpleTestCase):
|
||||
def setUp(self):
|
||||
self.d1 = SortedDict()
|
||||
self.d1[7] = 'seven'
|
||||
self.d1[1] = 'one'
|
||||
self.d1[9] = 'nine'
|
||||
|
||||
self.d2 = SortedDict()
|
||||
self.d2[1] = 'one'
|
||||
self.d2[9] = 'nine'
|
||||
self.d2[0] = 'nil'
|
||||
self.d2[7] = 'seven'
|
||||
|
||||
def test_basic_methods(self):
|
||||
self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9])
|
||||
self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'one', 'nine'])
|
||||
self.assertEqual(list(six.iteritems(self.d1)), [(7, 'seven'), (1, 'one'), (9, 'nine')])
|
||||
|
||||
def test_overwrite_ordering(self):
|
||||
""" Overwriting an item keeps its place. """
|
||||
self.d1[1] = 'ONE'
|
||||
self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'ONE', 'nine'])
|
||||
|
||||
def test_append_items(self):
|
||||
""" New items go to the end. """
|
||||
self.d1[0] = 'nil'
|
||||
self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9, 0])
|
||||
|
||||
def test_delete_and_insert(self):
|
||||
"""
|
||||
Deleting an item, then inserting the same key again will place it
|
||||
at the end.
|
||||
"""
|
||||
del self.d2[7]
|
||||
self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0])
|
||||
self.d2[7] = 'lucky number 7'
|
||||
self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0, 7])
|
||||
|
||||
if not six.PY3:
|
||||
def test_change_keys(self):
|
||||
"""
|
||||
Changing the keys won't do anything, it's only a copy of the
|
||||
keys dict.
|
||||
|
||||
This test doesn't make sense under Python 3 because keys is
|
||||
an iterator.
|
||||
"""
|
||||
k = self.d2.keys()
|
||||
k.remove(9)
|
||||
self.assertEqual(self.d2.keys(), [1, 9, 0, 7])
|
||||
|
||||
def test_init_keys(self):
|
||||
"""
|
||||
Initialising a SortedDict with two keys will just take the first one.
|
||||
|
||||
A real dict will actually take the second value so we will too, but
|
||||
we'll keep the ordering from the first key found.
|
||||
"""
|
||||
tuples = ((2, 'two'), (1, 'one'), (2, 'second-two'))
|
||||
d = SortedDict(tuples)
|
||||
|
||||
self.assertEqual(list(six.iterkeys(d)), [2, 1])
|
||||
|
||||
real_dict = dict(tuples)
|
||||
self.assertEqual(sorted(six.itervalues(real_dict)), ['one', 'second-two'])
|
||||
|
||||
# Here the order of SortedDict values *is* what we are testing
|
||||
self.assertEqual(list(six.itervalues(d)), ['second-two', 'one'])
|
||||
|
||||
def test_overwrite(self):
|
||||
self.d1[1] = 'not one'
|
||||
self.assertEqual(self.d1[1], 'not one')
|
||||
self.assertEqual(list(six.iterkeys(self.d1)), list(six.iterkeys(self.d1.copy())))
|
||||
|
||||
def test_append(self):
|
||||
self.d1[13] = 'thirteen'
|
||||
self.assertEqual(
|
||||
repr(self.d1),
|
||||
"{7: 'seven', 1: 'one', 9: 'nine', 13: 'thirteen'}"
|
||||
)
|
||||
|
||||
def test_pop(self):
|
||||
self.assertEqual(self.d1.pop(1, 'missing'), 'one')
|
||||
self.assertEqual(self.d1.pop(1, 'missing'), 'missing')
|
||||
|
||||
# We don't know which item will be popped in popitem(), so we'll
|
||||
# just check that the number of keys has decreased.
|
||||
l = len(self.d1)
|
||||
self.d1.popitem()
|
||||
self.assertEqual(l - len(self.d1), 1)
|
||||
|
||||
def test_dict_equality(self):
|
||||
d = SortedDict((i, i) for i in range(3))
|
||||
self.assertEqual(d, {0: 0, 1: 1, 2: 2})
|
||||
|
||||
def test_tuple_init(self):
|
||||
d = SortedDict(((1, "one"), (0, "zero"), (2, "two")))
|
||||
self.assertEqual(repr(d), "{1: 'one', 0: 'zero', 2: 'two'}")
|
||||
|
||||
def test_pickle(self):
|
||||
self.assertEqual(
|
||||
pickle.loads(pickle.dumps(self.d1, 2)),
|
||||
{7: 'seven', 1: 'one', 9: 'nine'}
|
||||
)
|
||||
|
||||
def test_copy(self):
|
||||
orig = SortedDict(((1, "one"), (0, "zero"), (2, "two")))
|
||||
copied = copy.copy(orig)
|
||||
self.assertEqual(list(six.iterkeys(orig)), [1, 0, 2])
|
||||
self.assertEqual(list(six.iterkeys(copied)), [1, 0, 2])
|
||||
|
||||
def test_clear(self):
|
||||
self.d1.clear()
|
||||
self.assertEqual(self.d1, {})
|
||||
self.assertEqual(self.d1.keyOrder, [])
|
||||
|
||||
def test_reversed(self):
|
||||
self.assertEqual(list(self.d1), [7, 1, 9])
|
||||
self.assertEqual(list(self.d2), [1, 9, 0, 7])
|
||||
self.assertEqual(list(reversed(self.d1)), [9, 1, 7])
|
||||
self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1])
|
||||
|
||||
def test_insert(self):
|
||||
d = SortedDict()
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
d.insert(0, "hello", "world")
|
||||
assert w[0].category is DeprecationWarning
|
||||
|
||||
def test_value_for_index(self):
|
||||
d = SortedDict({"a": 3})
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
self.assertEqual(d.value_for_index(0), 3)
|
||||
assert w[0].category is DeprecationWarning
|
||||
|
||||
|
||||
class MergeDictTests(SimpleTestCase):
|
||||
|
||||
def test_simple_mergedict(self):
|
||||
d1 = {'chris':'cool', 'camri':'cute', 'cotton':'adorable',
|
||||
'tulip':'snuggable', 'twoofme':'firstone'}
|
||||
|
||||
d2 = {'chris2':'cool2', 'camri2':'cute2', 'cotton2':'adorable2',
|
||||
'tulip2':'snuggable2'}
|
||||
|
||||
d3 = {'chris3':'cool3', 'camri3':'cute3', 'cotton3':'adorable3',
|
||||
'tulip3':'snuggable3'}
|
||||
|
||||
d4 = {'twoofme': 'secondone'}
|
||||
|
||||
md = MergeDict(d1, d2, d3)
|
||||
|
||||
self.assertEqual(md['chris'], 'cool')
|
||||
self.assertEqual(md['camri'], 'cute')
|
||||
self.assertEqual(md['twoofme'], 'firstone')
|
||||
|
||||
md2 = md.copy()
|
||||
self.assertEqual(md2['chris'], 'cool')
|
||||
|
||||
def test_mergedict_merges_multivaluedict(self):
|
||||
""" MergeDict can merge MultiValueDicts """
|
||||
|
||||
multi1 = MultiValueDict({'key1': ['value1'],
|
||||
'key2': ['value2', 'value3']})
|
||||
|
||||
multi2 = MultiValueDict({'key2': ['value4'],
|
||||
'key4': ['value5', 'value6']})
|
||||
|
||||
mm = MergeDict(multi1, multi2)
|
||||
|
||||
# Although 'key2' appears in both dictionaries,
|
||||
# only the first value is used.
|
||||
self.assertEqual(mm.getlist('key2'), ['value2', 'value3'])
|
||||
self.assertEqual(mm.getlist('key4'), ['value5', 'value6'])
|
||||
self.assertEqual(mm.getlist('undefined'), [])
|
||||
|
||||
self.assertEqual(sorted(six.iterkeys(mm)), ['key1', 'key2', 'key4'])
|
||||
self.assertEqual(len(list(six.itervalues(mm))), 3)
|
||||
|
||||
self.assertTrue('value1' in six.itervalues(mm))
|
||||
|
||||
self.assertEqual(sorted(six.iteritems(mm), key=lambda k: k[0]),
|
||||
[('key1', 'value1'), ('key2', 'value3'),
|
||||
('key4', 'value6')])
|
||||
|
||||
self.assertEqual([(k,mm.getlist(k)) for k in sorted(mm)],
|
||||
[('key1', ['value1']),
|
||||
('key2', ['value2', 'value3']),
|
||||
('key4', ['value5', 'value6'])])
|
||||
|
||||
class MultiValueDictTests(SimpleTestCase):
|
||||
|
||||
def test_multivaluedict(self):
|
||||
d = MultiValueDict({'name': ['Adrian', 'Simon'],
|
||||
'position': ['Developer']})
|
||||
|
||||
self.assertEqual(d['name'], 'Simon')
|
||||
self.assertEqual(d.get('name'), 'Simon')
|
||||
self.assertEqual(d.getlist('name'), ['Adrian', 'Simon'])
|
||||
self.assertEqual(sorted(list(six.iteritems(d))),
|
||||
[('name', 'Simon'), ('position', 'Developer')])
|
||||
|
||||
self.assertEqual(sorted(list(six.iterlists(d))),
|
||||
[('name', ['Adrian', 'Simon']),
|
||||
('position', ['Developer'])])
|
||||
|
||||
# MultiValueDictKeyError: "Key 'lastname' not found in
|
||||
# <MultiValueDict: {'position': ['Developer'],
|
||||
# 'name': ['Adrian', 'Simon']}>"
|
||||
six.assertRaisesRegex(self, MultiValueDictKeyError,
|
||||
r'"Key \'lastname\' not found in <MultiValueDict',
|
||||
d.__getitem__, 'lastname')
|
||||
|
||||
self.assertEqual(d.get('lastname'), None)
|
||||
self.assertEqual(d.get('lastname', 'nonexistent'), 'nonexistent')
|
||||
self.assertEqual(d.getlist('lastname'), [])
|
||||
self.assertEqual(d.getlist('doesnotexist', ['Adrian', 'Simon']),
|
||||
['Adrian', 'Simon'])
|
||||
|
||||
d.setlist('lastname', ['Holovaty', 'Willison'])
|
||||
self.assertEqual(d.getlist('lastname'), ['Holovaty', 'Willison'])
|
||||
self.assertEqual(sorted(list(six.itervalues(d))),
|
||||
['Developer', 'Simon', 'Willison'])
|
||||
|
||||
def test_appendlist(self):
|
||||
d = MultiValueDict()
|
||||
d.appendlist('name', 'Adrian')
|
||||
d.appendlist('name', 'Simon')
|
||||
self.assertEqual(d.getlist('name'), ['Adrian', 'Simon'])
|
||||
|
||||
def test_copy(self):
|
||||
for copy_func in [copy.copy, lambda d: d.copy()]:
|
||||
d1 = MultiValueDict({
|
||||
"developers": ["Carl", "Fred"]
|
||||
})
|
||||
self.assertEqual(d1["developers"], "Fred")
|
||||
d2 = copy_func(d1)
|
||||
d2.update({"developers": "Groucho"})
|
||||
self.assertEqual(d2["developers"], "Groucho")
|
||||
self.assertEqual(d1["developers"], "Fred")
|
||||
|
||||
d1 = MultiValueDict({
|
||||
"key": [[]]
|
||||
})
|
||||
self.assertEqual(d1["key"], [])
|
||||
d2 = copy_func(d1)
|
||||
d2["key"].append("Penguin")
|
||||
self.assertEqual(d1["key"], ["Penguin"])
|
||||
self.assertEqual(d2["key"], ["Penguin"])
|
||||
|
||||
def test_dict_translation(self):
|
||||
mvd = MultiValueDict({
|
||||
'devs': ['Bob', 'Joe'],
|
||||
'pm': ['Rory'],
|
||||
})
|
||||
d = mvd.dict()
|
||||
self.assertEqual(list(six.iterkeys(d)), list(six.iterkeys(mvd)))
|
||||
for key in six.iterkeys(mvd):
|
||||
self.assertEqual(d[key], mvd[key])
|
||||
|
||||
self.assertEqual({}, MultiValueDict().dict())
|
||||
|
||||
|
||||
class ImmutableListTests(SimpleTestCase):
|
||||
|
||||
def test_sort(self):
|
||||
d = ImmutableList(range(10))
|
||||
|
||||
# AttributeError: ImmutableList object is immutable.
|
||||
self.assertRaisesMessage(AttributeError,
|
||||
'ImmutableList object is immutable.', d.sort)
|
||||
|
||||
self.assertEqual(repr(d), '(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)')
|
||||
|
||||
def test_custom_warning(self):
|
||||
d = ImmutableList(range(10), warning="Object is immutable!")
|
||||
|
||||
self.assertEqual(d[1], 1)
|
||||
|
||||
# AttributeError: Object is immutable!
|
||||
self.assertRaisesMessage(AttributeError,
|
||||
'Object is immutable!', d.__setitem__, 1, 'test')
|
||||
|
||||
|
||||
class DictWrapperTests(SimpleTestCase):
|
||||
|
||||
def test_dictwrapper(self):
|
||||
f = lambda x: "*%s" % x
|
||||
d = DictWrapper({'a': 'a'}, f, 'xx_')
|
||||
self.assertEqual("Normal: %(a)s. Modified: %(xx_a)s" % d,
|
||||
'Normal: a. Modified: *a')
|
142
tests/utils_tests/dateformat.py
Normal file
142
tests/utils_tests/dateformat.py
Normal file
|
@ -0,0 +1,142 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import datetime, date
|
||||
import os
|
||||
import time
|
||||
|
||||
from django.utils.dateformat import format
|
||||
from django.utils import dateformat, translation, unittest
|
||||
from django.utils.timezone import utc
|
||||
from django.utils.tzinfo import FixedOffset, LocalTimezone
|
||||
|
||||
|
||||
class DateFormatTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.old_TZ = os.environ.get('TZ')
|
||||
os.environ['TZ'] = 'Europe/Copenhagen'
|
||||
translation.activate('en-us')
|
||||
|
||||
try:
|
||||
# Check if a timezone has been set
|
||||
time.tzset()
|
||||
self.tz_tests = True
|
||||
except AttributeError:
|
||||
# No timezone available. Don't run the tests that require a TZ
|
||||
self.tz_tests = False
|
||||
|
||||
def tearDown(self):
|
||||
if self.old_TZ is None:
|
||||
del os.environ['TZ']
|
||||
else:
|
||||
os.environ['TZ'] = self.old_TZ
|
||||
|
||||
# Cleanup - force re-evaluation of TZ environment variable.
|
||||
if self.tz_tests:
|
||||
time.tzset()
|
||||
|
||||
def test_date(self):
|
||||
d = date(2009, 5, 16)
|
||||
self.assertEqual(date.fromtimestamp(int(format(d, 'U'))), d)
|
||||
|
||||
def test_naive_datetime(self):
|
||||
dt = datetime(2009, 5, 16, 5, 30, 30)
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt)
|
||||
|
||||
def test_datetime_with_local_tzinfo(self):
|
||||
ltz = LocalTimezone(datetime.now())
|
||||
dt = datetime(2009, 5, 16, 5, 30, 30, tzinfo=ltz)
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), ltz), dt)
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt.replace(tzinfo=None))
|
||||
|
||||
def test_datetime_with_tzinfo(self):
|
||||
tz = FixedOffset(-510)
|
||||
ltz = LocalTimezone(datetime.now())
|
||||
dt = datetime(2009, 5, 16, 5, 30, 30, tzinfo=tz)
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), tz), dt)
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), ltz), dt)
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt.astimezone(ltz).replace(tzinfo=None))
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), tz).utctimetuple(), dt.utctimetuple())
|
||||
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), ltz).utctimetuple(), dt.utctimetuple())
|
||||
|
||||
def test_epoch(self):
|
||||
udt = datetime(1970, 1, 1, tzinfo=utc)
|
||||
self.assertEqual(format(udt, 'U'), '0')
|
||||
|
||||
def test_empty_format(self):
|
||||
my_birthday = datetime(1979, 7, 8, 22, 00)
|
||||
|
||||
self.assertEqual(dateformat.format(my_birthday, ''), '')
|
||||
|
||||
def test_am_pm(self):
|
||||
my_birthday = datetime(1979, 7, 8, 22, 00)
|
||||
|
||||
self.assertEqual(dateformat.format(my_birthday, 'a'), 'p.m.')
|
||||
|
||||
def test_microsecond(self):
|
||||
# Regression test for #18951
|
||||
dt = datetime(2009, 5, 16, microsecond=123)
|
||||
self.assertEqual(dateformat.format(dt, 'u'), '000123')
|
||||
|
||||
def test_date_formats(self):
|
||||
my_birthday = datetime(1979, 7, 8, 22, 00)
|
||||
timestamp = datetime(2008, 5, 19, 11, 45, 23, 123456)
|
||||
|
||||
self.assertEqual(dateformat.format(my_birthday, 'A'), 'PM')
|
||||
self.assertEqual(dateformat.format(timestamp, 'c'), '2008-05-19T11:45:23.123456')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'd'), '08')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'j'), '8')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'l'), 'Sunday')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'L'), 'False')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'm'), '07')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'M'), 'Jul')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'b'), 'jul')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'n'), '7')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'N'), 'July')
|
||||
|
||||
def test_time_formats(self):
|
||||
my_birthday = datetime(1979, 7, 8, 22, 00)
|
||||
|
||||
self.assertEqual(dateformat.format(my_birthday, 'P'), '10 p.m.')
|
||||
self.assertEqual(dateformat.format(my_birthday, 's'), '00')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'S'), 'th')
|
||||
self.assertEqual(dateformat.format(my_birthday, 't'), '31')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'w'), '0')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'W'), '27')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'y'), '79')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'Y'), '1979')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'z'), '189')
|
||||
|
||||
def test_dateformat(self):
|
||||
my_birthday = datetime(1979, 7, 8, 22, 00)
|
||||
|
||||
self.assertEqual(dateformat.format(my_birthday, r'Y z \C\E\T'), '1979 189 CET')
|
||||
|
||||
self.assertEqual(dateformat.format(my_birthday, r'jS \o\f F'), '8th of July')
|
||||
|
||||
def test_futuredates(self):
|
||||
the_future = datetime(2100, 10, 25, 0, 00)
|
||||
self.assertEqual(dateformat.format(the_future, r'Y'), '2100')
|
||||
|
||||
def test_timezones(self):
|
||||
my_birthday = datetime(1979, 7, 8, 22, 00)
|
||||
summertime = datetime(2005, 10, 30, 1, 00)
|
||||
wintertime = datetime(2005, 10, 30, 4, 00)
|
||||
timestamp = datetime(2008, 5, 19, 11, 45, 23, 123456)
|
||||
|
||||
if self.tz_tests:
|
||||
self.assertEqual(dateformat.format(my_birthday, 'O'), '+0100')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'r'), 'Sun, 8 Jul 1979 22:00:00 +0100')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'T'), 'CET')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'U'), '300315600')
|
||||
self.assertEqual(dateformat.format(timestamp, 'u'), '123456')
|
||||
self.assertEqual(dateformat.format(my_birthday, 'Z'), '3600')
|
||||
self.assertEqual(dateformat.format(summertime, 'I'), '1')
|
||||
self.assertEqual(dateformat.format(summertime, 'O'), '+0200')
|
||||
self.assertEqual(dateformat.format(wintertime, 'I'), '0')
|
||||
self.assertEqual(dateformat.format(wintertime, 'O'), '+0100')
|
||||
|
||||
# Ticket #16924 -- We don't need timezone support to test this
|
||||
# 3h30m to the west of UTC
|
||||
tz = FixedOffset(-3*60 - 30)
|
||||
dt = datetime(2009, 5, 16, 5, 30, 30, tzinfo=tz)
|
||||
self.assertEqual(dateformat.format(dt, 'O'), '-0330')
|
44
tests/utils_tests/dateparse.py
Normal file
44
tests/utils_tests/dateparse.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import date, time, datetime
|
||||
|
||||
from django.utils.dateparse import parse_date, parse_time, parse_datetime
|
||||
from django.utils import unittest
|
||||
from django.utils.tzinfo import FixedOffset
|
||||
|
||||
|
||||
class DateParseTests(unittest.TestCase):
|
||||
|
||||
def test_parse_date(self):
|
||||
# Valid inputs
|
||||
self.assertEqual(parse_date('2012-04-23'), date(2012, 4, 23))
|
||||
self.assertEqual(parse_date('2012-4-9'), date(2012, 4, 9))
|
||||
# Invalid inputs
|
||||
self.assertEqual(parse_date('20120423'), None)
|
||||
self.assertRaises(ValueError, parse_date, '2012-04-56')
|
||||
|
||||
def test_parse_time(self):
|
||||
# Valid inputs
|
||||
self.assertEqual(parse_time('09:15:00'), time(9, 15))
|
||||
self.assertEqual(parse_time('10:10'), time(10, 10))
|
||||
self.assertEqual(parse_time('10:20:30.400'), time(10, 20, 30, 400000))
|
||||
self.assertEqual(parse_time('4:8:16'), time(4, 8, 16))
|
||||
# Invalid inputs
|
||||
self.assertEqual(parse_time('091500'), None)
|
||||
self.assertRaises(ValueError, parse_time, '09:15:90')
|
||||
|
||||
def test_parse_datetime(self):
|
||||
# Valid inputs
|
||||
self.assertEqual(parse_datetime('2012-04-23T09:15:00'),
|
||||
datetime(2012, 4, 23, 9, 15))
|
||||
self.assertEqual(parse_datetime('2012-4-9 4:8:16'),
|
||||
datetime(2012, 4, 9, 4, 8, 16))
|
||||
self.assertEqual(parse_datetime('2012-04-23T09:15:00Z'),
|
||||
datetime(2012, 4, 23, 9, 15, 0, 0, FixedOffset(0)))
|
||||
self.assertEqual(parse_datetime('2012-4-9 4:8:16-0320'),
|
||||
datetime(2012, 4, 9, 4, 8, 16, 0, FixedOffset(-200)))
|
||||
self.assertEqual(parse_datetime('2012-04-23T10:20:30.400+02:30'),
|
||||
datetime(2012, 4, 23, 10, 20, 30, 400000, FixedOffset(150)))
|
||||
# Invalid inputs
|
||||
self.assertEqual(parse_datetime('20120423091500'), None)
|
||||
self.assertRaises(ValueError, parse_datetime, '2012-04-56T09:15:90')
|
42
tests/utils_tests/datetime_safe.py
Normal file
42
tests/utils_tests/datetime_safe.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
import unittest
|
||||
|
||||
from datetime import date as original_date, datetime as original_datetime
|
||||
from django.utils.datetime_safe import date, datetime
|
||||
|
||||
class DatetimeTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.just_safe = (1900, 1, 1)
|
||||
self.just_unsafe = (1899, 12, 31, 23, 59, 59)
|
||||
self.really_old = (20, 1, 1)
|
||||
self.more_recent = (2006, 1, 1)
|
||||
|
||||
def test_compare_datetimes(self):
|
||||
self.assertEqual(original_datetime(*self.more_recent), datetime(*self.more_recent))
|
||||
self.assertEqual(original_datetime(*self.really_old), datetime(*self.really_old))
|
||||
self.assertEqual(original_date(*self.more_recent), date(*self.more_recent))
|
||||
self.assertEqual(original_date(*self.really_old), date(*self.really_old))
|
||||
|
||||
self.assertEqual(original_date(*self.just_safe).strftime('%Y-%m-%d'), date(*self.just_safe).strftime('%Y-%m-%d'))
|
||||
self.assertEqual(original_datetime(*self.just_safe).strftime('%Y-%m-%d'), datetime(*self.just_safe).strftime('%Y-%m-%d'))
|
||||
|
||||
def test_safe_strftime(self):
|
||||
self.assertEqual(date(*self.just_unsafe[:3]).strftime('%Y-%m-%d (weekday %w)'), '1899-12-31 (weekday 0)')
|
||||
self.assertEqual(date(*self.just_safe).strftime('%Y-%m-%d (weekday %w)'), '1900-01-01 (weekday 1)')
|
||||
|
||||
self.assertEqual(datetime(*self.just_unsafe).strftime('%Y-%m-%d %H:%M:%S (weekday %w)'), '1899-12-31 23:59:59 (weekday 0)')
|
||||
self.assertEqual(datetime(*self.just_safe).strftime('%Y-%m-%d %H:%M:%S (weekday %w)'), '1900-01-01 00:00:00 (weekday 1)')
|
||||
|
||||
# %y will error before this date
|
||||
self.assertEqual(date(*self.just_safe).strftime('%y'), '00')
|
||||
self.assertEqual(datetime(*self.just_safe).strftime('%y'), '00')
|
||||
|
||||
self.assertEqual(date(1850, 8, 2).strftime("%Y/%m/%d was a %A"), '1850/08/02 was a Friday')
|
||||
|
||||
def test_zero_padding(self):
|
||||
"""
|
||||
Regression for #12524
|
||||
|
||||
Check that pre-1000AD dates are padded with zeros if necessary
|
||||
"""
|
||||
self.assertEqual(date(1, 1, 1).strftime("%Y/%m/%d was a %A"), '0001/01/01 was a Monday')
|
108
tests/utils_tests/decorators.py
Normal file
108
tests/utils_tests/decorators.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
from django.http import HttpResponse
|
||||
from django.template import Template, Context
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase, RequestFactory
|
||||
from django.utils.decorators import decorator_from_middleware
|
||||
|
||||
|
||||
class ProcessViewMiddleware(object):
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
pass
|
||||
|
||||
process_view_dec = decorator_from_middleware(ProcessViewMiddleware)
|
||||
|
||||
@process_view_dec
|
||||
def process_view(request):
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
class ClassProcessView(object):
|
||||
def __call__(self, request):
|
||||
return HttpResponse()
|
||||
|
||||
class_process_view = process_view_dec(ClassProcessView())
|
||||
|
||||
|
||||
class FullMiddleware(object):
|
||||
def process_request(self, request):
|
||||
request.process_request_reached = True
|
||||
|
||||
def process_view(sef, request, view_func, view_args, view_kwargs):
|
||||
request.process_view_reached = True
|
||||
|
||||
def process_template_response(self, request, response):
|
||||
request.process_template_response_reached = True
|
||||
return response
|
||||
|
||||
def process_response(self, request, response):
|
||||
# This should never receive unrendered content.
|
||||
request.process_response_content = response.content
|
||||
request.process_response_reached = True
|
||||
return response
|
||||
|
||||
full_dec = decorator_from_middleware(FullMiddleware)
|
||||
|
||||
|
||||
class DecoratorFromMiddlewareTests(TestCase):
|
||||
"""
|
||||
Tests for view decorators created using
|
||||
``django.utils.decorators.decorator_from_middleware``.
|
||||
"""
|
||||
rf = RequestFactory()
|
||||
|
||||
def test_process_view_middleware(self):
|
||||
"""
|
||||
Test a middleware that implements process_view.
|
||||
"""
|
||||
process_view(self.rf.get('/'))
|
||||
|
||||
def test_callable_process_view_middleware(self):
|
||||
"""
|
||||
Test a middleware that implements process_view, operating on a callable class.
|
||||
"""
|
||||
class_process_view(self.rf.get('/'))
|
||||
|
||||
def test_full_dec_normal(self):
|
||||
"""
|
||||
Test that all methods of middleware are called for normal HttpResponses
|
||||
"""
|
||||
|
||||
@full_dec
|
||||
def normal_view(request):
|
||||
t = Template("Hello world")
|
||||
return HttpResponse(t.render(Context({})))
|
||||
|
||||
request = self.rf.get('/')
|
||||
response = normal_view(request)
|
||||
self.assertTrue(getattr(request, 'process_request_reached', False))
|
||||
self.assertTrue(getattr(request, 'process_view_reached', False))
|
||||
# process_template_response must not be called for HttpResponse
|
||||
self.assertFalse(getattr(request, 'process_template_response_reached', False))
|
||||
self.assertTrue(getattr(request, 'process_response_reached', False))
|
||||
|
||||
def test_full_dec_templateresponse(self):
|
||||
"""
|
||||
Test that all methods of middleware are called for TemplateResponses in
|
||||
the right sequence.
|
||||
"""
|
||||
|
||||
@full_dec
|
||||
def template_response_view(request):
|
||||
t = Template("Hello world")
|
||||
return TemplateResponse(request, t, {})
|
||||
|
||||
request = self.rf.get('/')
|
||||
response = template_response_view(request)
|
||||
self.assertTrue(getattr(request, 'process_request_reached', False))
|
||||
self.assertTrue(getattr(request, 'process_view_reached', False))
|
||||
self.assertTrue(getattr(request, 'process_template_response_reached', False))
|
||||
# response must not be rendered yet.
|
||||
self.assertFalse(response._is_rendered)
|
||||
# process_response must not be called until after response is rendered,
|
||||
# otherwise some decorators like csrf_protect and gzip_page will not
|
||||
# work correctly. See #16004
|
||||
self.assertFalse(getattr(request, 'process_response_reached', False))
|
||||
response.render()
|
||||
self.assertTrue(getattr(request, 'process_response_reached', False))
|
||||
# Check that process_response saw the rendered content
|
||||
self.assertEqual(request.process_response_content, b"Hello world")
|
BIN
tests/utils_tests/eggs/test_egg.egg
Normal file
BIN
tests/utils_tests/eggs/test_egg.egg
Normal file
Binary file not shown.
17
tests/utils_tests/encoding.py
Normal file
17
tests/utils_tests/encoding.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils import unittest
|
||||
from django.utils.encoding import force_bytes
|
||||
|
||||
|
||||
class TestEncodingUtils(unittest.TestCase):
|
||||
def test_force_bytes_exception(self):
|
||||
"""
|
||||
Test that force_bytes knows how to convert to bytes an exception
|
||||
containing non-ASCII characters in its args.
|
||||
"""
|
||||
error_msg = "This is an exception, voilà"
|
||||
exc = ValueError(error_msg)
|
||||
result = force_bytes(exc)
|
||||
self.assertEqual(result, error_msg.encode('utf-8'))
|
117
tests/utils_tests/feedgenerator.py
Normal file
117
tests/utils_tests/feedgenerator.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
|
||||
from django.utils import feedgenerator, tzinfo, unittest
|
||||
|
||||
class FeedgeneratorTest(unittest.TestCase):
|
||||
"""
|
||||
Tests for the low-level syndication feed framework.
|
||||
"""
|
||||
|
||||
def test_get_tag_uri(self):
|
||||
"""
|
||||
Test get_tag_uri() correctly generates TagURIs.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.get_tag_uri('http://example.org/foo/bar#headline', datetime.date(2004, 10, 25)),
|
||||
'tag:example.org,2004-10-25:/foo/bar/headline')
|
||||
|
||||
def test_get_tag_uri_with_port(self):
|
||||
"""
|
||||
Test that get_tag_uri() correctly generates TagURIs from URLs with port
|
||||
numbers.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.get_tag_uri('http://www.example.org:8000/2008/11/14/django#headline', datetime.datetime(2008, 11, 14, 13, 37, 0)),
|
||||
'tag:www.example.org,2008-11-14:/2008/11/14/django/headline')
|
||||
|
||||
def test_rfc2822_date(self):
|
||||
"""
|
||||
Test rfc2822_date() correctly formats datetime objects.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.rfc2822_date(datetime.datetime(2008, 11, 14, 13, 37, 0)),
|
||||
"Fri, 14 Nov 2008 13:37:00 -0000"
|
||||
)
|
||||
|
||||
def test_rfc2822_date_with_timezone(self):
|
||||
"""
|
||||
Test rfc2822_date() correctly formats datetime objects with tzinfo.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.rfc2822_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=tzinfo.FixedOffset(datetime.timedelta(minutes=60)))),
|
||||
"Fri, 14 Nov 2008 13:37:00 +0100"
|
||||
)
|
||||
|
||||
def test_rfc2822_date_without_time(self):
|
||||
"""
|
||||
Test rfc2822_date() correctly formats date objects.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.rfc2822_date(datetime.date(2008, 11, 14)),
|
||||
"Fri, 14 Nov 2008 00:00:00 -0000"
|
||||
)
|
||||
|
||||
def test_rfc3339_date(self):
|
||||
"""
|
||||
Test rfc3339_date() correctly formats datetime objects.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0)),
|
||||
"2008-11-14T13:37:00Z"
|
||||
)
|
||||
|
||||
def test_rfc3339_date_with_timezone(self):
|
||||
"""
|
||||
Test rfc3339_date() correctly formats datetime objects with tzinfo.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=tzinfo.FixedOffset(datetime.timedelta(minutes=120)))),
|
||||
"2008-11-14T13:37:00+02:00"
|
||||
)
|
||||
|
||||
def test_rfc3339_date_without_time(self):
|
||||
"""
|
||||
Test rfc3339_date() correctly formats date objects.
|
||||
"""
|
||||
self.assertEqual(
|
||||
feedgenerator.rfc3339_date(datetime.date(2008, 11, 14)),
|
||||
"2008-11-14T00:00:00Z"
|
||||
)
|
||||
|
||||
def test_atom1_mime_type(self):
|
||||
"""
|
||||
Test to make sure Atom MIME type has UTF8 Charset parameter set
|
||||
"""
|
||||
atom_feed = feedgenerator.Atom1Feed("title", "link", "description")
|
||||
self.assertEqual(
|
||||
atom_feed.mime_type, "application/atom+xml; charset=utf-8"
|
||||
)
|
||||
|
||||
def test_rss_mime_type(self):
|
||||
"""
|
||||
Test to make sure RSS MIME type has UTF8 Charset parameter set
|
||||
"""
|
||||
rss_feed = feedgenerator.Rss201rev2Feed("title", "link", "description")
|
||||
self.assertEqual(
|
||||
rss_feed.mime_type, "application/rss+xml; charset=utf-8"
|
||||
)
|
||||
|
||||
# Two regression tests for #14202
|
||||
|
||||
def test_feed_without_feed_url_gets_rendered_without_atom_link(self):
|
||||
feed = feedgenerator.Rss201rev2Feed('title', '/link/', 'descr')
|
||||
self.assertEqual(feed.feed['feed_url'], None)
|
||||
feed_content = feed.writeString('utf-8')
|
||||
self.assertNotIn('<atom:link', feed_content)
|
||||
self.assertNotIn('href="/feed/"', feed_content)
|
||||
self.assertNotIn('rel="self"', feed_content)
|
||||
|
||||
def test_feed_with_feed_url_gets_rendered_with_atom_link(self):
|
||||
feed = feedgenerator.Rss201rev2Feed('title', '/link/', 'descr', feed_url='/feed/')
|
||||
self.assertEqual(feed.feed['feed_url'], '/feed/')
|
||||
feed_content = feed.writeString('utf-8')
|
||||
self.assertIn('<atom:link', feed_content)
|
||||
self.assertIn('href="/feed/"', feed_content)
|
||||
self.assertIn('rel="self"', feed_content)
|
66
tests/utils_tests/functional.py
Normal file
66
tests/utils_tests/functional.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
from django.utils import unittest
|
||||
from django.utils.functional import lazy, lazy_property, cached_property
|
||||
|
||||
|
||||
class FunctionalTestCase(unittest.TestCase):
|
||||
def test_lazy(self):
|
||||
t = lazy(lambda: tuple(range(3)), list, tuple)
|
||||
for a, b in zip(t(), range(3)):
|
||||
self.assertEqual(a, b)
|
||||
|
||||
def test_lazy_base_class(self):
|
||||
"""Test that lazy also finds base class methods in the proxy object"""
|
||||
|
||||
class Base(object):
|
||||
def base_method(self):
|
||||
pass
|
||||
|
||||
class Klazz(Base):
|
||||
pass
|
||||
|
||||
t = lazy(lambda: Klazz(), Klazz)()
|
||||
self.assertTrue('base_method' in dir(t))
|
||||
|
||||
def test_lazy_property(self):
|
||||
|
||||
class A(object):
|
||||
|
||||
def _get_do(self):
|
||||
raise NotImplementedError
|
||||
def _set_do(self, value):
|
||||
raise NotImplementedError
|
||||
do = lazy_property(_get_do, _set_do)
|
||||
|
||||
class B(A):
|
||||
def _get_do(self):
|
||||
return "DO IT"
|
||||
|
||||
self.assertRaises(NotImplementedError, lambda: A().do)
|
||||
self.assertEqual(B().do, 'DO IT')
|
||||
|
||||
def test_cached_property(self):
|
||||
"""
|
||||
Test that cached_property caches its value,
|
||||
and that it behaves like a property
|
||||
"""
|
||||
|
||||
class A(object):
|
||||
|
||||
@cached_property
|
||||
def value(self):
|
||||
return 1, object()
|
||||
|
||||
a = A()
|
||||
|
||||
# check that it is cached
|
||||
self.assertEqual(a.value, a.value)
|
||||
|
||||
# check that it returns the right thing
|
||||
self.assertEqual(a.value[0], 1)
|
||||
|
||||
# check that state isn't shared between instances
|
||||
a2 = A()
|
||||
self.assertNotEqual(a.value, a2.value)
|
||||
|
||||
# check that it behaves like a property when there's no instance
|
||||
self.assertIsInstance(A.value, cached_property)
|
161
tests/utils_tests/html.py
Normal file
161
tests/utils_tests/html.py
Normal file
|
@ -0,0 +1,161 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
from django.utils import html
|
||||
|
||||
class TestUtilsHtml(unittest.TestCase):
|
||||
|
||||
def check_output(self, function, value, output=None):
|
||||
"""
|
||||
Check that function(value) equals output. If output is None,
|
||||
check that function(value) equals value.
|
||||
"""
|
||||
if output is None:
|
||||
output = value
|
||||
self.assertEqual(function(value), output)
|
||||
|
||||
def test_escape(self):
|
||||
f = html.escape
|
||||
items = (
|
||||
('&','&'),
|
||||
('<', '<'),
|
||||
('>', '>'),
|
||||
('"', '"'),
|
||||
("'", '''),
|
||||
)
|
||||
# Substitution patterns for testing the above items.
|
||||
patterns = ("%s", "asdf%sfdsa", "%s1", "1%sb")
|
||||
for value, output in items:
|
||||
for pattern in patterns:
|
||||
self.check_output(f, pattern % value, pattern % output)
|
||||
# Check repeated values.
|
||||
self.check_output(f, value * 2, output * 2)
|
||||
# Verify it doesn't double replace &.
|
||||
self.check_output(f, '<&', '<&')
|
||||
|
||||
def test_format_html(self):
|
||||
self.assertEqual(
|
||||
html.format_html("{0} {1} {third} {fourth}",
|
||||
"< Dangerous >",
|
||||
html.mark_safe("<b>safe</b>"),
|
||||
third="< dangerous again",
|
||||
fourth=html.mark_safe("<i>safe again</i>")
|
||||
),
|
||||
"< Dangerous > <b>safe</b> < dangerous again <i>safe again</i>"
|
||||
)
|
||||
|
||||
def test_linebreaks(self):
|
||||
f = html.linebreaks
|
||||
items = (
|
||||
("para1\n\npara2\r\rpara3", "<p>para1</p>\n\n<p>para2</p>\n\n<p>para3</p>"),
|
||||
("para1\nsub1\rsub2\n\npara2", "<p>para1<br />sub1<br />sub2</p>\n\n<p>para2</p>"),
|
||||
("para1\r\n\r\npara2\rsub1\r\rpara4", "<p>para1</p>\n\n<p>para2<br />sub1</p>\n\n<p>para4</p>"),
|
||||
("para1\tmore\n\npara2", "<p>para1\tmore</p>\n\n<p>para2</p>"),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
def test_strip_tags(self):
|
||||
f = html.strip_tags
|
||||
items = (
|
||||
('<adf>a', 'a'),
|
||||
('</adf>a', 'a'),
|
||||
('<asdf><asdf>e', 'e'),
|
||||
('<f', '<f'),
|
||||
('</fe', '</fe'),
|
||||
('<x>b<y>', 'b'),
|
||||
('a<p onclick="alert(\'<test>\')">b</p>c', 'abc'),
|
||||
('a<p a >b</p>c', 'abc'),
|
||||
('d<a:b c:d>e</p>f', 'def'),
|
||||
('<strong>foo</strong><a href="http://example.com">bar</a>', 'foobar'),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
def test_strip_spaces_between_tags(self):
|
||||
f = html.strip_spaces_between_tags
|
||||
# Strings that should come out untouched.
|
||||
items = (' <adf>', '<adf> ', ' </adf> ', ' <f> x</f>')
|
||||
for value in items:
|
||||
self.check_output(f, value)
|
||||
# Strings that have spaces to strip.
|
||||
items = (
|
||||
('<d> </d>', '<d></d>'),
|
||||
('<p>hello </p>\n<p> world</p>', '<p>hello </p><p> world</p>'),
|
||||
('\n<p>\t</p>\n<p> </p>\n', '\n<p></p><p></p>\n'),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
def test_strip_entities(self):
|
||||
f = html.strip_entities
|
||||
# Strings that should come out untouched.
|
||||
values = ("&", "&a", "&a", "a&#a")
|
||||
for value in values:
|
||||
self.check_output(f, value)
|
||||
# Valid entities that should be stripped from the patterns.
|
||||
entities = ("", "", "&a;", "&fdasdfasdfasdf;")
|
||||
patterns = (
|
||||
("asdf %(entity)s ", "asdf "),
|
||||
("%(entity)s%(entity)s", ""),
|
||||
("&%(entity)s%(entity)s", "&"),
|
||||
("%(entity)s3", "3"),
|
||||
)
|
||||
for entity in entities:
|
||||
for in_pattern, output in patterns:
|
||||
self.check_output(f, in_pattern % {'entity': entity}, output)
|
||||
|
||||
def test_fix_ampersands(self):
|
||||
f = html.fix_ampersands
|
||||
# Strings without ampersands or with ampersands already encoded.
|
||||
values = ("a", "b", "&a;", "& &x; ", "asdf")
|
||||
patterns = (
|
||||
("%s", "%s"),
|
||||
("&%s", "&%s"),
|
||||
("&%s&", "&%s&"),
|
||||
)
|
||||
for value in values:
|
||||
for in_pattern, out_pattern in patterns:
|
||||
self.check_output(f, in_pattern % value, out_pattern % value)
|
||||
# Strings with ampersands that need encoding.
|
||||
items = (
|
||||
("&#;", "&#;"),
|
||||
("ͫ ;", "&#875 ;"),
|
||||
("abc;", "&#4abc;"),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
def test_escapejs(self):
|
||||
f = html.escapejs
|
||||
items = (
|
||||
('"double quotes" and \'single quotes\'', '\\u0022double quotes\\u0022 and \\u0027single quotes\\u0027'),
|
||||
(r'\ : backslashes, too', '\\u005C : backslashes, too'),
|
||||
('and lots of whitespace: \r\n\t\v\f\b', 'and lots of whitespace: \\u000D\\u000A\\u0009\\u000B\\u000C\\u0008'),
|
||||
(r'<script>and this</script>', '\\u003Cscript\\u003Eand this\\u003C/script\\u003E'),
|
||||
('paragraph separator:\u2029and line separator:\u2028', 'paragraph separator:\\u2029and line separator:\\u2028'),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
def test_clean_html(self):
|
||||
f = html.clean_html
|
||||
items = (
|
||||
('<p>I <i>believe</i> in <b>semantic markup</b>!</p>', '<p>I <em>believe</em> in <strong>semantic markup</strong>!</p>'),
|
||||
('I escape & I don\'t <a href="#" target="_blank">target</a>', 'I escape & I don\'t <a href="#" >target</a>'),
|
||||
('<p>I kill whitespace</p><br clear="all"><p> </p>', '<p>I kill whitespace</p>'),
|
||||
# also a regression test for #7267: this used to raise an UnicodeDecodeError
|
||||
('<p>* foo</p><p>* bar</p>', '<ul>\n<li> foo</li><li> bar</li>\n</ul>'),
|
||||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
def test_remove_tags(self):
|
||||
f = html.remove_tags
|
||||
items = (
|
||||
("<b><i>Yes</i></b>", "b i", "Yes"),
|
||||
("<a>x</a> <p><b>y</b></p>", "a b", "x <p>y</p>"),
|
||||
)
|
||||
for value, tags, output in items:
|
||||
self.assertEqual(f(value, tags), output)
|
163
tests/utils_tests/http.py
Normal file
163
tests/utils_tests/http.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
from datetime import datetime
|
||||
import sys
|
||||
|
||||
from django.http import HttpResponse, utils
|
||||
from django.test import RequestFactory
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.utils import http
|
||||
from django.utils import six
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class TestUtilsHttp(unittest.TestCase):
|
||||
|
||||
def test_same_origin_true(self):
|
||||
# Identical
|
||||
self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com/'))
|
||||
# One with trailing slash - see #15617
|
||||
self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com/'))
|
||||
self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com'))
|
||||
# With port
|
||||
self.assertTrue(http.same_origin('https://foo.com:8000', 'https://foo.com:8000/'))
|
||||
|
||||
def test_same_origin_false(self):
|
||||
# Different scheme
|
||||
self.assertFalse(http.same_origin('http://foo.com', 'https://foo.com'))
|
||||
# Different host
|
||||
self.assertFalse(http.same_origin('http://foo.com', 'http://goo.com'))
|
||||
# Different host again
|
||||
self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com'))
|
||||
# Different port
|
||||
self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001'))
|
||||
|
||||
def test_urlencode(self):
|
||||
# 2-tuples (the norm)
|
||||
result = http.urlencode((('a', 1), ('b', 2), ('c', 3)))
|
||||
self.assertEqual(result, 'a=1&b=2&c=3')
|
||||
|
||||
# A dictionary
|
||||
result = http.urlencode({ 'a': 1, 'b': 2, 'c': 3})
|
||||
acceptable_results = [
|
||||
# Need to allow all of these as dictionaries have to be treated as
|
||||
# unordered
|
||||
'a=1&b=2&c=3',
|
||||
'a=1&c=3&b=2',
|
||||
'b=2&a=1&c=3',
|
||||
'b=2&c=3&a=1',
|
||||
'c=3&a=1&b=2',
|
||||
'c=3&b=2&a=1'
|
||||
]
|
||||
self.assertTrue(result in acceptable_results)
|
||||
result = http.urlencode({'a': [1, 2]}, doseq=False)
|
||||
self.assertEqual(result, 'a=%5B%271%27%2C+%272%27%5D')
|
||||
result = http.urlencode({'a': [1, 2]}, doseq=True)
|
||||
self.assertEqual(result, 'a=1&a=2')
|
||||
result = http.urlencode({'a': []}, doseq=True)
|
||||
self.assertEqual(result, '')
|
||||
|
||||
# A MultiValueDict
|
||||
result = http.urlencode(MultiValueDict({
|
||||
'name': ['Adrian', 'Simon'],
|
||||
'position': ['Developer']
|
||||
}), doseq=True)
|
||||
acceptable_results = [
|
||||
# MultiValueDicts are similarly unordered
|
||||
'name=Adrian&name=Simon&position=Developer',
|
||||
'position=Developer&name=Adrian&name=Simon'
|
||||
]
|
||||
self.assertTrue(result in acceptable_results)
|
||||
|
||||
def test_fix_IE_for_vary(self):
|
||||
"""
|
||||
Regression for #16632.
|
||||
|
||||
`fix_IE_for_vary` shouldn't crash when there's no Content-Type header.
|
||||
"""
|
||||
|
||||
# functions to generate responses
|
||||
def response_with_unsafe_content_type():
|
||||
r = HttpResponse(content_type="text/unsafe")
|
||||
r['Vary'] = 'Cookie'
|
||||
return r
|
||||
|
||||
def no_content_response_with_unsafe_content_type():
|
||||
# 'Content-Type' always defaulted, so delete it
|
||||
r = response_with_unsafe_content_type()
|
||||
del r['Content-Type']
|
||||
return r
|
||||
|
||||
# request with & without IE user agent
|
||||
rf = RequestFactory()
|
||||
request = rf.get('/')
|
||||
ie_request = rf.get('/', HTTP_USER_AGENT='MSIE')
|
||||
|
||||
# not IE, unsafe_content_type
|
||||
response = response_with_unsafe_content_type()
|
||||
utils.fix_IE_for_vary(request, response)
|
||||
self.assertTrue('Vary' in response)
|
||||
|
||||
# IE, unsafe_content_type
|
||||
response = response_with_unsafe_content_type()
|
||||
utils.fix_IE_for_vary(ie_request, response)
|
||||
self.assertFalse('Vary' in response)
|
||||
|
||||
# not IE, no_content
|
||||
response = no_content_response_with_unsafe_content_type()
|
||||
utils.fix_IE_for_vary(request, response)
|
||||
self.assertTrue('Vary' in response)
|
||||
|
||||
# IE, no_content
|
||||
response = no_content_response_with_unsafe_content_type()
|
||||
utils.fix_IE_for_vary(ie_request, response)
|
||||
self.assertFalse('Vary' in response)
|
||||
|
||||
def test_base36(self):
|
||||
# reciprocity works
|
||||
for n in [0, 1, 1000, 1000000]:
|
||||
self.assertEqual(n, http.base36_to_int(http.int_to_base36(n)))
|
||||
if not six.PY3:
|
||||
self.assertEqual(sys.maxint, http.base36_to_int(http.int_to_base36(sys.maxint)))
|
||||
|
||||
# bad input
|
||||
self.assertRaises(ValueError, http.int_to_base36, -1)
|
||||
if not six.PY3:
|
||||
self.assertRaises(ValueError, http.int_to_base36, sys.maxint + 1)
|
||||
for n in ['1', 'foo', {1: 2}, (1, 2, 3), 3.141]:
|
||||
self.assertRaises(TypeError, http.int_to_base36, n)
|
||||
|
||||
for n in ['#', ' ']:
|
||||
self.assertRaises(ValueError, http.base36_to_int, n)
|
||||
for n in [123, {1: 2}, (1, 2, 3), 3.141]:
|
||||
self.assertRaises(TypeError, http.base36_to_int, n)
|
||||
|
||||
# more explicit output testing
|
||||
for n, b36 in [(0, '0'), (1, '1'), (42, '16'), (818469960, 'django')]:
|
||||
self.assertEqual(http.int_to_base36(n), b36)
|
||||
self.assertEqual(http.base36_to_int(b36), n)
|
||||
|
||||
|
||||
class ETagProcessingTests(unittest.TestCase):
|
||||
def testParsing(self):
|
||||
etags = http.parse_etags(r'"", "etag", "e\"t\"ag", "e\\tag", W/"weak"')
|
||||
self.assertEqual(etags, ['', 'etag', 'e"t"ag', r'e\tag', 'weak'])
|
||||
|
||||
def testQuoting(self):
|
||||
quoted_etag = http.quote_etag(r'e\t"ag')
|
||||
self.assertEqual(quoted_etag, r'"e\\t\"ag"')
|
||||
|
||||
|
||||
class HttpDateProcessingTests(unittest.TestCase):
|
||||
def testParsingRfc1123(self):
|
||||
parsed = http.parse_http_date('Sun, 06 Nov 1994 08:49:37 GMT')
|
||||
self.assertEqual(datetime.utcfromtimestamp(parsed),
|
||||
datetime(1994, 11, 6, 8, 49, 37))
|
||||
|
||||
def testParsingRfc850(self):
|
||||
parsed = http.parse_http_date('Sunday, 06-Nov-94 08:49:37 GMT')
|
||||
self.assertEqual(datetime.utcfromtimestamp(parsed),
|
||||
datetime(1994, 11, 6, 8, 49, 37))
|
||||
|
||||
def testParsingAsctime(self):
|
||||
parsed = http.parse_http_date('Sun Nov 6 08:49:37 1994')
|
||||
self.assertEqual(datetime.utcfromtimestamp(parsed),
|
||||
datetime(1994, 11, 6, 8, 49, 37))
|
53
tests/utils_tests/ipv6.py
Normal file
53
tests/utils_tests/ipv6.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils import unittest
|
||||
from django.utils.ipv6 import is_valid_ipv6_address, clean_ipv6_address
|
||||
|
||||
class TestUtilsIPv6(unittest.TestCase):
|
||||
|
||||
def test_validates_correct_plain_address(self):
|
||||
self.assertTrue(is_valid_ipv6_address('fe80::223:6cff:fe8a:2e8a'))
|
||||
self.assertTrue(is_valid_ipv6_address('2a02::223:6cff:fe8a:2e8a'))
|
||||
self.assertTrue(is_valid_ipv6_address('1::2:3:4:5:6:7'))
|
||||
self.assertTrue(is_valid_ipv6_address('::'))
|
||||
self.assertTrue(is_valid_ipv6_address('::a'))
|
||||
self.assertTrue(is_valid_ipv6_address('2::'))
|
||||
|
||||
def test_validates_correct_with_v4mapping(self):
|
||||
self.assertTrue(is_valid_ipv6_address('::ffff:254.42.16.14'))
|
||||
self.assertTrue(is_valid_ipv6_address('::ffff:0a0a:0a0a'))
|
||||
|
||||
def test_validates_incorrect_plain_address(self):
|
||||
self.assertFalse(is_valid_ipv6_address('foo'))
|
||||
self.assertFalse(is_valid_ipv6_address('127.0.0.1'))
|
||||
self.assertFalse(is_valid_ipv6_address('12345::'))
|
||||
self.assertFalse(is_valid_ipv6_address('1::2:3::4'))
|
||||
self.assertFalse(is_valid_ipv6_address('1::zzz'))
|
||||
self.assertFalse(is_valid_ipv6_address('1::2:3:4:5:6:7:8'))
|
||||
self.assertFalse(is_valid_ipv6_address('1:2'))
|
||||
self.assertFalse(is_valid_ipv6_address('1:::2'))
|
||||
|
||||
def test_validates_incorrect_with_v4mapping(self):
|
||||
self.assertFalse(is_valid_ipv6_address('::ffff:999.42.16.14'))
|
||||
self.assertFalse(is_valid_ipv6_address('::ffff:zzzz:0a0a'))
|
||||
# The ::1.2.3.4 format used to be valid but was deprecated
|
||||
# in rfc4291 section 2.5.5.1
|
||||
self.assertTrue(is_valid_ipv6_address('::254.42.16.14'))
|
||||
self.assertTrue(is_valid_ipv6_address('::0a0a:0a0a'))
|
||||
self.assertFalse(is_valid_ipv6_address('::999.42.16.14'))
|
||||
self.assertFalse(is_valid_ipv6_address('::zzzz:0a0a'))
|
||||
|
||||
def test_cleanes_plain_address(self):
|
||||
self.assertEqual(clean_ipv6_address('DEAD::0:BEEF'), 'dead::beef')
|
||||
self.assertEqual(clean_ipv6_address('2001:000:a:0000:0:fe:fe:beef'), '2001:0:a::fe:fe:beef')
|
||||
self.assertEqual(clean_ipv6_address('2001::a:0000:0:fe:fe:beef'), '2001:0:a::fe:fe:beef')
|
||||
|
||||
def test_cleanes_with_v4_mapping(self):
|
||||
self.assertEqual(clean_ipv6_address('::ffff:0a0a:0a0a'), '::ffff:10.10.10.10')
|
||||
self.assertEqual(clean_ipv6_address('::ffff:1234:1234'), '::ffff:18.52.18.52')
|
||||
self.assertEqual(clean_ipv6_address('::ffff:18.52.18.52'), '::ffff:18.52.18.52')
|
||||
|
||||
def test_unpacks_ipv4(self):
|
||||
self.assertEqual(clean_ipv6_address('::ffff:0a0a:0a0a', unpack_ipv4=True), '10.10.10.10')
|
||||
self.assertEqual(clean_ipv6_address('::ffff:1234:1234', unpack_ipv4=True), '18.52.18.52')
|
||||
self.assertEqual(clean_ipv6_address('::ffff:18.52.18.52', unpack_ipv4=True), '18.52.18.52')
|
216
tests/utils_tests/jslex.py
Normal file
216
tests/utils_tests/jslex.py
Normal file
|
@ -0,0 +1,216 @@
|
|||
"""Tests for jslex."""
|
||||
# encoding: utf-8
|
||||
# originally from https://bitbucket.org/ned/jslex
|
||||
|
||||
from django.test import TestCase
|
||||
from django.utils.jslex import JsLexer, prepare_js_for_gettext
|
||||
|
||||
class JsTokensTest(TestCase):
|
||||
LEX_CASES = [
|
||||
# ids
|
||||
("a ABC $ _ a123", ["id a", "id ABC", "id $", "id _", "id a123"]),
|
||||
(r"\u1234 abc\u0020 \u0065_\u0067", [r"id \u1234", r"id abc\u0020", r"id \u0065_\u0067"]),
|
||||
# numbers
|
||||
("123 1.234 0.123e-3 0 1E+40 1e1 .123", ["dnum 123", "dnum 1.234", "dnum 0.123e-3", "dnum 0", "dnum 1E+40", "dnum 1e1", "dnum .123"]),
|
||||
("0x1 0xabCD 0XABcd", ["hnum 0x1", "hnum 0xabCD", "hnum 0XABcd"]),
|
||||
("010 0377 090", ["onum 010", "onum 0377", "dnum 0", "dnum 90"]),
|
||||
("0xa123ghi", ["hnum 0xa123", "id ghi"]),
|
||||
# keywords
|
||||
("function Function FUNCTION", ["keyword function", "id Function", "id FUNCTION"]),
|
||||
("const constructor in inherits", ["keyword const", "id constructor", "keyword in", "id inherits"]),
|
||||
("true true_enough", ["reserved true", "id true_enough"]),
|
||||
# strings
|
||||
(''' 'hello' "hello" ''', ["string 'hello'", 'string "hello"']),
|
||||
(r""" 'don\'t' "don\"t" '"' "'" '\'' "\"" """,
|
||||
[r"""string 'don\'t'""", r'''string "don\"t"''', r"""string '"'""", r'''string "'"''', r"""string '\''""", r'''string "\""''']),
|
||||
(r'"ƃuıxǝ⅂ ʇdıɹɔsɐʌɐſ\""', [r'string "ƃuıxǝ⅂ ʇdıɹɔsɐʌɐſ\""']),
|
||||
# comments
|
||||
("a//b", ["id a", "linecomment //b"]),
|
||||
("/****/a/=2//hello", ["comment /****/", "id a", "punct /=", "dnum 2", "linecomment //hello"]),
|
||||
("/*\n * Header\n */\na=1;", ["comment /*\n * Header\n */", "id a", "punct =", "dnum 1", "punct ;"]),
|
||||
# punctuation
|
||||
("a+++b", ["id a", "punct ++", "punct +", "id b"]),
|
||||
# regex
|
||||
(r"a=/a*/,1", ["id a", "punct =", "regex /a*/", "punct ,", "dnum 1"]),
|
||||
(r"a=/a*[^/]+/,1", ["id a", "punct =", "regex /a*[^/]+/", "punct ,", "dnum 1"]),
|
||||
(r"a=/a*\[^/,1", ["id a", "punct =", r"regex /a*\[^/", "punct ,", "dnum 1"]),
|
||||
(r"a=/\//,1", ["id a", "punct =", r"regex /\//", "punct ,", "dnum 1"]),
|
||||
|
||||
# next two are from http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
("""for (var x = a in foo && "</x>" || mot ? z:/x:3;x<5;y</g/i) {xyz(x++);}""",
|
||||
["keyword for", "punct (", "keyword var", "id x", "punct =", "id a", "keyword in",
|
||||
"id foo", "punct &&", 'string "</x>"', "punct ||", "id mot", "punct ?", "id z",
|
||||
"punct :", "regex /x:3;x<5;y</g", "punct /", "id i", "punct )", "punct {",
|
||||
"id xyz", "punct (", "id x", "punct ++", "punct )", "punct ;", "punct }"]),
|
||||
("""for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y</g/i) {xyz(x++);}""",
|
||||
["keyword for", "punct (", "keyword var", "id x", "punct =", "id a", "keyword in",
|
||||
"id foo", "punct &&", 'string "</x>"', "punct ||", "id mot", "punct ?", "id z",
|
||||
"punct /", "id x", "punct :", "dnum 3", "punct ;", "id x", "punct <", "dnum 5",
|
||||
"punct ;", "id y", "punct <", "regex /g/i", "punct )", "punct {",
|
||||
"id xyz", "punct (", "id x", "punct ++", "punct )", "punct ;", "punct }"]),
|
||||
|
||||
# Various "illegal" regexes that are valid according to the std.
|
||||
(r"""/????/, /++++/, /[----]/ """, ["regex /????/", "punct ,", "regex /++++/", "punct ,", "regex /[----]/"]),
|
||||
|
||||
# Stress cases from http://stackoverflow.com/questions/5533925/what-javascript-constructs-does-jslex-incorrectly-lex/5573409#5573409
|
||||
(r"""/\[/""", [r"""regex /\[/"""]),
|
||||
(r"""/[i]/""", [r"""regex /[i]/"""]),
|
||||
(r"""/[\]]/""", [r"""regex /[\]]/"""]),
|
||||
(r"""/a[\]]/""", [r"""regex /a[\]]/"""]),
|
||||
(r"""/a[\]]b/""", [r"""regex /a[\]]b/"""]),
|
||||
(r"""/[\]/]/gi""", [r"""regex /[\]/]/gi"""]),
|
||||
(r"""/\[[^\]]+\]/gi""", [r"""regex /\[[^\]]+\]/gi"""]),
|
||||
("""
|
||||
rexl.re = {
|
||||
NAME: /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/,
|
||||
UNQUOTED_LITERAL: /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/,
|
||||
QUOTED_LITERAL: /^'(?:[^']|'')*'/,
|
||||
NUMERIC_LITERAL: /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/,
|
||||
SYMBOL: /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/
|
||||
};
|
||||
""",
|
||||
["id rexl", "punct .", "id re", "punct =", "punct {",
|
||||
"id NAME", "punct :", r"""regex /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/""", "punct ,",
|
||||
"id UNQUOTED_LITERAL", "punct :", r"""regex /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""", "punct ,",
|
||||
"id QUOTED_LITERAL", "punct :", r"""regex /^'(?:[^']|'')*'/""", "punct ,",
|
||||
"id NUMERIC_LITERAL", "punct :", r"""regex /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", "punct ,",
|
||||
"id SYMBOL", "punct :", r"""regex /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""",
|
||||
"punct }", "punct ;"
|
||||
]),
|
||||
|
||||
("""
|
||||
rexl.re = {
|
||||
NAME: /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/,
|
||||
UNQUOTED_LITERAL: /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/,
|
||||
QUOTED_LITERAL: /^'(?:[^']|'')*'/,
|
||||
NUMERIC_LITERAL: /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/,
|
||||
SYMBOL: /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/
|
||||
};
|
||||
str = '"';
|
||||
""",
|
||||
["id rexl", "punct .", "id re", "punct =", "punct {",
|
||||
"id NAME", "punct :", r"""regex /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/""", "punct ,",
|
||||
"id UNQUOTED_LITERAL", "punct :", r"""regex /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""", "punct ,",
|
||||
"id QUOTED_LITERAL", "punct :", r"""regex /^'(?:[^']|'')*'/""", "punct ,",
|
||||
"id NUMERIC_LITERAL", "punct :", r"""regex /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", "punct ,",
|
||||
"id SYMBOL", "punct :", r"""regex /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""",
|
||||
"punct }", "punct ;",
|
||||
"id str", "punct =", """string '"'""", "punct ;",
|
||||
]),
|
||||
|
||||
(r""" this._js = "e.str(\"" + this.value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\")"; """,
|
||||
["keyword this", "punct .", "id _js", "punct =", r'''string "e.str(\""''', "punct +", "keyword this", "punct .",
|
||||
"id value", "punct .", "id replace", "punct (", r"regex /\\/g", "punct ,", r'string "\\\\"', "punct )",
|
||||
"punct .", "id replace", "punct (", r'regex /"/g', "punct ,", r'string "\\\""', "punct )", "punct +",
|
||||
r'string "\")"', "punct ;"]),
|
||||
]
|
||||
|
||||
def make_function(input, toks):
|
||||
def test_func(self):
|
||||
lexer = JsLexer()
|
||||
result = ["%s %s" % (name, tok) for name, tok in lexer.lex(input) if name != 'ws']
|
||||
self.assertListEqual(result, toks)
|
||||
return test_func
|
||||
|
||||
for i, (input, toks) in enumerate(JsTokensTest.LEX_CASES):
|
||||
setattr(JsTokensTest, "test_case_%d" % i, make_function(input, toks))
|
||||
|
||||
|
||||
GETTEXT_CASES = (
|
||||
(
|
||||
r"""
|
||||
a = 1; /* /[0-9]+/ */
|
||||
b = 0x2a0b / 1; // /[0-9]+/
|
||||
c = 3;
|
||||
""",
|
||||
r"""
|
||||
a = 1; /* /[0-9]+/ */
|
||||
b = 0x2a0b / 1; // /[0-9]+/
|
||||
c = 3;
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
a = 1.234e-5;
|
||||
/*
|
||||
* /[0-9+/
|
||||
*/
|
||||
b = .0123;
|
||||
""",
|
||||
r"""
|
||||
a = 1.234e-5;
|
||||
/*
|
||||
* /[0-9+/
|
||||
*/
|
||||
b = .0123;
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
x = y / z;
|
||||
alert(gettext("hello"));
|
||||
x /= 3;
|
||||
""",
|
||||
r"""
|
||||
x = y / z;
|
||||
alert(gettext("hello"));
|
||||
x /= 3;
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
s = "Hello \"th/foo/ere\"";
|
||||
s = 'He\x23llo \'th/foo/ere\'';
|
||||
s = 'slash quote \", just quote "';
|
||||
""",
|
||||
r"""
|
||||
s = "Hello \"th/foo/ere\"";
|
||||
s = "He\x23llo \'th/foo/ere\'";
|
||||
s = "slash quote \", just quote \"";
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
s = "Line continuation\
|
||||
continued /hello/ still the string";/hello/;
|
||||
""",
|
||||
r"""
|
||||
s = "Line continuation\
|
||||
continued /hello/ still the string";"REGEX";
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
var regex = /pattern/;
|
||||
var regex2 = /matter/gm;
|
||||
var regex3 = /[*/]+/gm.foo("hey");
|
||||
""",
|
||||
r"""
|
||||
var regex = "REGEX";
|
||||
var regex2 = "REGEX";
|
||||
var regex3 = "REGEX".foo("hey");
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
for (var x = a in foo && "</x>" || mot ? z:/x:3;x<5;y</g/i) {xyz(x++);}
|
||||
for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y</g/i) {xyz(x++);}
|
||||
""",
|
||||
r"""
|
||||
for (var x = a in foo && "</x>" || mot ? z:"REGEX"/i) {xyz(x++);}
|
||||
for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y<"REGEX") {xyz(x++);}
|
||||
"""
|
||||
), (
|
||||
r"""
|
||||
\u1234xyz = gettext('Hello there');
|
||||
""", r"""
|
||||
Uu1234xyz = gettext("Hello there");
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class JsToCForGettextTest(TestCase):
|
||||
pass
|
||||
|
||||
def make_function(js, c):
|
||||
def test_func(self):
|
||||
self.assertMultiLineEqual(prepare_js_for_gettext(js), c)
|
||||
return test_func
|
||||
|
||||
for i, pair in enumerate(GETTEXT_CASES):
|
||||
setattr(JsToCForGettextTest, "test_case_%d" % i, make_function(*pair))
|
1
tests/utils_tests/models.py
Normal file
1
tests/utils_tests/models.py
Normal file
|
@ -0,0 +1 @@
|
|||
# Test runner needs a models.py file.
|
184
tests/utils_tests/module_loading.py
Normal file
184
tests/utils_tests/module_loading.py
Normal file
|
@ -0,0 +1,184 @@
|
|||
import os
|
||||
import sys
|
||||
import imp
|
||||
from zipimport import zipimporter
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils import unittest
|
||||
from django.utils.importlib import import_module
|
||||
from django.utils.module_loading import import_by_path, module_has_submodule
|
||||
from django.utils._os import upath
|
||||
|
||||
|
||||
class DefaultLoader(unittest.TestCase):
|
||||
def setUp(self):
|
||||
sys.meta_path.insert(0, ProxyFinder())
|
||||
|
||||
def tearDown(self):
|
||||
sys.meta_path.pop(0)
|
||||
|
||||
def test_loader(self):
|
||||
"Normal module existence can be tested"
|
||||
test_module = import_module('utils_tests.test_module')
|
||||
test_no_submodule = import_module(
|
||||
'utils_tests.test_no_submodule')
|
||||
|
||||
# An importable child
|
||||
self.assertTrue(module_has_submodule(test_module, 'good_module'))
|
||||
mod = import_module('utils_tests.test_module.good_module')
|
||||
self.assertEqual(mod.content, 'Good Module')
|
||||
|
||||
# A child that exists, but will generate an import error if loaded
|
||||
self.assertTrue(module_has_submodule(test_module, 'bad_module'))
|
||||
self.assertRaises(ImportError, import_module, 'utils_tests.test_module.bad_module')
|
||||
|
||||
# A child that doesn't exist
|
||||
self.assertFalse(module_has_submodule(test_module, 'no_such_module'))
|
||||
self.assertRaises(ImportError, import_module, 'utils_tests.test_module.no_such_module')
|
||||
|
||||
# A child that doesn't exist, but is the name of a package on the path
|
||||
self.assertFalse(module_has_submodule(test_module, 'django'))
|
||||
self.assertRaises(ImportError, import_module, 'utils_tests.test_module.django')
|
||||
|
||||
# Don't be confused by caching of import misses
|
||||
import types # causes attempted import of utils_tests.types
|
||||
self.assertFalse(module_has_submodule(sys.modules['utils_tests'], 'types'))
|
||||
|
||||
# A module which doesn't have a __path__ (so no submodules)
|
||||
self.assertFalse(module_has_submodule(test_no_submodule, 'anything'))
|
||||
self.assertRaises(ImportError, import_module,
|
||||
'utils_tests.test_no_submodule.anything')
|
||||
|
||||
class EggLoader(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.old_path = sys.path[:]
|
||||
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))
|
||||
|
||||
def tearDown(self):
|
||||
sys.path = self.old_path
|
||||
sys.path_importer_cache.clear()
|
||||
|
||||
sys.modules.pop('egg_module.sub1.sub2.bad_module', None)
|
||||
sys.modules.pop('egg_module.sub1.sub2.good_module', None)
|
||||
sys.modules.pop('egg_module.sub1.sub2', None)
|
||||
sys.modules.pop('egg_module.sub1', None)
|
||||
sys.modules.pop('egg_module.bad_module', None)
|
||||
sys.modules.pop('egg_module.good_module', None)
|
||||
sys.modules.pop('egg_module', None)
|
||||
|
||||
def test_shallow_loader(self):
|
||||
"Module existence can be tested inside eggs"
|
||||
egg_name = '%s/test_egg.egg' % self.egg_dir
|
||||
sys.path.append(egg_name)
|
||||
egg_module = import_module('egg_module')
|
||||
|
||||
# An importable child
|
||||
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
|
||||
mod = import_module('egg_module.good_module')
|
||||
self.assertEqual(mod.content, 'Good Module')
|
||||
|
||||
# A child that exists, but will generate an import error if loaded
|
||||
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
|
||||
self.assertRaises(ImportError, import_module, 'egg_module.bad_module')
|
||||
|
||||
# A child that doesn't exist
|
||||
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
|
||||
self.assertRaises(ImportError, import_module, 'egg_module.no_such_module')
|
||||
|
||||
def test_deep_loader(self):
|
||||
"Modules deep inside an egg can still be tested for existence"
|
||||
egg_name = '%s/test_egg.egg' % self.egg_dir
|
||||
sys.path.append(egg_name)
|
||||
egg_module = import_module('egg_module.sub1.sub2')
|
||||
|
||||
# An importable child
|
||||
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
|
||||
mod = import_module('egg_module.sub1.sub2.good_module')
|
||||
self.assertEqual(mod.content, 'Deep Good Module')
|
||||
|
||||
# A child that exists, but will generate an import error if loaded
|
||||
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
|
||||
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.bad_module')
|
||||
|
||||
# A child that doesn't exist
|
||||
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
|
||||
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module')
|
||||
|
||||
|
||||
class ModuleImportTestCase(unittest.TestCase):
|
||||
def test_import_by_path(self):
|
||||
cls = import_by_path(
|
||||
'django.utils.module_loading.import_by_path')
|
||||
self.assertEqual(cls, import_by_path)
|
||||
|
||||
# Test exceptions raised
|
||||
for path in ('no_dots_in_path', 'unexistent.path',
|
||||
'tests.utils_tests.unexistent'):
|
||||
self.assertRaises(ImproperlyConfigured, import_by_path, path)
|
||||
|
||||
with self.assertRaises(ImproperlyConfigured) as cm:
|
||||
import_by_path('unexistent.module.path', error_prefix="Foo")
|
||||
self.assertTrue(str(cm.exception).startswith('Foo'))
|
||||
|
||||
|
||||
class ProxyFinder(object):
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
|
||||
def find_module(self, fullname, path=None):
|
||||
tail = fullname.rsplit('.', 1)[-1]
|
||||
try:
|
||||
fd, fn, info = imp.find_module(tail, path)
|
||||
if fullname in self._cache:
|
||||
old_fd = self._cache[fullname][0]
|
||||
if old_fd:
|
||||
old_fd.close()
|
||||
self._cache[fullname] = (fd, fn, info)
|
||||
except ImportError:
|
||||
return None
|
||||
else:
|
||||
return self # this is a loader as well
|
||||
|
||||
def load_module(self, fullname):
|
||||
if fullname in sys.modules:
|
||||
return sys.modules[fullname]
|
||||
fd, fn, info = self._cache[fullname]
|
||||
try:
|
||||
return imp.load_module(fullname, fd, fn, info)
|
||||
finally:
|
||||
if fd:
|
||||
fd.close()
|
||||
|
||||
class TestFinder(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.importer = zipimporter(*args, **kwargs)
|
||||
|
||||
def find_module(self, path):
|
||||
importer = self.importer.find_module(path)
|
||||
if importer is None:
|
||||
return
|
||||
return TestLoader(importer)
|
||||
|
||||
class TestLoader(object):
|
||||
def __init__(self, importer):
|
||||
self.importer = importer
|
||||
|
||||
def load_module(self, name):
|
||||
mod = self.importer.load_module(name)
|
||||
mod.__loader__ = self
|
||||
return mod
|
||||
|
||||
class CustomLoader(EggLoader):
|
||||
"""The Custom Loader test is exactly the same as the EggLoader, but
|
||||
it uses a custom defined Loader and Finder that is intentionally
|
||||
split into two classes. Although the EggLoader combines both functions
|
||||
into one class, this isn't required.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(CustomLoader, self).setUp()
|
||||
sys.path_hooks.insert(0, TestFinder)
|
||||
sys.path_importer_cache.clear()
|
||||
|
||||
def tearDown(self):
|
||||
super(CustomLoader, self).tearDown()
|
||||
sys.path_hooks.pop(0)
|
47
tests/utils_tests/numberformat.py
Normal file
47
tests/utils_tests/numberformat.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
from unittest import TestCase
|
||||
from django.utils.numberformat import format as nformat
|
||||
from sys import float_info
|
||||
|
||||
|
||||
class TestNumberFormat(TestCase):
|
||||
|
||||
def test_format_number(self):
|
||||
self.assertEqual(nformat(1234, '.'), '1234')
|
||||
self.assertEqual(nformat(1234.2, '.'), '1234.2')
|
||||
self.assertEqual(nformat(1234, '.', decimal_pos=2), '1234.00')
|
||||
self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=','),
|
||||
'1234')
|
||||
self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=',',
|
||||
force_grouping=True), '12,34')
|
||||
self.assertEqual(nformat(-1234.33, '.', decimal_pos=1), '-1234.3')
|
||||
|
||||
def test_format_string(self):
|
||||
self.assertEqual(nformat('1234', '.'), '1234')
|
||||
self.assertEqual(nformat('1234.2', '.'), '1234.2')
|
||||
self.assertEqual(nformat('1234', '.', decimal_pos=2), '1234.00')
|
||||
self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=','),
|
||||
'1234')
|
||||
self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=',',
|
||||
force_grouping=True), '12,34')
|
||||
self.assertEqual(nformat('-1234.33', '.', decimal_pos=1), '-1234.3')
|
||||
|
||||
def test_large_number(self):
|
||||
most_max = ('{0}179769313486231570814527423731704356798070567525844996'
|
||||
'598917476803157260780028538760589558632766878171540458953'
|
||||
'514382464234321326889464182768467546703537516986049910576'
|
||||
'551282076245490090389328944075868508455133942304583236903'
|
||||
'222948165808559332123348274797826204144723168738177180919'
|
||||
'29988125040402618412485836{1}')
|
||||
most_max2 = ('{0}35953862697246314162905484746340871359614113505168999'
|
||||
'31978349536063145215600570775211791172655337563430809179'
|
||||
'07028764928468642653778928365536935093407075033972099821'
|
||||
'15310256415249098018077865788815173701691026788460916647'
|
||||
'38064458963316171186642466965495956524082894463374763543'
|
||||
'61838599762500808052368249716736')
|
||||
int_max = int(float_info.max)
|
||||
self.assertEqual(nformat(int_max, '.'), most_max.format('', '8'))
|
||||
self.assertEqual(nformat(int_max + 1, '.'), most_max.format('', '9'))
|
||||
self.assertEqual(nformat(int_max * 2, '.'), most_max2.format(''))
|
||||
self.assertEqual(nformat(0 - int_max, '.'), most_max.format('-', '8'))
|
||||
self.assertEqual(nformat(-1 - int_max, '.'), most_max.format('-', '9'))
|
||||
self.assertEqual(nformat(-2 * int_max, '.'), most_max2.format('-'))
|
26
tests/utils_tests/os_utils.py
Normal file
26
tests/utils_tests/os_utils.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import os
|
||||
|
||||
from django.utils import unittest
|
||||
from django.utils._os import safe_join
|
||||
|
||||
|
||||
class SafeJoinTests(unittest.TestCase):
|
||||
def test_base_path_ends_with_sep(self):
|
||||
drive, path = os.path.splitdrive(safe_join("/abc/", "abc"))
|
||||
self.assertEqual(
|
||||
path,
|
||||
"{0}abc{0}abc".format(os.path.sep)
|
||||
)
|
||||
|
||||
def test_root_path(self):
|
||||
drive, path = os.path.splitdrive(safe_join("/", "path"))
|
||||
self.assertEqual(
|
||||
path,
|
||||
"{0}path".format(os.path.sep),
|
||||
)
|
||||
|
||||
drive, path = os.path.splitdrive(safe_join("/", ""))
|
||||
self.assertEqual(
|
||||
path,
|
||||
os.path.sep,
|
||||
)
|
50
tests/utils_tests/regex_helper.py
Normal file
50
tests/utils_tests/regex_helper.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils import regex_helper
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class NormalizeTests(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
pattern = r""
|
||||
expected = [('', [])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_escape(self):
|
||||
pattern = r"\\\^\$\.\|\?\*\+\(\)\["
|
||||
expected = [('\\^$.|?*+()[', [])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_group_positional(self):
|
||||
pattern = r"(.*)-(.+)"
|
||||
expected = [('%(_0)s-%(_1)s', ['_0', '_1'])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_group_ignored(self):
|
||||
pattern = r"(?i)(?L)(?m)(?s)(?u)(?#)"
|
||||
expected = [('', [])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_group_noncapturing(self):
|
||||
pattern = r"(?:non-capturing)"
|
||||
expected = [('non-capturing', [])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_group_named(self):
|
||||
pattern = r"(?P<first_group_name>.*)-(?P<second_group_name>.*)"
|
||||
expected = [('%(first_group_name)s-%(second_group_name)s',
|
||||
['first_group_name', 'second_group_name'])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_group_backreference(self):
|
||||
pattern = r"(?P<first_group_name>.*)-(?P=first_group_name)"
|
||||
expected = [('%(first_group_name)s-%(first_group_name)s',
|
||||
['first_group_name'])]
|
||||
result = regex_helper.normalize(pattern)
|
||||
self.assertEqual(result, expected)
|
123
tests/utils_tests/simplelazyobject.py
Normal file
123
tests/utils_tests/simplelazyobject.py
Normal file
|
@ -0,0 +1,123 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import copy
|
||||
import pickle
|
||||
|
||||
from django.test.utils import str_prefix
|
||||
from django.utils import six
|
||||
from django.utils.unittest import TestCase
|
||||
from django.utils.functional import SimpleLazyObject, empty
|
||||
|
||||
|
||||
class _ComplexObject(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
if six.PY3:
|
||||
def __bytes__(self):
|
||||
return ("I am _ComplexObject(%r)" % self.name).encode("utf-8")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
else:
|
||||
def __str__(self):
|
||||
return b"I am _ComplexObject(%r)" % str(self.name)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return "_ComplexObject(%r)" % self.name
|
||||
|
||||
|
||||
complex_object = lambda: _ComplexObject("joe")
|
||||
|
||||
|
||||
class TestUtilsSimpleLazyObject(TestCase):
|
||||
"""
|
||||
Tests for SimpleLazyObject
|
||||
"""
|
||||
# Note that concrete use cases for SimpleLazyObject are also found in the
|
||||
# auth context processor tests (unless the implementation of that function
|
||||
# is changed).
|
||||
|
||||
def test_equality(self):
|
||||
self.assertEqual(complex_object(), SimpleLazyObject(complex_object))
|
||||
self.assertEqual(SimpleLazyObject(complex_object), complex_object())
|
||||
|
||||
def test_hash(self):
|
||||
# hash() equality would not be true for many objects, but it should be
|
||||
# for _ComplexObject
|
||||
self.assertEqual(hash(complex_object()),
|
||||
hash(SimpleLazyObject(complex_object)))
|
||||
|
||||
def test_repr(self):
|
||||
# For debugging, it will really confuse things if there is no clue that
|
||||
# SimpleLazyObject is actually a proxy object. So we don't
|
||||
# proxy __repr__
|
||||
self.assertTrue("SimpleLazyObject" in repr(SimpleLazyObject(complex_object)))
|
||||
|
||||
def test_bytes(self):
|
||||
self.assertEqual(b"I am _ComplexObject('joe')",
|
||||
bytes(SimpleLazyObject(complex_object)))
|
||||
|
||||
def test_text(self):
|
||||
self.assertEqual("joe", six.text_type(SimpleLazyObject(complex_object)))
|
||||
|
||||
def test_class(self):
|
||||
# This is important for classes that use __class__ in things like
|
||||
# equality tests.
|
||||
self.assertEqual(_ComplexObject, SimpleLazyObject(complex_object).__class__)
|
||||
|
||||
def test_deepcopy(self):
|
||||
# Check that we *can* do deep copy, and that it returns the right
|
||||
# objects.
|
||||
|
||||
# First, for an unevaluated SimpleLazyObject
|
||||
s = SimpleLazyObject(complex_object)
|
||||
self.assertIs(s._wrapped, empty)
|
||||
s2 = copy.deepcopy(s)
|
||||
# something has gone wrong is s is evaluated
|
||||
self.assertIs(s._wrapped, empty)
|
||||
self.assertEqual(s2, complex_object())
|
||||
|
||||
# Second, for an evaluated SimpleLazyObject
|
||||
name = s.name # evaluate
|
||||
self.assertIsNot(s._wrapped, empty)
|
||||
s3 = copy.deepcopy(s)
|
||||
self.assertEqual(s3, complex_object())
|
||||
|
||||
|
||||
def test_none(self):
|
||||
i = [0]
|
||||
def f():
|
||||
i[0] += 1
|
||||
return None
|
||||
|
||||
x = SimpleLazyObject(f)
|
||||
self.assertEqual(str(x), "None")
|
||||
self.assertEqual(i, [1])
|
||||
self.assertEqual(str(x), "None")
|
||||
self.assertEqual(i, [1])
|
||||
|
||||
def test_bool(self):
|
||||
x = SimpleLazyObject(lambda: 3)
|
||||
self.assertTrue(x)
|
||||
x = SimpleLazyObject(lambda: 0)
|
||||
self.assertFalse(x)
|
||||
|
||||
def test_pickle_complex(self):
|
||||
# See ticket #16563
|
||||
x = SimpleLazyObject(complex_object)
|
||||
pickled = pickle.dumps(x)
|
||||
unpickled = pickle.loads(pickled)
|
||||
self.assertEqual(unpickled, x)
|
||||
self.assertEqual(six.text_type(unpickled), six.text_type(x))
|
||||
self.assertEqual(unpickled.name, x.name)
|
157
tests/utils_tests/termcolors.py
Normal file
157
tests/utils_tests/termcolors.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
from django.utils import unittest
|
||||
from django.utils.termcolors import (parse_color_setting, PALETTES,
|
||||
DEFAULT_PALETTE, LIGHT_PALETTE, DARK_PALETTE, NOCOLOR_PALETTE, colorize)
|
||||
|
||||
|
||||
class TermColorTests(unittest.TestCase):
|
||||
|
||||
def test_empty_string(self):
|
||||
self.assertEqual(parse_color_setting(''), PALETTES[DEFAULT_PALETTE])
|
||||
|
||||
def test_simple_palette(self):
|
||||
self.assertEqual(parse_color_setting('light'), PALETTES[LIGHT_PALETTE])
|
||||
self.assertEqual(parse_color_setting('dark'), PALETTES[DARK_PALETTE])
|
||||
self.assertEqual(parse_color_setting('nocolor'), None)
|
||||
|
||||
def test_fg(self):
|
||||
self.assertEqual(parse_color_setting('error=green'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
|
||||
def test_fg_bg(self):
|
||||
self.assertEqual(parse_color_setting('error=green/blue'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg':'blue'}))
|
||||
|
||||
def test_fg_opts(self):
|
||||
self.assertEqual(parse_color_setting('error=green,blink'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'opts': ('blink',)}))
|
||||
self.assertEqual(parse_color_setting('error=green,bold,blink'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'opts': ('blink','bold')}))
|
||||
|
||||
def test_fg_bg_opts(self):
|
||||
self.assertEqual(parse_color_setting('error=green/blue,blink'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg':'blue', 'opts': ('blink',)}))
|
||||
self.assertEqual(parse_color_setting('error=green/blue,bold,blink'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg':'blue', 'opts': ('blink','bold')}))
|
||||
|
||||
def test_override_palette(self):
|
||||
self.assertEqual(parse_color_setting('light;error=green'),
|
||||
dict(PALETTES[LIGHT_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
|
||||
def test_override_nocolor(self):
|
||||
self.assertEqual(parse_color_setting('nocolor;error=green'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg': 'green'}))
|
||||
|
||||
def test_reverse_override(self):
|
||||
self.assertEqual(parse_color_setting('error=green;light'), PALETTES[LIGHT_PALETTE])
|
||||
|
||||
def test_multiple_roles(self):
|
||||
self.assertEqual(parse_color_setting('error=green;sql_field=blue'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'},
|
||||
SQL_FIELD={'fg':'blue'}))
|
||||
|
||||
def test_override_with_multiple_roles(self):
|
||||
self.assertEqual(parse_color_setting('light;error=green;sql_field=blue'),
|
||||
dict(PALETTES[LIGHT_PALETTE],
|
||||
ERROR={'fg':'green'},
|
||||
SQL_FIELD={'fg':'blue'}))
|
||||
|
||||
def test_empty_definition(self):
|
||||
self.assertEqual(parse_color_setting(';'), None)
|
||||
self.assertEqual(parse_color_setting('light;'), PALETTES[LIGHT_PALETTE])
|
||||
self.assertEqual(parse_color_setting(';;;'), None)
|
||||
|
||||
def test_empty_options(self):
|
||||
self.assertEqual(parse_color_setting('error=green,'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('error=green,,,'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('error=green,,blink,,'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'opts': ('blink',)}))
|
||||
|
||||
def test_bad_palette(self):
|
||||
self.assertEqual(parse_color_setting('unknown'), None)
|
||||
|
||||
def test_bad_role(self):
|
||||
self.assertEqual(parse_color_setting('unknown='), None)
|
||||
self.assertEqual(parse_color_setting('unknown=green'), None)
|
||||
self.assertEqual(parse_color_setting('unknown=green;sql_field=blue'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
SQL_FIELD={'fg':'blue'}))
|
||||
|
||||
def test_bad_color(self):
|
||||
self.assertEqual(parse_color_setting('error='), None)
|
||||
self.assertEqual(parse_color_setting('error=;sql_field=blue'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
SQL_FIELD={'fg':'blue'}))
|
||||
self.assertEqual(parse_color_setting('error=unknown'), None)
|
||||
self.assertEqual(parse_color_setting('error=unknown;sql_field=blue'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
SQL_FIELD={'fg':'blue'}))
|
||||
self.assertEqual(parse_color_setting('error=green/unknown'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('error=green/blue/something'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg': 'blue'}))
|
||||
self.assertEqual(parse_color_setting('error=green/blue/something,blink'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg': 'blue', 'opts': ('blink',)}))
|
||||
|
||||
def test_bad_option(self):
|
||||
self.assertEqual(parse_color_setting('error=green,unknown'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('error=green,unknown,blink'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'opts': ('blink',)}))
|
||||
|
||||
def test_role_case(self):
|
||||
self.assertEqual(parse_color_setting('ERROR=green'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('eRrOr=green'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
|
||||
def test_color_case(self):
|
||||
self.assertEqual(parse_color_setting('error=GREEN'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('error=GREEN/BLUE'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg':'blue'}))
|
||||
|
||||
self.assertEqual(parse_color_setting('error=gReEn'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green'}))
|
||||
self.assertEqual(parse_color_setting('error=gReEn/bLuE'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'bg':'blue'}))
|
||||
|
||||
def test_opts_case(self):
|
||||
self.assertEqual(parse_color_setting('error=green,BLINK'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'opts': ('blink',)}))
|
||||
|
||||
self.assertEqual(parse_color_setting('error=green,bLiNk'),
|
||||
dict(PALETTES[NOCOLOR_PALETTE],
|
||||
ERROR={'fg':'green', 'opts': ('blink',)}))
|
||||
|
||||
def test_colorize_empty_text(self):
|
||||
self.assertEqual(colorize(text=None), '\x1b[m\x1b[0m')
|
||||
self.assertEqual(colorize(text=''), '\x1b[m\x1b[0m')
|
||||
|
||||
self.assertEqual(colorize(text=None, opts=('noreset')), '\x1b[m')
|
||||
self.assertEqual(colorize(text='', opts=('noreset')), '\x1b[m')
|
0
tests/utils_tests/test_module/__init__.py
Normal file
0
tests/utils_tests/test_module/__init__.py
Normal file
3
tests/utils_tests/test_module/bad_module.py
Normal file
3
tests/utils_tests/test_module/bad_module.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
import a_package_name_that_does_not_exist
|
||||
|
||||
content = 'Bad Module'
|
1
tests/utils_tests/test_module/good_module.py
Normal file
1
tests/utils_tests/test_module/good_module.py
Normal file
|
@ -0,0 +1 @@
|
|||
content = 'Good Module'
|
1
tests/utils_tests/test_no_submodule.py
Normal file
1
tests/utils_tests/test_no_submodule.py
Normal file
|
@ -0,0 +1 @@
|
|||
# Used to test for modules which don't have submodules.
|
33
tests/utils_tests/tests.py
Normal file
33
tests/utils_tests/tests.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Tests for django.utils.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from .archive import TestBzip2Tar, TestGzipTar, TestTar, TestZip
|
||||
from .baseconv import TestBaseConv
|
||||
from .checksums import TestUtilsChecksums
|
||||
from .crypto import TestUtilsCryptoMisc, TestUtilsCryptoPBKDF2
|
||||
from .datastructures import (DictWrapperTests, ImmutableListTests,
|
||||
MergeDictTests, MultiValueDictTests, SortedDictTests)
|
||||
from .dateformat import DateFormatTests
|
||||
from .dateparse import DateParseTests
|
||||
from .datetime_safe import DatetimeTests
|
||||
from .decorators import DecoratorFromMiddlewareTests
|
||||
from .encoding import TestEncodingUtils
|
||||
from .feedgenerator import FeedgeneratorTest
|
||||
from .functional import FunctionalTestCase
|
||||
from .html import TestUtilsHtml
|
||||
from .http import TestUtilsHttp, ETagProcessingTests, HttpDateProcessingTests
|
||||
from .ipv6 import TestUtilsIPv6
|
||||
from .jslex import JsToCForGettextTest, JsTokensTest
|
||||
from .module_loading import (CustomLoader, DefaultLoader, EggLoader,
|
||||
ModuleImportTestCase)
|
||||
from .numberformat import TestNumberFormat
|
||||
from .os_utils import SafeJoinTests
|
||||
from .regex_helper import NormalizeTests
|
||||
from .simplelazyobject import TestUtilsSimpleLazyObject
|
||||
from .termcolors import TermColorTests
|
||||
from .text import TestUtilsText
|
||||
from .timesince import TimesinceTests
|
||||
from .timezone import TimezoneTests
|
||||
from .tzinfo import TzinfoTests
|
108
tests/utils_tests/text.py
Normal file
108
tests/utils_tests/text.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import warnings
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils import text
|
||||
|
||||
class TestUtilsText(SimpleTestCase):
|
||||
|
||||
def test_truncate_chars(self):
|
||||
truncator = text.Truncator(
|
||||
'The quick brown fox jumped over the lazy dog.'
|
||||
)
|
||||
self.assertEqual('The quick brown fox jumped over the lazy dog.',
|
||||
truncator.chars(100)),
|
||||
self.assertEqual('The quick brown fox ...',
|
||||
truncator.chars(23)),
|
||||
self.assertEqual('The quick brown fo.....',
|
||||
truncator.chars(23, '.....')),
|
||||
|
||||
# Ensure that we normalize our unicode data first
|
||||
nfc = text.Truncator('o\xfco\xfco\xfco\xfc')
|
||||
nfd = text.Truncator('ou\u0308ou\u0308ou\u0308ou\u0308')
|
||||
self.assertEqual('oüoüoüoü', nfc.chars(8))
|
||||
self.assertEqual('oüoüoüoü', nfd.chars(8))
|
||||
self.assertEqual('oü...', nfc.chars(5))
|
||||
self.assertEqual('oü...', nfd.chars(5))
|
||||
|
||||
# Ensure the final length is calculated correctly when there are
|
||||
# combining characters with no precomposed form, and that combining
|
||||
# characters are not split up.
|
||||
truncator = text.Truncator('-B\u030AB\u030A----8')
|
||||
self.assertEqual('-B\u030A...', truncator.chars(5))
|
||||
self.assertEqual('-B\u030AB\u030A-...', truncator.chars(7))
|
||||
self.assertEqual('-B\u030AB\u030A----8', truncator.chars(8))
|
||||
|
||||
# Ensure the length of the end text is correctly calculated when it
|
||||
# contains combining characters with no precomposed form.
|
||||
truncator = text.Truncator('-----')
|
||||
self.assertEqual('---B\u030A', truncator.chars(4, 'B\u030A'))
|
||||
self.assertEqual('-----', truncator.chars(5, 'B\u030A'))
|
||||
|
||||
# Make a best effort to shorten to the desired length, but requesting
|
||||
# a length shorter than the ellipsis shouldn't break
|
||||
self.assertEqual('...', text.Truncator('asdf').chars(1))
|
||||
|
||||
def test_truncate_words(self):
|
||||
truncator = text.Truncator('The quick brown fox jumped over the lazy '
|
||||
'dog.')
|
||||
self.assertEqual('The quick brown fox jumped over the lazy dog.',
|
||||
truncator.words(10))
|
||||
self.assertEqual('The quick brown fox...', truncator.words(4))
|
||||
self.assertEqual('The quick brown fox[snip]',
|
||||
truncator.words(4, '[snip]'))
|
||||
|
||||
def test_truncate_html_words(self):
|
||||
truncator = text.Truncator('<p id="par"><strong><em>The quick brown fox'
|
||||
' jumped over the lazy dog.</em></strong></p>')
|
||||
self.assertEqual('<p id="par"><strong><em>The quick brown fox jumped over'
|
||||
' the lazy dog.</em></strong></p>', truncator.words(10, html=True))
|
||||
self.assertEqual('<p id="par"><strong><em>The quick brown fox...</em>'
|
||||
'</strong></p>', truncator.words(4, html=True))
|
||||
self.assertEqual('<p id="par"><strong><em>The quick brown fox....</em>'
|
||||
'</strong></p>', truncator.words(4, '....', html=True))
|
||||
self.assertEqual('<p id="par"><strong><em>The quick brown fox</em>'
|
||||
'</strong></p>', truncator.words(4, '', html=True))
|
||||
|
||||
# Test with new line inside tag
|
||||
truncator = text.Truncator('<p>The quick <a href="xyz.html"\n'
|
||||
'id="mylink">brown fox</a> jumped over the lazy dog.</p>')
|
||||
self.assertEqual('<p>The quick <a href="xyz.html"\n'
|
||||
'id="mylink">brown...</a></p>', truncator.words(3, '...', html=True))
|
||||
|
||||
# Test self-closing tags
|
||||
truncator = text.Truncator('<br/>The <hr />quick brown fox jumped over'
|
||||
' the lazy dog.')
|
||||
self.assertEqual('<br/>The <hr />quick brown...',
|
||||
truncator.words(3, '...', html=True ))
|
||||
truncator = text.Truncator('<br>The <hr/>quick <em>brown fox</em> '
|
||||
'jumped over the lazy dog.')
|
||||
self.assertEqual('<br>The <hr/>quick <em>brown...</em>',
|
||||
truncator.words(3, '...', html=True ))
|
||||
|
||||
def test_wrap(self):
|
||||
digits = '1234 67 9'
|
||||
self.assertEqual(text.wrap(digits, 100), '1234 67 9')
|
||||
self.assertEqual(text.wrap(digits, 9), '1234 67 9')
|
||||
self.assertEqual(text.wrap(digits, 8), '1234 67\n9')
|
||||
|
||||
self.assertEqual(text.wrap('short\na long line', 7),
|
||||
'short\na long\nline')
|
||||
|
||||
self.assertEqual(text.wrap('do-not-break-long-words please? ok', 8),
|
||||
'do-not-break-long-words\nplease?\nok')
|
||||
|
||||
long_word = 'l%sng' % ('o' * 20)
|
||||
self.assertEqual(text.wrap(long_word, 20), long_word)
|
||||
self.assertEqual(text.wrap('a %s word' % long_word, 10),
|
||||
'a\n%s\nword' % long_word)
|
||||
|
||||
def test_slugify(self):
|
||||
items = (
|
||||
('Hello, World!', 'hello-world'),
|
||||
('spam & eggs', 'spam-eggs'),
|
||||
)
|
||||
for value, output in items:
|
||||
self.assertEqual(text.slugify(value), output)
|
124
tests/utils_tests/timesince.py
Normal file
124
tests/utils_tests/timesince.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
import unittest
|
||||
|
||||
from django.utils.timesince import timesince, timeuntil
|
||||
from django.utils.tzinfo import LocalTimezone, FixedOffset
|
||||
|
||||
class TimesinceTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.t = datetime.datetime(2007, 8, 14, 13, 46, 0)
|
||||
self.onemicrosecond = datetime.timedelta(microseconds=1)
|
||||
self.onesecond = datetime.timedelta(seconds=1)
|
||||
self.oneminute = datetime.timedelta(minutes=1)
|
||||
self.onehour = datetime.timedelta(hours=1)
|
||||
self.oneday = datetime.timedelta(days=1)
|
||||
self.oneweek = datetime.timedelta(days=7)
|
||||
self.onemonth = datetime.timedelta(days=30)
|
||||
self.oneyear = datetime.timedelta(days=365)
|
||||
|
||||
def test_equal_datetimes(self):
|
||||
""" equal datetimes. """
|
||||
self.assertEqual(timesince(self.t, self.t), '0 minutes')
|
||||
|
||||
def test_ignore_microseconds_and_seconds(self):
|
||||
""" Microseconds and seconds are ignored. """
|
||||
self.assertEqual(timesince(self.t, self.t+self.onemicrosecond),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t+self.onesecond),
|
||||
'0 minutes')
|
||||
|
||||
def test_other_units(self):
|
||||
""" Test other units. """
|
||||
self.assertEqual(timesince(self.t, self.t+self.oneminute),
|
||||
'1 minute')
|
||||
self.assertEqual(timesince(self.t, self.t+self.onehour), '1 hour')
|
||||
self.assertEqual(timesince(self.t, self.t+self.oneday), '1 day')
|
||||
self.assertEqual(timesince(self.t, self.t+self.oneweek), '1 week')
|
||||
self.assertEqual(timesince(self.t, self.t+self.onemonth),
|
||||
'1 month')
|
||||
self.assertEqual(timesince(self.t, self.t+self.oneyear), '1 year')
|
||||
|
||||
def test_multiple_units(self):
|
||||
""" Test multiple units. """
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t+2*self.oneday+6*self.onehour), '2 days, 6 hours')
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t+2*self.oneweek+2*self.oneday), '2 weeks, 2 days')
|
||||
|
||||
def test_display_first_unit(self):
|
||||
"""
|
||||
If the two differing units aren't adjacent, only the first unit is
|
||||
displayed.
|
||||
"""
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t+2*self.oneweek+3*self.onehour+4*self.oneminute),
|
||||
'2 weeks')
|
||||
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t+4*self.oneday+5*self.oneminute), '4 days')
|
||||
|
||||
def test_display_second_before_first(self):
|
||||
"""
|
||||
When the second date occurs before the first, we should always
|
||||
get 0 minutes.
|
||||
"""
|
||||
self.assertEqual(timesince(self.t, self.t-self.onemicrosecond),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.onesecond),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.oneminute),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.onehour),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.oneday),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.oneweek),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.onemonth),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t, self.t-self.oneyear),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t-2*self.oneday-6*self.onehour), '0 minutes')
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t-2*self.oneweek-2*self.oneday), '0 minutes')
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t-2*self.oneweek-3*self.onehour-4*self.oneminute),
|
||||
'0 minutes')
|
||||
self.assertEqual(timesince(self.t,
|
||||
self.t-4*self.oneday-5*self.oneminute), '0 minutes')
|
||||
|
||||
def test_different_timezones(self):
|
||||
""" When using two different timezones. """
|
||||
now = datetime.datetime.now()
|
||||
now_tz = datetime.datetime.now(LocalTimezone(now))
|
||||
now_tz_i = datetime.datetime.now(FixedOffset((3 * 60) + 15))
|
||||
|
||||
self.assertEqual(timesince(now), '0 minutes')
|
||||
self.assertEqual(timesince(now_tz), '0 minutes')
|
||||
self.assertEqual(timeuntil(now_tz, now_tz_i), '0 minutes')
|
||||
|
||||
def test_date_objects(self):
|
||||
""" Both timesince and timeuntil should work on date objects (#17937). """
|
||||
today = datetime.date.today()
|
||||
self.assertEqual(timesince(today + self.oneday), '0 minutes')
|
||||
self.assertEqual(timeuntil(today - self.oneday), '0 minutes')
|
||||
|
||||
def test_both_date_objects(self):
|
||||
""" Timesince should work with both date objects (#9672) """
|
||||
today = datetime.date.today()
|
||||
self.assertEqual(timeuntil(today + self.oneday, today), '1 day')
|
||||
self.assertEqual(timeuntil(today - self.oneday, today), '0 minutes')
|
||||
self.assertEqual(timeuntil(today + self.oneweek, today), '1 week')
|
||||
|
||||
def test_naive_datetime_with_tzinfo_attribute(self):
|
||||
class naive(datetime.tzinfo):
|
||||
def utcoffset(self, dt):
|
||||
return None
|
||||
future = datetime.datetime(2080, 1, 1, tzinfo=naive())
|
||||
self.assertEqual(timesince(future), '0 minutes')
|
||||
past = datetime.datetime(1980, 1, 1, tzinfo=naive())
|
||||
self.assertEqual(timeuntil(past), '0 minutes')
|
63
tests/utils_tests/timezone.py
Normal file
63
tests/utils_tests/timezone.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import copy
|
||||
import datetime
|
||||
import pickle
|
||||
from django.test.utils import override_settings
|
||||
from django.utils import timezone
|
||||
from django.utils.tzinfo import FixedOffset
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
EAT = FixedOffset(180) # Africa/Nairobi
|
||||
ICT = FixedOffset(420) # Asia/Bangkok
|
||||
|
||||
|
||||
class TimezoneTests(unittest.TestCase):
|
||||
|
||||
def test_localtime(self):
|
||||
now = datetime.datetime.utcnow().replace(tzinfo=timezone.utc)
|
||||
local_tz = timezone.LocalTimezone()
|
||||
local_now = timezone.localtime(now, local_tz)
|
||||
self.assertEqual(local_now.tzinfo, local_tz)
|
||||
|
||||
def test_now(self):
|
||||
with override_settings(USE_TZ=True):
|
||||
self.assertTrue(timezone.is_aware(timezone.now()))
|
||||
with override_settings(USE_TZ=False):
|
||||
self.assertTrue(timezone.is_naive(timezone.now()))
|
||||
|
||||
def test_override(self):
|
||||
default = timezone.get_default_timezone()
|
||||
try:
|
||||
timezone.activate(ICT)
|
||||
|
||||
with timezone.override(EAT):
|
||||
self.assertIs(EAT, timezone.get_current_timezone())
|
||||
self.assertIs(ICT, timezone.get_current_timezone())
|
||||
|
||||
with timezone.override(None):
|
||||
self.assertIs(default, timezone.get_current_timezone())
|
||||
self.assertIs(ICT, timezone.get_current_timezone())
|
||||
|
||||
timezone.deactivate()
|
||||
|
||||
with timezone.override(EAT):
|
||||
self.assertIs(EAT, timezone.get_current_timezone())
|
||||
self.assertIs(default, timezone.get_current_timezone())
|
||||
|
||||
with timezone.override(None):
|
||||
self.assertIs(default, timezone.get_current_timezone())
|
||||
self.assertIs(default, timezone.get_current_timezone())
|
||||
finally:
|
||||
timezone.deactivate()
|
||||
|
||||
def test_copy(self):
|
||||
self.assertIsInstance(copy.copy(timezone.UTC()), timezone.UTC)
|
||||
self.assertIsInstance(copy.copy(timezone.LocalTimezone()), timezone.LocalTimezone)
|
||||
|
||||
def test_deepcopy(self):
|
||||
self.assertIsInstance(copy.deepcopy(timezone.UTC()), timezone.UTC)
|
||||
self.assertIsInstance(copy.deepcopy(timezone.LocalTimezone()), timezone.LocalTimezone)
|
||||
|
||||
def test_pickling_unpickling(self):
|
||||
self.assertIsInstance(pickle.loads(pickle.dumps(timezone.UTC())), timezone.UTC)
|
||||
self.assertIsInstance(pickle.loads(pickle.dumps(timezone.LocalTimezone())), timezone.LocalTimezone)
|
79
tests/utils_tests/tzinfo.py
Normal file
79
tests/utils_tests/tzinfo.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
import copy
|
||||
import datetime
|
||||
import os
|
||||
import pickle
|
||||
import time
|
||||
from django.utils.tzinfo import FixedOffset, LocalTimezone
|
||||
from django.utils import unittest
|
||||
|
||||
class TzinfoTests(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.old_TZ = os.environ.get('TZ')
|
||||
os.environ['TZ'] = 'US/Eastern'
|
||||
|
||||
try:
|
||||
# Check if a timezone has been set
|
||||
time.tzset()
|
||||
cls.tz_tests = True
|
||||
except AttributeError:
|
||||
# No timezone available. Don't run the tests that require a TZ
|
||||
cls.tz_tests = False
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.old_TZ is None:
|
||||
del os.environ['TZ']
|
||||
else:
|
||||
os.environ['TZ'] = cls.old_TZ
|
||||
|
||||
# Cleanup - force re-evaluation of TZ environment variable.
|
||||
if cls.tz_tests:
|
||||
time.tzset()
|
||||
|
||||
def test_fixedoffset(self):
|
||||
self.assertEqual(repr(FixedOffset(0)), '+0000')
|
||||
self.assertEqual(repr(FixedOffset(60)), '+0100')
|
||||
self.assertEqual(repr(FixedOffset(-60)), '-0100')
|
||||
self.assertEqual(repr(FixedOffset(280)), '+0440')
|
||||
self.assertEqual(repr(FixedOffset(-280)), '-0440')
|
||||
self.assertEqual(repr(FixedOffset(-78.4)), '-0118')
|
||||
self.assertEqual(repr(FixedOffset(78.4)), '+0118')
|
||||
self.assertEqual(repr(FixedOffset(-5.5*60)), '-0530')
|
||||
self.assertEqual(repr(FixedOffset(5.5*60)), '+0530')
|
||||
self.assertEqual(repr(FixedOffset(-.5*60)), '-0030')
|
||||
self.assertEqual(repr(FixedOffset(.5*60)), '+0030')
|
||||
|
||||
def test_16899(self):
|
||||
if not self.tz_tests:
|
||||
return
|
||||
ts = 1289106000
|
||||
# Midnight at the end of DST in US/Eastern: 2010-11-07T05:00:00Z
|
||||
dt = datetime.datetime.utcfromtimestamp(ts)
|
||||
# US/Eastern -- we force its representation to "EST"
|
||||
tz = LocalTimezone(dt + datetime.timedelta(days=1))
|
||||
self.assertEqual(
|
||||
repr(datetime.datetime.fromtimestamp(ts - 3600, tz)),
|
||||
'datetime.datetime(2010, 11, 7, 0, 0, tzinfo=EST)')
|
||||
self.assertEqual(
|
||||
repr(datetime.datetime.fromtimestamp(ts, tz)),
|
||||
'datetime.datetime(2010, 11, 7, 1, 0, tzinfo=EST)')
|
||||
self.assertEqual(
|
||||
repr(datetime.datetime.fromtimestamp(ts + 3600, tz)),
|
||||
'datetime.datetime(2010, 11, 7, 1, 0, tzinfo=EST)')
|
||||
|
||||
def test_copy(self):
|
||||
now = datetime.datetime.now()
|
||||
self.assertIsInstance(copy.copy(FixedOffset(90)), FixedOffset)
|
||||
self.assertIsInstance(copy.copy(LocalTimezone(now)), LocalTimezone)
|
||||
|
||||
def test_deepcopy(self):
|
||||
now = datetime.datetime.now()
|
||||
self.assertIsInstance(copy.deepcopy(FixedOffset(90)), FixedOffset)
|
||||
self.assertIsInstance(copy.deepcopy(LocalTimezone(now)), LocalTimezone)
|
||||
|
||||
def test_pickling_unpickling(self):
|
||||
now = datetime.datetime.now()
|
||||
self.assertIsInstance(pickle.loads(pickle.dumps(FixedOffset(90))), FixedOffset)
|
||||
self.assertIsInstance(pickle.loads(pickle.dumps(LocalTimezone(now))), LocalTimezone)
|
Loading…
Add table
Add a link
Reference in a new issue