Source code for callee.numbers
"""
Matchers for numbers.
"""
from __future__ import absolute_import
import fractions
import numbers
from callee._compat import IS_PY3
from callee.base import BaseMatcher
__all__ = [
'Number',
'Complex', 'Real', 'Float', 'Rational', 'Fraction',
'Integral', 'Integer', 'Int', 'Long',
]
class NumericMatcher(BaseMatcher):
"""Matches some number type.
This class shouldn't be used directly.
"""
#: Number class to match.
#: Must be overridden in subclasses.
CLASS = None
def __init__(self):
assert self.CLASS, "must specify number type to match"
def match(self, value):
return isinstance(value, self.CLASS)
def __repr__(self):
return "<%s>" % (self.__class__.__name__,)
[docs]class Number(NumericMatcher):
"""Matches any number
(integer, float, complex, custom number types, etc.).
"""
CLASS = numbers.Number
[docs]class Complex(NumericMatcher):
"""Matches any complex number.
This *includes* all real, rational, and integer numbers as well,
which in Python translates to `float`\ s, fractions, and `int`\ egers.
"""
CLASS = numbers.Complex
# TODO: consider adding a dedicated matcher for the ``complex`` type;
# right now, though, ``IsA(complex)`` and ``Complex() & ~Real()`` are probably
# acceptable workarounds
[docs]class Real(NumericMatcher):
"""Matches any real number.
This includes all rational and integer numbers as well, which in Python
translates to fractions, and `int`\ egers.
"""
CLASS = numbers.Real
[docs]class Float(NumericMatcher):
"""Matches a floating point number."""
CLASS = float
[docs]class Rational(NumericMatcher):
"""Matches a rational number.
This includes all `int`\ eger numbers as well.
"""
CLASS = numbers.Rational
[docs]class Fraction(NumericMatcher):
"""Matches a fraction object."""
CLASS = fractions.Fraction
[docs]class Integral(NumericMatcher):
"""Matches any integer.
This ignores the length of integer's internal representation on Python 2.
"""
CLASS = int if IS_PY3 else (int, long)
[docs]class Integer(NumericMatcher):
"""Matches a regular integer.
On Python 3, there is no distinction between regular and long integer,
making this matcher and :class:`Long` equivalent.
On Python 2, this matches the :class:`int` integers exclusively.
"""
CLASS = int
#: Alias for :class:`Integer`.
Int = Integer
[docs]class Long(NumericMatcher):
"""Matches a long integer.
On Python 3, this is the same as regular integer, making this matcher
and :class:`Integer` equivalent.
On Python 2, this matches the :class:`long` integers exclusively.
"""
CLASS = int if IS_PY3 else long