Skip to content

Commit

Permalink
Modify to support ANSI color
Browse files Browse the repository at this point in the history
  • Loading branch information
thombashi committed Oct 30, 2018
1 parent 408e39c commit 8cdfc43
Show file tree
Hide file tree
Showing 26 changed files with 154 additions and 81 deletions.
16 changes: 13 additions & 3 deletions test/checker/test_checker_bool.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
from typepy import Bool, StrictLevel, Typecode


class_under_test = Bool
nan = float("nan")
inf = float("inf")


class Test_Bool_is_type:
@pytest.mark.parametrize(
["value", "strict_level", "expected"],
[[colored("True", "red"), StrictLevel.MIN, True]]
+ list(itertools.product([True, False], [StrictLevel.MIN, StrictLevel.MAX], [True]))
list(itertools.product([True, False], [StrictLevel.MIN, StrictLevel.MAX], [True]))
+ list(
itertools.product([0, 1, "True", "False", "true", "false"], [StrictLevel.MIN], [True])
)
Expand All @@ -33,7 +33,17 @@ class Test_Bool_is_type:
),
)
def test_normal(self, value, strict_level, expected):
type_checker = Bool(value, strict_level)
type_checker = class_under_test(value, strict_level)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.BOOL

@pytest.mark.parametrize(
["value", "strip_ansi_escape", "expected"],
[[colored("True", "red"), False, False], [colored("True", "red"), True, True]],
)
def test_normal_ansi(self, value, strip_ansi_escape, expected):
type_checker = class_under_test(value, StrictLevel.MIN, strip_ansi_escape=strip_ansi_escape)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.BOOL
19 changes: 16 additions & 3 deletions test/checker/test_checker_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
from typepy import DateTime, StrictLevel, Typecode


class_under_test = DateTime
nan = float("nan")
inf = float("inf")


class Test_DateTime_is_type(object):
@pytest.mark.parametrize(
["value", "strict_level", "expected"],
[[colored("2017-03-22T10:00:00", "red"), StrictLevel.MIN, True]]
+ list(
list(
itertools.product(
[datetime(2017, 3, 22, 10, 0, tzinfo=tzoffset(None, 32400)), date(2017, 3, 22)],
[StrictLevel.MIN, StrictLevel.MIN + 1, StrictLevel.MAX],
Expand All @@ -43,7 +43,20 @@ class Test_DateTime_is_type(object):
+ list(itertools.product(["2017-03-22T10:00:00+0900"], [StrictLevel.MAX], [False])),
)
def test_normal(self, value, strict_level, expected):
type_object = DateTime(value, strict_level)
type_object = class_under_test(value, strict_level)

assert type_object.is_type() == expected
assert type_object.typecode == Typecode.DATETIME

@pytest.mark.parametrize(
["value", "strip_ansi_escape", "expected"],
[
[colored("2017-03-22T10:00:00", "red"), False, False],
[colored("2017-03-22T10:00:00", "red"), True, True],
],
)
def test_normal_ansi(self, value, strip_ansi_escape, expected):
type_checker = class_under_test(value, StrictLevel.MIN, strip_ansi_escape=strip_ansi_escape)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.DATETIME
14 changes: 12 additions & 2 deletions test/checker/test_checker_integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from typepy import Integer, StrictLevel, Typecode


class_under_test = Integer
nan = float("nan")
inf = float("inf")

Expand All @@ -30,7 +31,6 @@ class Test_Integer_is_type(object):
[" 1 ", StrictLevel.MIN + 1, True],
[True, StrictLevel.MIN + 1, False],
[False, StrictLevel.MAX, False],
[colored("1", "red"), StrictLevel.MIN, True],
]
+ list(
itertools.product(
Expand Down Expand Up @@ -65,7 +65,17 @@ class Test_Integer_is_type(object):
),
)
def test_normal(self, value, strict_level, expected):
type_checker = Integer(value, strict_level)
type_checker = class_under_test(value, strict_level)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.INTEGER

@pytest.mark.parametrize(
["value", "strip_ansi_escape", "expected"],
[[colored("1", "red"), False, False], [colored("1", "red"), True, True]],
)
def test_normal_ansi(self, value, strip_ansi_escape, expected):
type_checker = class_under_test(value, StrictLevel.MIN, strip_ansi_escape=strip_ansi_escape)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.INTEGER
11 changes: 11 additions & 0 deletions test/checker/test_checker_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from typepy import IpAddress, StrictLevel, Typecode


class_under_test = IpAddress
nan = float("nan")
inf = float("inf")

Expand Down Expand Up @@ -46,3 +47,13 @@ def test_normal(self, value, strict_level, expected):

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.IP_ADDRESS

@pytest.mark.parametrize(
["value", "strip_ansi_escape", "expected"],
[[colored("127.0.0.1", "red"), False, False], [colored("127.0.0.1", "red"), True, True]],
)
def test_normal_ansi(self, value, strip_ansi_escape, expected):
type_checker = class_under_test(value, StrictLevel.MIN, strip_ansi_escape=strip_ansi_escape)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.IP_ADDRESS
16 changes: 13 additions & 3 deletions test/checker/test_checker_realnumber.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
from typepy import RealNumber, StrictLevel, Typecode


class_under_test = RealNumber
nan = float("nan")
inf = float("inf")


class Test_RealNumber_is_type(object):
@pytest.mark.parametrize(
["value", "strict_level", "expected"],
[[colored("1.1", "red"), StrictLevel.MIN, True]]
+ list(
list(
itertools.product(
[
0,
Expand Down Expand Up @@ -77,7 +77,17 @@ class Test_RealNumber_is_type(object):
),
)
def test_normal(self, value, strict_level, expected):
type_checker = RealNumber(value, strict_level)
type_checker = class_under_test(value, strict_level)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.REAL_NUMBER

@pytest.mark.parametrize(
["value", "strip_ansi_escape", "expected"],
[[colored("1.1", "red"), False, False], [colored("1.1", "red"), True, True]],
)
def test_normal_ansi(self, value, strip_ansi_escape, expected):
type_checker = class_under_test(value, StrictLevel.MIN, strip_ansi_escape=strip_ansi_escape)

assert type_checker.is_type() == expected
assert type_checker.typecode == Typecode.REAL_NUMBER
2 changes: 1 addition & 1 deletion typepy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import typepy.type

from .__version__ import __author__, __copyright__, __email__, __license__, __version__
from ._const import StrictLevel
from ._const import StrictLevel, ParamKey
from ._function import (
is_empty_sequence,
is_empty_string,
Expand Down
6 changes: 6 additions & 0 deletions typepy/_const.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@

class DefaultValue(object):
FLOAT_TYPE = Decimal
STRIP_ANSI_ESCAPE = True


class StrictLevel(object):
MIN = 0
MAX = 100


class ParamKey(object):
STRIP_ANSI_ESCAPE = "strip_ansi_escape"
TIMEZONE = "timezone"
16 changes: 10 additions & 6 deletions typepy/converter/_bool.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import six

from .._common import strip_ansi_escape
from .._const import DefaultValue, ParamKey
from ..error import TypeConversionError
from ._interface import AbstractValueConverter

Expand All @@ -23,12 +24,15 @@ def force_convert(self):
except ValueError:
pass

try:
return self.__strict_strtobool(strip_ansi_escape(self._value))
except (TypeError, ValueError):
raise TypeConversionError(
"failed to force_convert to bool: type={}".format(type(self._value))
)
if self._params.get(ParamKey.STRIP_ANSI_ESCAPE, DefaultValue.STRIP_ANSI_ESCAPE):
try:
return self.__strict_strtobool(strip_ansi_escape(self._value))
except (TypeError, ValueError):
pass

raise TypeConversionError(
"failed to force_convert to bool: type={}".format(type(self._value))
)

@staticmethod
def __strict_strtobool(value):
Expand Down
23 changes: 14 additions & 9 deletions typepy/converter/_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from distutils.version import StrictVersion

from .._common import strip_ansi_escape
from .._const import DefaultValue, ParamKey
from ..error import TypeConversionError
from ._interface import AbstractValueConverter

Expand All @@ -31,11 +32,11 @@ class DateTimeConverter(AbstractValueConverter):
7200: "Africa/Tripoli", # 0200
}

def __init__(self, value, timezone=None):
super(DateTimeConverter, self).__init__(value)
def __init__(self, value, params):
super(DateTimeConverter, self).__init__(value, params)

self.__datetime = None
self.__timezone = timezone
self.__timezone = self._params.get(ParamKey.TIMEZONE)

def force_convert(self):
self.__datetime = self.__from_datetime()
Expand Down Expand Up @@ -89,12 +90,16 @@ def __from_datetime_string(self):
try:
self.__datetime = dateutil.parser.parse(self._value)
except (AttributeError, ValueError, OverflowError):
try:
self.__datetime = dateutil.parser.parse(strip_ansi_escape(self._value))
except (AttributeError, ValueError, OverflowError):
raise TypeConversionError(
"failed to parse as a datetime: type={}".format(type(self._value))
)
if self._params.get(ParamKey.STRIP_ANSI_ESCAPE, DefaultValue.STRIP_ANSI_ESCAPE):
try:
self.__datetime = dateutil.parser.parse(strip_ansi_escape(self._value))
except (AttributeError, ValueError, OverflowError):
pass

if self.__datetime is None:
raise TypeConversionError(
"failed to parse as a datetime: type={}".format(type(self._value))
)

if self.__timezone:
pytz_timezone = self.__timezone
Expand Down
10 changes: 6 additions & 4 deletions typepy/converter/_integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from decimal import Decimal, InvalidOperation

from .._common import strip_ansi_escape
from .._const import DefaultValue, ParamKey
from ..error import TypeConversionError
from ._interface import AbstractValueConverter

Expand All @@ -20,10 +21,11 @@ def force_convert(self):
except (TypeError, OverflowError, ValueError, InvalidOperation):
pass

try:
return int(Decimal(strip_ansi_escape(self._value)))
except (TypeError, OverflowError, ValueError, InvalidOperation):
pass
if self._params.get(ParamKey.STRIP_ANSI_ESCAPE, DefaultValue.STRIP_ANSI_ESCAPE):
try:
return int(Decimal(strip_ansi_escape(self._value)))
except (TypeError, OverflowError, ValueError, InvalidOperation):
pass

raise TypeConversionError(
"failed to force_convert to int: type={}".format(type(self._value))
Expand Down
3 changes: 2 additions & 1 deletion typepy/converter/_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ def force_convert(self): # pragma: no cover
class AbstractValueConverter(ValueConverterInterface):
__slots__ = "_value"

def __init__(self, value):
def __init__(self, value, params):
self._value = value
self._params = params

def __repr__(self):
try:
Expand Down
16 changes: 10 additions & 6 deletions typepy/converter/_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import six

from .._common import strip_ansi_escape
from .._const import DefaultValue, ParamKey
from ..error import TypeConversionError
from ._interface import AbstractValueConverter

Expand All @@ -24,9 +25,12 @@ def force_convert(self):
except ValueError:
pass

try:
return ipaddress.ip_address(strip_ansi_escape(value))
except ValueError:
raise TypeConversionError(
"failed to force_convert to dictionary: type={}".format(type(self._value))
)
if self._params.get(ParamKey.STRIP_ANSI_ESCAPE, DefaultValue.STRIP_ANSI_ESCAPE):
try:
return ipaddress.ip_address(strip_ansi_escape(value))
except ValueError:
pass

raise TypeConversionError(
"failed to force_convert to dictionary: type={}".format(type(self._value))
)
21 changes: 12 additions & 9 deletions typepy/converter/_realnumber.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
import six

from .._common import strip_ansi_escape
from .._const import DefaultValue
from .._const import DefaultValue, ParamKey
from ..error import TypeConversionError
from ._interface import AbstractValueConverter


class FloatConverter(AbstractValueConverter):
def __init__(self, value):
super(FloatConverter, self).__init__(value)
def __init__(self, value, params):
super(FloatConverter, self).__init__(value, params)

self.float_class = DefaultValue.FLOAT_TYPE

Expand All @@ -34,9 +34,12 @@ def force_convert(self):
except (TypeError, ValueError, decimal.InvalidOperation):
pass

try:
return self.float_class(strip_ansi_escape(self._value))
except (TypeError, ValueError, decimal.InvalidOperation):
raise TypeConversionError(
"failed to force_convert to float: type={}".format(type(self._value))
)
if self._params.get(ParamKey.STRIP_ANSI_ESCAPE, DefaultValue.STRIP_ANSI_ESCAPE):
try:
return self.float_class(strip_ansi_escape(self._value))
except (TypeError, ValueError, decimal.InvalidOperation):
pass

raise TypeConversionError(
"failed to force_convert to float: type={}".format(type(self._value))
)
8 changes: 2 additions & 6 deletions typepy/type/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,10 @@ def _create_type_converter(self): # pragma: no cover
def typename(self):
return self.typecode.name

def __init__(self, value, strict_level, params):
def __init__(self, value, strict_level, **kwargs):
self._data = value
self._strict_level = strict_level

if not params:
self._params = {}
else:
self._params = params
self._params = kwargs

self.__checker = self._create_type_checker()
self.__converter = self._create_type_converter()
Expand Down
4 changes: 2 additions & 2 deletions typepy/type/_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ def typecode(self):
return Typecode.STRING

def __init__(self, value, strict_level=1, **kwargs):
super(Binary, self).__init__(value, strict_level, kwargs)
super(Binary, self).__init__(value, strict_level, **kwargs)

def _create_type_checker(self):
return BinaryTypeChecker(self._data, self._strict_level)

def _create_type_converter(self):
return BinaryConverter(self._data)
return BinaryConverter(self._data, self._params)

0 comments on commit 8cdfc43

Please sign in to comment.