_oldstyle.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. # -*- test-case-name: twisted.test.test_nooldstyle -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Utilities to assist in the "flag day" new-style object transition.
  6. """
  7. from __future__ import absolute_import, division
  8. import types
  9. from functools import wraps
  10. from twisted.python.compat import _shouldEnableNewStyle, _PY3
  11. def _replaceIf(condition, alternative):
  12. """
  13. If C{condition}, replace this function with C{alternative}.
  14. @param condition: A L{bool} which says whether this should be replaced.
  15. @param alternative: An alternative function that will be swapped in instead
  16. of the original, if C{condition} is truthy.
  17. @return: A decorator.
  18. """
  19. def decorator(func):
  20. if condition is True:
  21. call = alternative
  22. elif condition is False:
  23. call = func
  24. else:
  25. raise ValueError(("condition argument to _replaceIf requires a "
  26. "bool, not {}").format(repr(condition)))
  27. @wraps(func)
  28. def wrapped(*args, **kwargs):
  29. return call(*args, **kwargs)
  30. return wrapped
  31. return decorator
  32. def passthru(arg):
  33. """
  34. Return C{arg}. Do nothing.
  35. @param arg: The arg to return.
  36. @return: C{arg}
  37. """
  38. return arg
  39. def _ensureOldClass(cls):
  40. """
  41. Ensure that C{cls} is an old-style class.
  42. @param cls: The class to check.
  43. @return: The class, if it is an old-style class.
  44. @raises: L{ValueError} if it is a new-style class.
  45. """
  46. if not type(cls) is types.ClassType:
  47. from twisted.python.reflect import fullyQualifiedName
  48. raise ValueError(
  49. ("twisted.python._oldstyle._oldStyle is being used to decorate a "
  50. "new-style class ({cls}). This should only be used to "
  51. "decorate old-style classes.").format(
  52. cls=fullyQualifiedName(cls)))
  53. return cls
  54. @_replaceIf(_PY3, passthru)
  55. @_replaceIf(not _shouldEnableNewStyle(), _ensureOldClass)
  56. def _oldStyle(cls):
  57. """
  58. A decorator which conditionally converts old-style classes to new-style
  59. classes. If it is Python 3, or if the C{TWISTED_NEWSTYLE} environment
  60. variable has a falsey (C{no}, C{false}, C{False}, or C{0}) value in the
  61. environment, this decorator is a no-op.
  62. @param cls: An old-style class to convert to new-style.
  63. @type cls: L{types.ClassType}
  64. @return: A new-style version of C{cls}.
  65. """
  66. _ensureOldClass(cls)
  67. _bases = cls.__bases__ + (object,)
  68. return type(cls.__name__, _bases, cls.__dict__)