From a20db8ff53e62c78f9e6b4077167ebb4a81cf94c Mon Sep 17 00:00:00 2001 From: Yesudeep Mangalapilly Date: Thu, 11 Aug 2011 01:47:46 +0530 Subject: Compatibility wrapper module to make rsa work with various versions of Python. --- rsa/_compat.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test_compat.py | 17 +++++++++ 2 files changed, 116 insertions(+) create mode 100644 rsa/_compat.py create mode 100644 tests/test_compat.py diff --git a/rsa/_compat.py b/rsa/_compat.py new file mode 100644 index 0000000..162f47e --- /dev/null +++ b/rsa/_compat.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2011 Sybren A. Stüvel +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +'''Python compatibility wrappers.''' + + +from __future__ import absolute_import + +from struct import pack + +try: + # < Python3 + unicode_type = unicode + have_python3 = False +except NameError: + # Python3. + unicode_type = str + have_python3 = True + +# Fake byte literals. +if str is unicode_type: + def byte_literal(s): + return s.encode('latin1') +else: + def byte_literal(s): + return s + +# ``long`` is no more. Do type detection using this instead. +try: + integer_types = (int, long) +except NameError: + integer_types = (int,) + +b = byte_literal + +try: + # Python 2.6 or higher. + bytes_type = bytes +except NameError: + # Python 2.5 + bytes_type = str + + +def is_bytes(obj): + """ + Determines whether the given value is a byte string. + + :param obj: + The value to test. + :returns: + ``True`` if ``value`` is a byte string; ``False`` otherwise. + """ + return isinstance(obj, bytes_type) + + +def is_integer(obj): + """ + Determines whether the given value is an integer. + + :param obj: + The value to test. + :returns: + ``True`` if ``value`` is an integer; ``False`` otherwise. + """ + return isinstance(obj, integer_types) + + +def byte(num): + """ + Converts a number between 0 and 255 (both inclusive) to a base-256 (byte) + representation. + + Use it as a replacement for ``chr`` where you are expecting a byte + because this will work on all current versions of Python:: + + >>> byte(0) + '\x00' + >>> byte(255) + '\xff' + + :param num: + An unsigned integer between 0 and 255 (both inclusive). + :returns: + A single byte. + """ + return pack("B", num) diff --git a/tests/test_compat.py b/tests/test_compat.py new file mode 100644 index 0000000..3652c82 --- /dev/null +++ b/tests/test_compat.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +import unittest2 +import struct + +from rsa._compat import is_bytes, byte + +class Test_byte(unittest2.TestCase): + def test_byte(self): + for i in range(256): + byt = byte(i) + self.assertTrue(is_bytes(byt)) + self.assertEqual(ord(byt), i) + + def test_raises_StructError_on_overflow(self): + self.assertRaises(struct.error, byte, 256) + self.assertRaises(struct.error, byte, -1) -- cgit v1.2.1