r47051 - clean up the implementation
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Tue, 22 Mar 2016 06:05:34 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Tue Mar 22 06:05:26 2016
New Revision: 47051
Modified:
branches/oldstyle-decorator-8244/twisted/python/_oldstyle.py
branches/oldstyle-decorator-8244/twisted/test/test_nooldstyle.py
Log:
clean up the implementation
Modified: branches/oldstyle-decorator-8244/twisted/python/_oldstyle.py
==============================================================================
--- branches/oldstyle-decorator-8244/twisted/python/_oldstyle.py (original)
+++ branches/oldstyle-decorator-8244/twisted/python/_oldstyle.py Tue Mar 22 06:05:26 2016
@@ -1,25 +1,79 @@
+# -*- test-case-name: twisted.test.test_nooldstyle -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
+"""
+Utilities to assist in the "flag day" new-style object transition.
+"""
+
from __future__ import absolute_import, division
import os
-
-from functools import wraps
+import types
from twisted.python.compat import _PY3
-if _PY3 or int(os.environ.get('TWISTED_NEWSTYLE', 0)) == 0:
+
+def _ensureOldClass(cls):
+ """
+ Ensure that C{cls} is an old-style class.
+
+ @param cls: The class to check.
+
+ @return: C{None} if it is an old-style class.
+ @raises: L{ValueError} if it is a new-style class.
+ """
+ if not type(cls) is types.ClassType:
+ from twisted.python.reflect import fullyQualifiedName
+
+ raise ValueError(
+ ("twisted.python._oldstyle._oldStyle is being used to decorate a "
+ "new-style class ({cls}). This should only be used to "
+ "decorate old-style classes.").format(
+ cls=fullyQualifiedName(cls)))
+
+
+if _PY3:
def _oldStyle(cls):
+ """
+ No such thing as an old style class on Python 3.
+
+ @param cls: The class to wrap (or in this case, not wrap).
+ @return: C{cls}, unchanged
+ """
+ return cls
+
+elif int(os.environ.get('TWISTED_NEWSTYLE', 0)) == 0:
+
+ def _oldStyle(cls):
+ """
+ We don't want to override anything, but throw an exception if a
+ new-style class is decorated.
+
+ @param cls: The class to wrap (or in this case, not wrap).
+ @type cls: L{types.ClassType}
+
+ @return: C{cls}, unchanged
+ @raises: L{ValueError} if C{cls} is a new-style class.
+ """
+ _ensureOldClass(cls)
return cls
else:
def _oldStyle(cls):
+ """
+ A decorator which converts old-style classes to new-style classes.
+
+ @param cls: An old-style class to convert to new-style.
+ @type cls: L{types.ClassType}
+ @return: A new-style subclass of C{cls}.
+ """
+ _ensureOldClass(cls)
class OverwrittenClass(cls, object):
- pass
+ __doc__ = cls.__doc__
OverwrittenClass.__name__ = cls.__name__
OverwrittenClass.__module__ = cls.__module__
Modified: branches/oldstyle-decorator-8244/twisted/test/test_nooldstyle.py
==============================================================================
--- branches/oldstyle-decorator-8244/twisted/test/test_nooldstyle.py (original)
+++ branches/oldstyle-decorator-8244/twisted/test/test_nooldstyle.py Tue Mar 22 06:05:26 2016
@@ -1,6 +1,10 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
+"""
+Tests for L{twisted.python._oldstyle._oldStyle}.
+"""
+
from __future__ import absolute_import, division
import os
@@ -11,21 +15,100 @@
from twisted.python.modules import getModule
from twisted.python.compat import _PY3
from twisted.trial import unittest
+from twisted.python._oldstyle import _oldStyle
-skip = None
+_skip = None
if _PY3:
- skip = "Not relevant on Python 3."
-elif not int(os.environ.get('TWISTED_NEWSTYLE', 0)) == 1:
- skip = "Not running with TWISTED_NEWSTYLE=1"
+ _skip = "Not relevant on Python 3."
+elif int(os.environ.get('TWISTED_NEWSTYLE', 0)) == 0:
+ _skip = "Not running with TWISTED_NEWSTYLE=1"
+
+
+
+class SomeOldStyleClass:
+ """
+ I am a docstring!
+ """
+
+
+
+class SomeNewStyleClass(object):
+ """
+ Some new style class!
+ """
+
+
+
+class OldStyleDecoratorTests(unittest.TestCase):
+ """
+ Tests for L{_oldStyle}.
+ """
+
+ def test_makesNewStyle(self):
+ """
+ L{_oldStyle} wraps an old-style class and returns a new-style class
+ that descends from the old-style one.
+ """
+ self.assertEqual(type(SomeOldStyleClass), types.ClassType)
+ updatedClass = _oldStyle(SomeOldStyleClass)
+ self.assertEqual(type(updatedClass), type)
+ self.assertIn(SomeOldStyleClass, updatedClass.__bases__)
+
+
+ def test_carriesAttributes(self):
+ """
+ The class returned by L{_oldStyle} has the same C{__name__},
+ C{__module__}, and docstring (C{__doc__}) attributes as the original.
+ """
+ updatedClass = _oldStyle(SomeOldStyleClass)
+
+ self.assertEqual(updatedClass.__name__, SomeOldStyleClass.__name__)
+ self.assertEqual(updatedClass.__doc__, SomeOldStyleClass.__doc__)
+ self.assertEqual(updatedClass.__module__, SomeOldStyleClass.__module__)
+
+
+ def test_onlyOldStyleMayBeDecorated(self):
+ """
+ Using L{_oldStyle} on a new-style class on Python 2 will raise an
+ exception.
+ """
+
+ with self.assertRaises(ValueError) as e:
+ _oldStyle(SomeNewStyleClass)
+
+ self.assertEqual(
+ e.exception.args[0],
+ ("twisted.python._oldstyle._oldStyle is being used to decorate a "
+ "new-style class (twisted.test.test_nooldstyle.SomeNewStyleClass)"
+ ". This should only be used to decorate old-style classes."))
+
+
+ def test_noOpByDefault(self):
+ """
+ On Python 3 or on Py2 when C{TWISTED_NEWSTYLE} is not set, L{_oldStyle}
+ is a no-op.
+ """
+ updatedClass = _oldStyle(SomeOldStyleClass)
+ self.assertIs(updatedClass, SomeOldStyleClass)
+
+ if _PY3:
+ test_onlyOldStyleMayBeDecorated.skip = "Only relevant on Py2."
+
+ if _skip:
+ test_makesNewStyle.skip = _skip
+ test_carriesAttributes.skip = _skip
+ else:
+ test_noOpByDefault.skip = ("Only relevant when not running under "
+ "TWISTED_NEWSTYLE=1")
-if not skip:
+if not _skip:
class NewStyleOnly(object):
"""
- A testclass that takes a module and tests if the classes defined in it
- are old-style.
+ A base testclass that takes a module and tests if the classes defined
+ in it are old-style.
CAVEATS: This is maybe slightly dumb, and only looks in non-test
modules (because some test modules have side effects). It also doesn't
@@ -34,6 +117,9 @@
module = None
def test_newStyleClassesOnly(self):
+ """
+ Test that C{self.module} has no old-style classes in it.
+ """
try:
module = namedAny(self.module)
except ImportError:
@@ -51,12 +137,15 @@
if ".test." in x.name:
continue
- class test(NewStyleOnly, unittest.TestCase):
+ class Test(NewStyleOnly, unittest.TestCase):
+ """
+ See L{NewStyleOnly}.
+ """
module = x.name
acceptableName = x.name.replace(".", "_")
- test.__name__ = acceptableName
- locals().update({acceptableName: test})
+ Test.__name__ = acceptableName
+ locals().update({acceptableName: Test})
else:
@@ -65,4 +154,7 @@
Just skip, it doesn't make sense right now.
"""
def test_newStyleClassesOnly(self):
+ """
+ No-op.
+ """
raise unittest.SkipTest(skip)