From 54cb8d9983b6f1cf64511918a097077e93e153b7 Mon Sep 17 00:00:00 2001 From: elie Date: Sun, 9 Feb 2014 17:32:41 +0000 Subject: * The abs(Integer()) & abs(Real()) operation now returns respective pyasn1 type, not a Python type. * More Python magic methods implementations added to Integer & Real classes (e.g. __pos__, __neg__, __round__, __floor__, __ceil__, __trunc__) * The Integer.__invert__ Python magic method implemented. --- CHANGES | 5 +++++ pyasn1/type/univ.py | 25 +++++++++++++++++++++---- test/type/test_univ.py | 25 +++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 1445cbc..93959b4 100644 --- a/CHANGES +++ b/CHANGES @@ -29,6 +29,11 @@ Revision 0.1.8 reflect this change. - NamedTypes() and NamedValues() made comparable. - Test coverage extended to cover pyasn1 types __repr__() function. +- The abs(Integer()) & abs(Real()) operation now returns respective pyasn1 + type, not a Python type. +- More Python magic methods implementations added to Integer & Real classes + (e.g. __pos__, __neg__, __round__, __floor__, __ceil__, __trunc__) +- The Integer.__invert__ Python magic method implemented. - Fix to NamedType.__repr__() to work properly. - Fixes to __repr__() implementation of many built-in ASN.1 types to take into account all of their initializers such as tagSet, subtypeSpec etc. diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 4b88fda..ddae16f 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -1,5 +1,5 @@ # ASN.1 "universal" data types -import operator, sys +import operator, sys, math from pyasn1.type import base, tag, constraint, namedtype, namedval, tagmap from pyasn1.codec.ber import eoo from pyasn1.compat import octets @@ -63,8 +63,17 @@ class Integer(base.AbstractSimpleAsn1Item): if sys.version_info[0] <= 2: def __long__(self): return long(self._value) def __float__(self): return float(self._value) - def __abs__(self): return abs(self._value) + def __abs__(self): return self.clone(abs(self._value)) def __index__(self): return int(self._value) + def __pos__(self): return self.clone(+self._value) + def __neg__(self): return self.clone(-self._value) + def __invert__(self): return self.clone(~self._value) + + def __round__(self, n): return round(self._value, n) + def __floor__(self): return math.floor(self._value) + def __ceil__(self): return math.ceil(self._value) + if sys.version_info[0:2] > (2, 4): + def __trunc__(self): return math.trunc(self._value) def __lt__(self, value): return self._value < value def __le__(self, value): return self._value <= value @@ -642,8 +651,16 @@ class Real(base.AbstractSimpleAsn1Item): else: return float( self._value[0] * pow(self._value[1], self._value[2]) - ) - def __abs__(self): return abs(float(self)) + ) + def __abs__(self): return self.clone(abs(float(self))) + def __pos__(self): return self.clone(+float(self)) + def __neg__(self): return self.clone(-float(self)) + + def __round__(self, n): return round(float(self), n) + def __floor__(self): return math.floor(float(self)) + def __ceil__(self): return math.ceil(float(self)) + if sys.version_info[0:2] > (2, 4): + def __trunc__(self): return math.trunc(float(self)) def __lt__(self, value): return float(self) < value def __le__(self, value): return float(self) <= value diff --git a/test/type/test_univ.py b/test/type/test_univ.py index d2280b9..9a14963 100644 --- a/test/type/test_univ.py +++ b/test/type/test_univ.py @@ -2,6 +2,7 @@ from pyasn1.type import univ, tag, constraint, namedtype, namedval, error from pyasn1.compat.octets import str2octs, ints2octs from pyasn1.error import PyAsn1Error from sys import version_info +import math if version_info[0:2] < (2, 7) or \ version_info[0:2] in ( (3, 0), (3, 1) ): try: @@ -38,6 +39,18 @@ class IntegerTestCase(unittest.TestCase): def testInt(self): assert int(univ.Integer(3)) == 3, '__int__() fails' def testLong(self): assert int(univ.Integer(8)) == 8, '__long__() fails' def testFloat(self): assert float(univ.Integer(4))==4.0,'__float__() fails' + def testPos(self): assert +univ.Integer(1) == 1, '__pos__() fails' + def testNeg(self): assert -univ.Integer(1) == -1, '__neg__() fails' + def testInvert(self): assert ~univ.Integer(1) == -2, '__invert__() fails' + def testRound(self): + assert round(univ.Integer(1), 3) == 1.0,'__round__() fails' + def testFloor(self): + assert math.floor(univ.Integer(1)) == 1,'__floor__() fails' + def testCeil(self): + assert math.ceil(univ.Integer(1)) == 1,'__ceil__() fails' + if version_info[0:2] > (2, 4): + def testTrunc(self): + assert math.trunc(univ.Integer(1)) == 1,'__trunc__() fails' def testPrettyIn(self): assert univ.Integer('3') == 3, 'prettyIn() fails' def testTag(self): assert univ.Integer().getTagSet() == tag.TagSet( @@ -229,6 +242,18 @@ class RealTestCase(unittest.TestCase): def testMinusInf(self): assert univ.Real('-inf').isMinusInfinity(), 'isMinusInfinity failed' + def testPos(self): assert +univ.Real(1.0) == 1.0, '__pos__() fails' + def testNeg(self): assert -univ.Real(1.0) == -1.0, '__neg__() fails' + def testRound(self): + assert round(univ.Real(1.123), 2) == 1.12,'__round__() fails' + def testFloor(self): + assert math.floor(univ.Real(1.6)) == 1.0,'__floor__() fails' + def testCeil(self): + assert math.ceil(univ.Real(1.2)) == 2.0,'__ceil__() fails' + if version_info[0:2] > (2, 4): + def testTrunc(self): + assert math.trunc(univ.Real(1.1)) == 1.0,'__trunc__() fails' + def testTag(self): assert univ.Real().getTagSet() == tag.TagSet( (), -- cgit v1.2.1