/nose/pyversion.py

https://bitbucket.org/jpellerin/nose/ · Python · 130 lines · 89 code · 17 blank · 24 comment · 17 complexity · 4e947d05902f1ff278cdcb7e9df69356 MD5 · raw file

  1. """
  2. This module contains fixups for using nose under different versions of Python.
  3. """
  4. import sys
  5. import os
  6. import types
  7. import inspect
  8. import nose.util
  9. __all__ = ['make_instancemethod', 'cmp_to_key', 'sort_list', 'ClassType',
  10. 'TypeType', 'UNICODE_STRINGS', 'unbound_method', 'ismethod',
  11. 'bytes_']
  12. # In Python 3.x, all strings are unicode (the call to 'unicode()' in the 2.x
  13. # source will be replaced with 'str()' when running 2to3, so this test will
  14. # then become true)
  15. UNICODE_STRINGS = (type(unicode()) == type(str()))
  16. # new.instancemethod() is obsolete for new-style classes (Python 3.x)
  17. # We need to use descriptor methods instead.
  18. try:
  19. import new
  20. def make_instancemethod(function, instance):
  21. return new.instancemethod(function.im_func, instance,
  22. instance.__class__)
  23. except ImportError:
  24. def make_instancemethod(function, instance):
  25. return function.__get__(instance, instance.__class__)
  26. # To be forward-compatible, we do all list sorts using keys instead of cmp
  27. # functions. However, part of the unittest.TestLoader API involves a
  28. # user-provideable cmp function, so we need some way to convert that.
  29. def cmp_to_key(mycmp):
  30. 'Convert a cmp= function into a key= function'
  31. class Key(object):
  32. def __init__(self, obj):
  33. self.obj = obj
  34. def __lt__(self, other):
  35. return mycmp(self.obj, other.obj) < 0
  36. def __gt__(self, other):
  37. return mycmp(self.obj, other.obj) > 0
  38. def __eq__(self, other):
  39. return mycmp(self.obj, other.obj) == 0
  40. return Key
  41. # Python 2.3 also does not support list-sorting by key, so we need to convert
  42. # keys to cmp functions if we're running on old Python..
  43. if sys.version_info < (2, 4):
  44. def sort_list(l, key, reverse=False):
  45. if reverse:
  46. return l.sort(lambda a, b: cmp(key(b), key(a)))
  47. else:
  48. return l.sort(lambda a, b: cmp(key(a), key(b)))
  49. else:
  50. def sort_list(l, key, reverse=False):
  51. return l.sort(key=key, reverse=reverse)
  52. # In Python 3.x, all objects are "new style" objects descended from 'type', and
  53. # thus types.ClassType and types.TypeType don't exist anymore. For
  54. # compatibility, we make sure they still work.
  55. if hasattr(types, 'ClassType'):
  56. ClassType = types.ClassType
  57. TypeType = types.TypeType
  58. else:
  59. ClassType = type
  60. TypeType = type
  61. # The following emulates the behavior (we need) of an 'unbound method' under
  62. # Python 3.x (namely, the ability to have a class associated with a function
  63. # definition so that things can do stuff based on its associated class)
  64. class UnboundMethod:
  65. def __init__(self, cls, func):
  66. # Make sure we have all the same attributes as the original function,
  67. # so that the AttributeSelector plugin will work correctly...
  68. self.__dict__ = func.__dict__.copy()
  69. self._func = func
  70. self.__self__ = UnboundSelf(cls)
  71. def address(self):
  72. cls = self.__self__.cls
  73. modname = cls.__module__
  74. module = sys.modules[modname]
  75. filename = getattr(module, '__file__', None)
  76. if filename is not None:
  77. filename = os.path.abspath(filename)
  78. return (nose.util.src(filename), modname, "%s.%s" % (cls.__name__,
  79. self._func.__name__))
  80. def __call__(self, *args, **kwargs):
  81. return self._func(*args, **kwargs)
  82. def __getattr__(self, attr):
  83. return getattr(self._func, attr)
  84. def __repr__(self):
  85. return '<unbound method %s.%s>' % (self.__self__.cls.__name__,
  86. self._func.__name__)
  87. class UnboundSelf:
  88. def __init__(self, cls):
  89. self.cls = cls
  90. # We have to do this hackery because Python won't let us override the
  91. # __class__ attribute...
  92. def __getattribute__(self, attr):
  93. if attr == '__class__':
  94. return self.cls
  95. else:
  96. return object.__getattribute__(self, attr)
  97. def unbound_method(cls, func):
  98. if inspect.ismethod(func):
  99. return func
  100. if not inspect.isfunction(func):
  101. raise TypeError('%s is not a function' % (repr(func),))
  102. return UnboundMethod(cls, func)
  103. def ismethod(obj):
  104. return inspect.ismethod(obj) or isinstance(obj, UnboundMethod)
  105. # Make a pseudo-bytes function that can be called without the encoding arg:
  106. if sys.version_info >= (3, 0):
  107. def bytes_(s, encoding='utf8'):
  108. if isinstance(s, bytes):
  109. return s
  110. return bytes(s, encoding)
  111. else:
  112. def bytes_(s, encoding=None):
  113. return str(s)