Source code for tests.test_converters

import warnings
import pytest
from datetime import datetime, date
from decimal import Decimal

from dateutil.tz import tzutc

from privex import helpers
from tests.base import PrivexBaseCase

JAN_2019_1_MID = datetime(2019, 1, 1, 0, 0, 0, 0, tzinfo=tzutc())
JAN_2019_1_MID_DATE = date(2019, 1, 1)


[docs]class TestConvertDate(PrivexBaseCase): """Test cases for date/time converter functions/classes""" ###### # Test convert_datetime with strings containing full dates + times in ISO format + common formats ######
[docs] def test_convert_date_str(self): """Test converting ISO date string into datetime""" self.assertEqual(helpers.convert_datetime("2019-01-01T00:00:00Z"), JAN_2019_1_MID)
[docs] def test_convert_date_str_2(self): """Test converting no-timezone ISO date string into datetime""" self.assertEqual(helpers.convert_datetime("2019-01-01 00:00:00.0000"), JAN_2019_1_MID)
[docs] def test_convert_date_str_3(self): """Test converting no-timezone human date string (spaces) into datetime""" self.assertEqual(helpers.convert_datetime("Jan 1 2019 00:00:00.0000"), JAN_2019_1_MID)
[docs] def test_convert_date_str_4(self): """Test converting no-timezone human date string (slashes) into datetime""" self.assertEqual(helpers.convert_datetime("01/JAN/2019 00:00:00.0000"), JAN_2019_1_MID)
def test_convert_date_bytes(self): """Test converting ISO date byte-string into datetime""" self.assertEqual(helpers.convert_datetime(b"2019-01-01T00:00:00Z"), JAN_2019_1_MID) ###### # Test convert_datetime / convert_unixtime_datetime with epoch times in various formats (string, int, millisecond-epoch) ######
[docs] def test_convert_date_int(self): """Test :func:`.convert_datetime` - converting integer unix time into datetime""" self.assertEqual(helpers.convert_datetime(1546300800), JAN_2019_1_MID)
[docs] def test_convert_date_int_str(self): """Test :func:`.convert_datetime` - converting string unix time into datetime""" self.assertEqual(helpers.convert_datetime('1546300800'), JAN_2019_1_MID)
[docs] def test_convert_date_int_ms(self): """Test :func:`.convert_datetime` - converting integer unix time (milliseconds) into datetime""" self.assertEqual(helpers.convert_datetime(1546300800 * 1000), JAN_2019_1_MID)
[docs] def test_convert_unixtime_int(self): """Test :func:`.convert_unixtime_datetime` - converting integer unix time into datetime""" self.assertEqual(helpers.convert_unixtime_datetime(1546300800), JAN_2019_1_MID)
[docs] def test_convert_unixtime_int_str(self): """Test :func:`.convert_unixtime_datetime` - converting string unix time into datetime""" self.assertEqual(helpers.convert_unixtime_datetime('1546300800'), JAN_2019_1_MID)
[docs] def test_convert_unixtime_int_ms(self): """Test :func:`.convert_datetime` - converting integer unix time (milliseconds) into datetime""" self.assertEqual(helpers.convert_unixtime_datetime(1546300800 * 1000), JAN_2019_1_MID)
###### # Test convert_datetime with :class:`.date` objects and string/bytes dates (no times) ###### def test_convert_date_datetime(self): """Test converting :class:`.datetime` object into datetime""" self.assertEqual(helpers.convert_datetime(JAN_2019_1_MID), JAN_2019_1_MID) def test_convert_date_date(self): """Test converting :class:`.date` object into datetime""" self.assertEqual(helpers.convert_datetime(JAN_2019_1_MID_DATE), JAN_2019_1_MID) def test_convert_date_date_str(self): """Test converting :class:`.date` object's string value into datetime""" self.assertEqual(helpers.convert_datetime(str(JAN_2019_1_MID_DATE)), JAN_2019_1_MID) def test_convert_date_date_str_2(self): """Test converting a flat date string into datetime""" self.assertEqual(helpers.convert_datetime("2019-01-01"), JAN_2019_1_MID) def test_convert_date_date_str_3(self): """Test converting a human date string into datetime""" self.assertEqual(helpers.convert_datetime("Jan 1 2019"), JAN_2019_1_MID) def test_convert_date_date_str_4(self): """Test converting a human date string (slashes) into datetime""" self.assertEqual(helpers.convert_datetime("01/JAN/2019"), JAN_2019_1_MID) def test_convert_date_date_bytes(self): """Test converting :class:`.date` object's byte-string value into datetime""" self.assertEqual(helpers.convert_datetime(str(JAN_2019_1_MID_DATE).encode('utf-8')), JAN_2019_1_MID)
[docs]class TestConvertGeneral(PrivexBaseCase): """Test cases for general converter functions/classes"""
[docs] def test_convert_bool_int_true(self): self.assertEqual(helpers.convert_bool_int(True), 1)
[docs] def test_convert_bool_int_false(self): self.assertEqual(helpers.convert_bool_int(False), 0)
[docs] def test_convert_bool_int_empty(self): self.assertEqual(helpers.convert_bool_int(None), 0)
[docs] def test_convert_bool_int_empty_cust(self): self.assertEqual(helpers.convert_bool_int(None, if_empty="error"), "error")
[docs] def test_convert_bool_int_empty_fail(self): with self.assertRaises(AttributeError): helpers.convert_bool_int(None, fail_empty=True)
[docs] def test_convert_int_bool_true(self): self.assertTrue(helpers.convert_int_bool(1))
[docs] def test_convert_int_bool_false(self): self.assertFalse(helpers.convert_int_bool(0))
[docs] def test_convert_int_bool_empty(self): self.assertFalse(helpers.convert_int_bool(None))
[docs] def test_convert_int_bool_empty_cust(self): self.assertEqual(helpers.convert_int_bool(None, if_empty="error"), "error")
[docs] def test_convert_int_bool_empty_fail(self): with self.assertRaises(AttributeError): helpers.convert_int_bool(None, fail_empty=True)
try: from dataclasses import dataclass, field HAS_DATACLASSES = True except ImportError: HAS_DATACLASSES = False warnings.warn( 'WARNING: Could not import dataclasses module (Python older than 3.7?). ' 'For older python versions such as 3.6, you can run "pip3 install dataclasses" to install the dataclasses ' 'backport library, which emulates Py3.7+ dataclasses using older syntax.', category=ImportWarning ) # To avoid a severe syntax error caused by the missing dataclass types, we generate a dummy dataclass and field class # so that type annotations such as Type[dataclass] don't break the test before it can be skipped. from privex.helpers.mockers import dataclass, field try: import attr HAS_ATTRS = True except ImportError: HAS_ATTRS = False warnings.warn( 'WARNING: Could not import "attr" module. Please run "pip3 install attrs" to install the attrs module.', category=ImportWarning ) # To avoid a severe syntax error caused by the missing dataclass types, we generate a dummy dataclass and field class # so that type annotations such as Type[dataclass] don't break the test before it can be skipped. from privex.helpers.mockers import attr EXAMP_DEC = Decimal('1.2345') EXAMP_DEC_STR = '1.2345' EXAMP_DEC_FLOAT = 1.2345 EXAMP_INT, EXAMP_INT_STR = 123123, '123123' EXAMP_FLOAT, EXAMP_FLOAT_STR = 543.12342, '543.12342' EXAMP_STR = 'hello world' EXAMP_LIST = [1, 2, Decimal('3.123'), ('a', 'b', b'c')] EXAMP_LIST_CLEAN_NUM = [1, 2, 3.123, ['a', 'b', 'c']] EXAMP_LIST_CLEAN_STR = ['1', '2', '3.123', ['a', 'b', 'c']] EXAMP_DICT = dict(lorem='ipsum', dolor=3, world=list(EXAMP_LIST), example=Decimal(EXAMP_DEC)) EXAMP_DICT_CLEAN_STR = dict(lorem='ipsum', dolor='3', world=list(EXAMP_LIST_CLEAN_STR), example=EXAMP_DEC_STR) EXAMP_DICT_CLEAN_NUM = dict(lorem='ipsum', dolor=3, world=list(EXAMP_LIST_CLEAN_NUM), example=EXAMP_DEC_FLOAT) @attr.s class ExampleAttrs: hello = attr.ib(default='world') lorem = attr.ib(factory=lambda: Decimal(EXAMP_DEC)) ipsum = attr.ib(factory=lambda: list(EXAMP_LIST)) dolor = attr.ib(factory=lambda: dict(EXAMP_DICT)) @dataclass class ExampleDataClass: hello: str = 'world' lorem: Decimal = field(default_factory=lambda: Decimal(EXAMP_DEC)) ipsum: list = field(default_factory=lambda: list(EXAMP_LIST)) dolor: dict = field(default_factory=lambda: dict(EXAMP_DICT)) class TestCleanData(PrivexBaseCase): def test_clean_obj_decimal(self): self.assertEqual(helpers.clean_obj(EXAMP_DEC), EXAMP_DEC_FLOAT) self.assertEqual(helpers.clean_obj(EXAMP_DEC, number_str=True), EXAMP_DEC_STR) def test_clean_obj_float(self): self.assertEqual(helpers.clean_obj(EXAMP_FLOAT), EXAMP_FLOAT) self.assertEqual(helpers.clean_obj(EXAMP_FLOAT, number_str=True), EXAMP_FLOAT_STR) def test_clean_obj_int(self): self.assertEqual(helpers.clean_obj(EXAMP_INT), EXAMP_INT) self.assertEqual(helpers.clean_obj(EXAMP_INT, number_str=True), EXAMP_INT_STR) def test_clean_obj_list(self): self.assertEqual(helpers.clean_obj(EXAMP_LIST), EXAMP_LIST_CLEAN_NUM) self.assertEqual(helpers.clean_obj(EXAMP_LIST, number_str=True), EXAMP_LIST_CLEAN_STR) def test_clean_obj_dict(self): self.assertEqual(helpers.clean_obj(EXAMP_DICT), EXAMP_DICT_CLEAN_NUM) self.assertEqual(helpers.clean_obj(EXAMP_DICT, number_str=True), EXAMP_DICT_CLEAN_STR) @pytest.mark.skipif(HAS_ATTRS is False, reason='HAS_ATTRS is False (must install attrs: pip3 install attrs)') def test_clean_obj_attrs(self): o = ExampleAttrs() c = helpers.clean_obj(o) self.assertIsInstance(c, dict) self.assertEqual(c['hello'], 'world') self.assertEqual(c['lorem'], EXAMP_DEC_FLOAT) self.assertListEqual(c['ipsum'], EXAMP_LIST_CLEAN_NUM) self.assertDictEqual(c['dolor'], EXAMP_DICT_CLEAN_NUM) cs = helpers.clean_obj(o, True) self.assertIsInstance(cs, dict) self.assertEqual(cs['hello'], 'world') self.assertEqual(cs['lorem'], EXAMP_DEC_STR) self.assertListEqual(cs['ipsum'], EXAMP_LIST_CLEAN_STR) self.assertDictEqual(cs['dolor'], EXAMP_DICT_CLEAN_STR) @pytest.mark.skipif(HAS_DATACLASSES is False, reason='HAS_DATACLASSES is False (Python older than 3.7?)') def test_clean_obj_dataclass(self): o = ExampleDataClass() c = helpers.clean_obj(o) self.assertIsInstance(c, dict) self.assertEqual(c['hello'], 'world') self.assertEqual(c['lorem'], EXAMP_DEC_FLOAT) self.assertListEqual(c['ipsum'], EXAMP_LIST_CLEAN_NUM) self.assertDictEqual(c['dolor'], EXAMP_DICT_CLEAN_NUM) cs = helpers.clean_obj(o, True) self.assertIsInstance(cs, dict) self.assertEqual(cs['hello'], 'world') self.assertEqual(cs['lorem'], EXAMP_DEC_STR) self.assertListEqual(cs['ipsum'], EXAMP_LIST_CLEAN_STR) self.assertDictEqual(cs['dolor'], EXAMP_DICT_CLEAN_STR)