Changeset 200:ab43d6940b65


Ignore:
Timestamp:
Oct 3, 2016, 8:49:10 AM (4 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
rebase_source:
d1e5d6827b59ba96688a5a8724fb63277a13dbf5
Message:

imported patch py3-compat.patch

Location:
wokkel
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • wokkel/compat.py

    r165 r200  
    88"""
    99
    10 __all__ = ['BootstrapMixin', 'XmlStreamServerFactory', 'IQ',
    11            'NamedConstant', 'ValueConstant', 'Names', 'Values']
    12 
    13 from itertools import count
     10from __future__ import division, absolute_import
    1411
    1512from twisted.python.deprecate import deprecatedModuleAttribute
    1613from twisted.python.versions import Version
    1714from twisted.words.protocols.jabber import xmlstream
    18 from twisted.words.protocols.jabber.xmlstream import XmlStreamServerFactory
    19 from twisted.words.xish.xmlstream import BootstrapMixin
    20 
    21 deprecatedModuleAttribute(
    22         Version("Wokkel", 0, 7, 0),
    23         "Use twisted.words.xish.xmlstream.BootstrapMixin instead.",
    24         __name__,
    25         "BootstrapMixin")
    26 
    27 deprecatedModuleAttribute(
    28         Version("Wokkel", 0, 7, 0),
    29         "Use twisted.words.protocols.jabber.xmlstream.XmlStreamServerFactory "
    30                 "instead.",
    31         __name__,
    32         "XmlStreamServerFactory")
    3315
    3416class IQ(xmlstream.IQ):
     
    5436
    5537
    56 _unspecified = object()
    57 _constantOrder = count().next
    58 
    59 
    60 class _Constant(object):
    61     """
    62     @ivar _index: A C{int} allocated from a shared counter in order to keep
    63         track of the order in which L{_Constant}s are instantiated.
    64 
    65     @ivar name: A C{str} giving the name of this constant; only set once the
    66         constant is initialized by L{_ConstantsContainer}.
    67 
    68     @ivar _container: The L{_ConstantsContainer} subclass this constant belongs
    69         to; only set once the constant is initialized by that subclass.
    70 
    71     @since: Twisted 12.0.0.
    72     """
    73     def __init__(self):
    74         self._index = _constantOrder()
    75 
    76 
    77     def __get__(self, oself, cls):
    78         """
    79         Ensure this constant has been initialized before returning it.
    80         """
    81         cls._initializeEnumerants()
    82         return self
    83 
    84 
    85     def __repr__(self):
    86         """
    87         Return text identifying both which constant this is and which collection
    88         it belongs to.
    89         """
    90         return "<%s=%s>" % (self._container.__name__, self.name)
    91 
    92 
    93     def _realize(self, container, name, value):
    94         """
    95         Complete the initialization of this L{_Constant}.
    96 
    97         @param container: The L{_ConstantsContainer} subclass this constant is
    98             part of.
    99 
    100         @param name: The name of this constant in its container.
    101 
    102         @param value: The value of this constant; not used, as named constants
    103             have no value apart from their identity.
    104         """
    105         self._container = container
    106         self.name = name
    107 
    108 
    109 
    110 class _EnumerantsInitializer(object):
    111     """
    112     L{_EnumerantsInitializer} is a descriptor used to initialize a cache of
    113     objects representing named constants for a particular L{_ConstantsContainer}
    114     subclass.
    115 
    116     @since: Twisted 12.0.0.
    117     """
    118     def __get__(self, oself, cls):
    119         """
    120         Trigger the initialization of the enumerants cache on C{cls} and then
    121         return it.
    122         """
    123         cls._initializeEnumerants()
    124         return cls._enumerants
    125 
    126 
    127 
    128 class _ConstantsContainer(object):
    129     """
    130     L{_ConstantsContainer} is a class with attributes used as symbolic
    131     constants.  It is up to subclasses to specify what kind of constants are
    132     allowed.
    133 
    134     @cvar _constantType: Specified by a L{_ConstantsContainer} subclass to
    135         specify the type of constants allowed by that subclass.
    136 
    137     @cvar _enumerantsInitialized: A C{bool} tracking whether C{_enumerants} has
    138         been initialized yet or not.
    139 
    140     @cvar _enumerants: A C{dict} mapping the names of constants (eg
    141         L{NamedConstant} instances) found in the class definition to those
    142         instances.  This is initialized via the L{_EnumerantsInitializer}
    143         descriptor the first time it is accessed.
    144 
    145     @since: Twisted 12.0.0.
    146     """
    147     _constantType = None
    148 
    149     _enumerantsInitialized = False
    150     _enumerants = _EnumerantsInitializer()
    151 
    152     def __new__(cls):
    153         """
    154         Classes representing constants containers are not intended to be
    155         instantiated.
    156 
    157         The class object itself is used directly.
    158         """
    159         raise TypeError("%s may not be instantiated." % (cls.__name__,))
    160 
    161 
    162     def _initializeEnumerants(cls):
    163         """
    164         Find all of the L{NamedConstant} instances in the definition of C{cls},
    165         initialize them with constant values, and build a mapping from their
    166         names to them to attach to C{cls}.
    167         """
    168         if not cls._enumerantsInitialized:
    169             constants = []
    170             for (name, descriptor) in cls.__dict__.iteritems():
    171                 if isinstance(descriptor, cls._constantType):
    172                     constants.append((descriptor._index, name, descriptor))
    173             enumerants = {}
    174             for (index, enumerant, descriptor) in constants:
    175                 value = cls._constantFactory(enumerant)
    176                 descriptor._realize(cls, enumerant, value)
    177                 enumerants[enumerant] = descriptor
    178             # Replace the _enumerants descriptor with the result so future
    179             # access will go directly to the values.  The _enumerantsInitialized
    180             # flag is still necessary because NamedConstant.__get__ may also
    181             # call this method.
    182             cls._enumerants = enumerants
    183             cls._enumerantsInitialized = True
    184     _initializeEnumerants = classmethod(_initializeEnumerants)
    185 
    186 
    187     def _constantFactory(cls, name):
    188         """
    189         Construct the value for a new constant to add to this container.
    190 
    191         @param name: The name of the constant to create.
    192 
    193         @return: L{NamedConstant} instances have no value apart from identity,
    194             so return a meaningless dummy value.
    195         """
    196         return _unspecified
    197     _constantFactory = classmethod(_constantFactory)
    198 
    199 
    200     def lookupByName(cls, name):
    201         """
    202         Retrieve a constant by its name or raise a C{ValueError} if there is no
    203         constant associated with that name.
    204 
    205         @param name: A C{str} giving the name of one of the constants defined by
    206             C{cls}.
    207 
    208         @raise ValueError: If C{name} is not the name of one of the constants
    209             defined by C{cls}.
    210 
    211         @return: The L{NamedConstant} associated with C{name}.
    212         """
    213         if name in cls._enumerants:
    214             return getattr(cls, name)
    215         raise ValueError(name)
    216     lookupByName = classmethod(lookupByName)
    217 
    218 
    219     def iterconstants(cls):
    220         """
    221         Iteration over a L{Names} subclass results in all of the constants it
    222         contains.
    223 
    224         @return: an iterator the elements of which are the L{NamedConstant}
    225             instances defined in the body of this L{Names} subclass.
    226         """
    227         constants = cls._enumerants.values()
    228         constants.sort(key=lambda descriptor: descriptor._index)
    229         return iter(constants)
    230     iterconstants = classmethod(iterconstants)
    231 
    232 
    233 
    234 class NamedConstant(_Constant):
    235     """
    236     L{NamedConstant} defines an attribute to be a named constant within a
    237     collection defined by a L{Names} subclass.
    238 
    239     L{NamedConstant} is only for use in the definition of L{Names}
    240     subclasses.  Do not instantiate L{NamedConstant} elsewhere and do not
    241     subclass it.
    242 
    243     @since: Twisted 12.0.0.
    244     """
    245 
    246 
    247 
    248 class Names(_ConstantsContainer):
    249     """
    250     A L{Names} subclass contains constants which differ only in their names and
    251     identities.
    252 
    253     @since: Twisted 12.0.0.
    254     """
    255     _constantType = NamedConstant
    256 
    257 
    258 
    259 class ValueConstant(_Constant):
    260     """
    261     L{ValueConstant} defines an attribute to be a named constant within a
    262     collection defined by a L{Values} subclass.
    263 
    264     L{ValueConstant} is only for use in the definition of L{Values} subclasses.
    265     Do not instantiate L{ValueConstant} elsewhere and do not subclass it.
    266 
    267     @since: Twisted 12.0.0.
    268     """
    269     def __init__(self, value):
    270         _Constant.__init__(self)
    271         self.value = value
    272 
    273 
    274 
    275 class Values(_ConstantsContainer):
    276     """
    277     A L{Values} subclass contains constants which are associated with arbitrary
    278     values.
    279 
    280     @since: Twisted 12.0.0.
    281     """
    282     _constantType = ValueConstant
    283 
    284     def lookupByValue(cls, value):
    285         """
    286         Retrieve a constant by its value or raise a C{ValueError} if there is no
    287         constant associated with that value.
    288 
    289         @param value: The value of one of the constants defined by C{cls}.
    290 
    291         @raise ValueError: If C{value} is not the value of one of the constants
    292             defined by C{cls}.
    293 
    294         @return: The L{ValueConstant} associated with C{value}.
    295         """
    296         for constant in cls.iterconstants():
    297             if constant.value == value:
    298                 return constant
    299         raise ValueError(value)
    300     lookupByValue = classmethod(lookupByValue)
     38__all__ = ['IQ']
  • wokkel/muc.py

    r166 r200  
    1212from dateutil.tz import tzutc
    1313
    14 from zope.interface import implements
     14from zope.interface import implementer
    1515
    1616from twisted.internet import defer
     17from twisted.python.constants import Values, ValueConstant
    1718from twisted.words.protocols.jabber import jid, error, xmlstream
    1819from twisted.words.xish import domish
    1920
    2021from wokkel import data_form, generic, iwokkel, xmppim
    21 from wokkel.compat import Values, ValueConstant
    2222from wokkel.delay import Delay, DelayMixin
    2323from wokkel.subprotocols import XMPPHandler
     
    6565
    6666
     67@implementer(iwokkel.IMUCStatuses)
    6768class Statuses(set):
    6869    """
     
    7677    U{XEP-0306<http://xmpp.org/extensions/xep-0306.html>}.
    7778    """
    78     implements(iwokkel.IMUCStatuses)
    7979
    8080
     
    12041204
    12051205
     1206@implementer(IMUCClient)
    12061207class MUCClient(MUCClientProtocol):
    12071208    """
     
    12151216    @type _rooms: C{dict}
    12161217    """
    1217 
    1218     implements(IMUCClient)
    12191218
    12201219    def __init__(self, reactor=None):
  • wokkel/test/test_compat.py

    r165 r200  
    77"""
    88
    9 from zope.interface import implements
     9from __future__ import division, absolute_import
     10
     11from zope.interface import implementer
    1012from twisted.internet import task
    1113from twisted.internet.interfaces import IReactorTime
     
    1416
    1517from wokkel.compat import IQ
    16 from wokkel.compat import NamedConstant, Names, ValueConstant, Values
    1718
    18 class DeprecationTest(unittest.TestCase):
    19     """
    20     Deprecation tests for L{wokkel.compat}.
    21     """
    22 
    23     def lookForDeprecationWarning(self, testmethod, attributeName, newName):
    24         """
    25         Importing C{testmethod} emits a deprecation warning.
    26         """
    27         warningsShown = self.flushWarnings([testmethod])
    28         self.assertEqual(len(warningsShown), 1)
    29         self.assertIdentical(warningsShown[0]['category'], DeprecationWarning)
    30         self.assertEqual(
    31             warningsShown[0]['message'],
    32             "wokkel.compat." + attributeName + " "
    33             "was deprecated in Wokkel 0.7.0: Use " + newName + " instead.")
    34 
    35 
    36     def test_bootstrapMixinTest(self):
    37         """
    38         L{compat.BootstrapMixin} is deprecated.
    39         """
    40         from wokkel.compat import BootstrapMixin
    41         BootstrapMixin
    42         self.lookForDeprecationWarning(
    43                 self.test_bootstrapMixinTest,
    44                 "BootstrapMixin",
    45                 "twisted.words.xish.xmlstream.BootstrapMixin")
    46 
    47 
    48     def test_xmlStreamServerFactory(self):
    49         """
    50         L{compat.XmlStreamServerFactory} is deprecated.
    51         """
    52         from wokkel.compat import XmlStreamServerFactory
    53         XmlStreamServerFactory
    54         self.lookForDeprecationWarning(
    55                 self.test_xmlStreamServerFactory,
    56                 "XmlStreamServerFactory",
    57                 "twisted.words.protocols.jabber.xmlstream."
    58                     "XmlStreamServerFactory")
    59 
    60 
    61 
     19@implementer(IReactorTime)
    6220class FakeReactor(object):
    6321
    64     implements(IReactorTime)
    6522    def __init__(self):
    6623        self.clock = task.Clock()
     
    9855        self.assertFalse(xs.iqDeferreds)
    9956        return d
    100 
    101 
    102 
    103 class NamedConstantTests(unittest.TestCase):
    104     """
    105     Tests for the L{twisted.python.constants.NamedConstant} class which is used
    106     to represent individual values.
    107     """
    108     def setUp(self):
    109         """
    110         Create a dummy container into which constants can be placed.
    111         """
    112         class foo(Names):
    113             pass
    114         self.container = foo
    115 
    116 
    117     def test_name(self):
    118         """
    119         The C{name} attribute of a L{NamedConstant} refers to the value passed
    120         for the C{name} parameter to C{_realize}.
    121         """
    122         name = NamedConstant()
    123         name._realize(self.container, "bar", None)
    124         self.assertEqual("bar", name.name)
    125 
    126 
    127     def test_representation(self):
    128         """
    129         The string representation of an instance of L{NamedConstant} includes
    130         the container the instances belongs to as well as the instance's name.
    131         """
    132         name = NamedConstant()
    133         name._realize(self.container, "bar", None)
    134         self.assertEqual("<foo=bar>", repr(name))
    135 
    136 
    137     def test_equality(self):
    138         """
    139         A L{NamedConstant} instance compares equal to itself.
    140         """
    141         name = NamedConstant()
    142         name._realize(self.container, "bar", None)
    143         self.assertTrue(name == name)
    144         self.assertFalse(name != name)
    145 
    146 
    147     def test_nonequality(self):
    148         """
    149         Two different L{NamedConstant} instances do not compare equal to each
    150         other.
    151         """
    152         first = NamedConstant()
    153         first._realize(self.container, "bar", None)
    154         second = NamedConstant()
    155         second._realize(self.container, "bar", None)
    156         self.assertFalse(first == second)
    157         self.assertTrue(first != second)
    158 
    159 
    160     def test_hash(self):
    161         """
    162         Because two different L{NamedConstant} instances do not compare as equal
    163         to each other, they also have different hashes to avoid collisions when
    164         added to a C{dict} or C{set}.
    165         """
    166         first = NamedConstant()
    167         first._realize(self.container, "bar", None)
    168         second = NamedConstant()
    169         second._realize(self.container, "bar", None)
    170         self.assertNotEqual(hash(first), hash(second))
    171 
    172 
    173 
    174 class _ConstantsTestsMixin(object):
    175     """
    176     Mixin defining test helpers common to multiple types of constants
    177     collections.
    178     """
    179     def _notInstantiableTest(self, name, cls):
    180         """
    181         Assert that an attempt to instantiate the constants class raises
    182         C{TypeError}.
    183 
    184         @param name: A C{str} giving the name of the constants collection.
    185         @param cls: The constants class to test.
    186         """
    187         exc = self.assertRaises(TypeError, cls)
    188         self.assertEqual(name + " may not be instantiated.", str(exc))
    189 
    190 
    191 
    192 class NamesTests(unittest.TestCase, _ConstantsTestsMixin):
    193     """
    194     Tests for L{twisted.python.constants.Names}, a base class for containers of
    195     related constaints.
    196     """
    197     def setUp(self):
    198         """
    199         Create a fresh new L{Names} subclass for each unit test to use.  Since
    200         L{Names} is stateful, re-using the same subclass across test methods
    201         makes exercising all of the implementation code paths difficult.
    202         """
    203         class METHOD(Names):
    204             """
    205             A container for some named constants to use in unit tests for
    206             L{Names}.
    207             """
    208             GET = NamedConstant()
    209             PUT = NamedConstant()
    210             POST = NamedConstant()
    211             DELETE = NamedConstant()
    212 
    213         self.METHOD = METHOD
    214 
    215 
    216     def test_notInstantiable(self):
    217         """
    218         A subclass of L{Names} raises C{TypeError} if an attempt is made to
    219         instantiate it.
    220         """
    221         self._notInstantiableTest("METHOD", self.METHOD)
    222 
    223 
    224     def test_symbolicAttributes(self):
    225         """
    226         Each name associated with a L{NamedConstant} instance in the definition
    227         of a L{Names} subclass is available as an attribute on the resulting
    228         class.
    229         """
    230         self.assertTrue(hasattr(self.METHOD, "GET"))
    231         self.assertTrue(hasattr(self.METHOD, "PUT"))
    232         self.assertTrue(hasattr(self.METHOD, "POST"))
    233         self.assertTrue(hasattr(self.METHOD, "DELETE"))
    234 
    235 
    236     def test_withoutOtherAttributes(self):
    237         """
    238         As usual, names not defined in the class scope of a L{Names}
    239         subclass are not available as attributes on the resulting class.
    240         """
    241         self.assertFalse(hasattr(self.METHOD, "foo"))
    242 
    243 
    244     def test_representation(self):
    245         """
    246         The string representation of a constant on a L{Names} subclass includes
    247         the name of the L{Names} subclass and the name of the constant itself.
    248         """
    249         self.assertEqual("<METHOD=GET>", repr(self.METHOD.GET))
    250 
    251 
    252     def test_lookupByName(self):
    253         """
    254         Constants can be looked up by name using L{Names.lookupByName}.
    255         """
    256         method = self.METHOD.lookupByName("GET")
    257         self.assertIdentical(self.METHOD.GET, method)
    258 
    259 
    260     def test_notLookupMissingByName(self):
    261         """
    262         Names not defined with a L{NamedConstant} instance cannot be looked up
    263         using L{Names.lookupByName}.
    264         """
    265         self.assertRaises(ValueError, self.METHOD.lookupByName, "lookupByName")
    266         self.assertRaises(ValueError, self.METHOD.lookupByName, "__init__")
    267         self.assertRaises(ValueError, self.METHOD.lookupByName, "foo")
    268 
    269 
    270     def test_name(self):
    271         """
    272         The C{name} attribute of one of the named constants gives that
    273         constant's name.
    274         """
    275         self.assertEqual("GET", self.METHOD.GET.name)
    276 
    277 
    278     def test_attributeIdentity(self):
    279         """
    280         Repeated access of an attribute associated with a L{NamedConstant} value
    281         in a L{Names} subclass results in the same object.
    282         """
    283         self.assertIdentical(self.METHOD.GET, self.METHOD.GET)
    284 
    285 
    286     def test_iterconstants(self):
    287         """
    288         L{Names.iterconstants} returns an iterator over all of the constants
    289         defined in the class, in the order they were defined.
    290         """
    291         constants = list(self.METHOD.iterconstants())
    292         self.assertEqual(
    293             [self.METHOD.GET, self.METHOD.PUT,
    294              self.METHOD.POST, self.METHOD.DELETE],
    295             constants)
    296 
    297 
    298     def test_attributeIterconstantsIdentity(self):
    299         """
    300         The constants returned from L{Names.iterconstants} are identical to the
    301         constants accessible using attributes.
    302         """
    303         constants = list(self.METHOD.iterconstants())
    304         self.assertIdentical(self.METHOD.GET, constants[0])
    305         self.assertIdentical(self.METHOD.PUT, constants[1])
    306         self.assertIdentical(self.METHOD.POST, constants[2])
    307         self.assertIdentical(self.METHOD.DELETE, constants[3])
    308 
    309 
    310     def test_iterconstantsIdentity(self):
    311         """
    312         The constants returned from L{Names.iterconstants} are identical on each
    313         call to that method.
    314         """
    315         constants = list(self.METHOD.iterconstants())
    316         again = list(self.METHOD.iterconstants())
    317         self.assertIdentical(again[0], constants[0])
    318         self.assertIdentical(again[1], constants[1])
    319         self.assertIdentical(again[2], constants[2])
    320         self.assertIdentical(again[3], constants[3])
    321 
    322 
    323     def test_initializedOnce(self):
    324         """
    325         L{Names._enumerants} is initialized once and its value re-used on
    326         subsequent access.
    327         """
    328         first = self.METHOD._enumerants
    329         self.METHOD.GET # Side-effects!
    330         second = self.METHOD._enumerants
    331         self.assertIdentical(first, second)
    332 
    333 
    334 
    335 class ValuesTests(unittest.TestCase, _ConstantsTestsMixin):
    336     """
    337     Tests for L{twisted.python.constants.Names}, a base class for containers of
    338     related constaints with arbitrary values.
    339     """
    340     def setUp(self):
    341         """
    342         Create a fresh new L{Values} subclass for each unit test to use.  Since
    343         L{Values} is stateful, re-using the same subclass across test methods
    344         makes exercising all of the implementation code paths difficult.
    345         """
    346         class STATUS(Values):
    347             OK = ValueConstant("200")
    348             NOT_FOUND = ValueConstant("404")
    349 
    350         self.STATUS = STATUS
    351 
    352 
    353     def test_notInstantiable(self):
    354         """
    355         A subclass of L{Values} raises C{TypeError} if an attempt is made to
    356         instantiate it.
    357         """
    358         self._notInstantiableTest("STATUS", self.STATUS)
    359 
    360 
    361     def test_symbolicAttributes(self):
    362         """
    363         Each name associated with a L{ValueConstant} instance in the definition
    364         of a L{Values} subclass is available as an attribute on the resulting
    365         class.
    366         """
    367         self.assertTrue(hasattr(self.STATUS, "OK"))
    368         self.assertTrue(hasattr(self.STATUS, "NOT_FOUND"))
    369 
    370 
    371     def test_withoutOtherAttributes(self):
    372         """
    373         As usual, names not defined in the class scope of a L{Values}
    374         subclass are not available as attributes on the resulting class.
    375         """
    376         self.assertFalse(hasattr(self.STATUS, "foo"))
    377 
    378 
    379     def test_representation(self):
    380         """
    381         The string representation of a constant on a L{Values} subclass includes
    382         the name of the L{Values} subclass and the name of the constant itself.
    383         """
    384         self.assertEqual("<STATUS=OK>", repr(self.STATUS.OK))
    385 
    386 
    387     def test_lookupByName(self):
    388         """
    389         Constants can be looked up by name using L{Values.lookupByName}.
    390         """
    391         method = self.STATUS.lookupByName("OK")
    392         self.assertIdentical(self.STATUS.OK, method)
    393 
    394 
    395     def test_notLookupMissingByName(self):
    396         """
    397         Names not defined with a L{ValueConstant} instance cannot be looked up
    398         using L{Values.lookupByName}.
    399         """
    400         self.assertRaises(ValueError, self.STATUS.lookupByName, "lookupByName")
    401         self.assertRaises(ValueError, self.STATUS.lookupByName, "__init__")
    402         self.assertRaises(ValueError, self.STATUS.lookupByName, "foo")
    403 
    404 
    405     def test_lookupByValue(self):
    406         """
    407         Constants can be looked up by their associated value, defined by the
    408         argument passed to L{ValueConstant}, using L{Values.lookupByValue}.
    409         """
    410         status = self.STATUS.lookupByValue("200")
    411         self.assertIdentical(self.STATUS.OK, status)
    412 
    413 
    414     def test_lookupDuplicateByValue(self):
    415         """
    416         If more than one constant is associated with a particular value,
    417         L{Values.lookupByValue} returns whichever of them is defined first.
    418         """
    419         class TRANSPORT_MESSAGE(Values):
    420             """
    421             Message types supported by an SSH transport.
    422             """
    423             KEX_DH_GEX_REQUEST_OLD = ValueConstant(30)
    424             KEXDH_INIT = ValueConstant(30)
    425 
    426         self.assertIdentical(
    427             TRANSPORT_MESSAGE.lookupByValue(30),
    428             TRANSPORT_MESSAGE.KEX_DH_GEX_REQUEST_OLD)
    429 
    430 
    431     def test_notLookupMissingByValue(self):
    432         """
    433         L{Values.lookupByValue} raises L{ValueError} when called with a value
    434         with which no constant is associated.
    435         """
    436         self.assertRaises(ValueError, self.STATUS.lookupByValue, "OK")
    437         self.assertRaises(ValueError, self.STATUS.lookupByValue, 200)
    438         self.assertRaises(ValueError, self.STATUS.lookupByValue, "200.1")
    439 
    440 
    441     def test_name(self):
    442         """
    443         The C{name} attribute of one of the constants gives that constant's
    444         name.
    445         """
    446         self.assertEqual("OK", self.STATUS.OK.name)
    447 
    448 
    449     def test_attributeIdentity(self):
    450         """
    451         Repeated access of an attribute associated with a L{ValueConstant} value
    452         in a L{Values} subclass results in the same object.
    453         """
    454         self.assertIdentical(self.STATUS.OK, self.STATUS.OK)
    455 
    456 
    457     def test_iterconstants(self):
    458         """
    459         L{Values.iterconstants} returns an iterator over all of the constants
    460         defined in the class, in the order they were defined.
    461         """
    462         constants = list(self.STATUS.iterconstants())
    463         self.assertEqual(
    464             [self.STATUS.OK, self.STATUS.NOT_FOUND],
    465             constants)
    466 
    467 
    468     def test_attributeIterconstantsIdentity(self):
    469         """
    470         The constants returned from L{Values.iterconstants} are identical to the
    471         constants accessible using attributes.
    472         """
    473         constants = list(self.STATUS.iterconstants())
    474         self.assertIdentical(self.STATUS.OK, constants[0])
    475         self.assertIdentical(self.STATUS.NOT_FOUND, constants[1])
    476 
    477 
    478     def test_iterconstantsIdentity(self):
    479         """
    480         The constants returned from L{Values.iterconstants} are identical on
    481         each call to that method.
    482         """
    483         constants = list(self.STATUS.iterconstants())
    484         again = list(self.STATUS.iterconstants())
    485         self.assertIdentical(again[0], constants[0])
    486         self.assertIdentical(again[1], constants[1])
    487 
    488 
    489     def test_initializedOnce(self):
    490         """
    491         L{Values._enumerants} is initialized once and its value re-used on
    492         subsequent access.
    493         """
    494         first = self.STATUS._enumerants
    495         self.STATUS.OK # Side-effects!
    496         second = self.STATUS._enumerants
    497         self.assertIdentical(first, second)
Note: See TracChangeset for help on using the changeset viewer.