"""Misc. class tests. These are more general class tests than CPython's test_class which focuses on operators. Made for Jython """ import __builtin__ import types import unittest from java.lang import Object from test import test_support class ClassGeneralTestCase(unittest.TestCase): TE_MSG = "can't set attributes of built-in/extension type 'str'" def test_dunder_module(self): self.assertEqual(str.__module__, '__builtin__') class Foo: pass Fu = types.ClassType('Fu', (), {}) for cls in Foo, Fu: self.assert_('__module__' in cls.__dict__) self.assertEqual(cls.__module__, __name__) self.assertEqual(str(cls), '%s.%s' % (__name__, cls.__name__)) self.assert_(repr(cls).startswith('" % (__name__, cls.__name__)) self.assertEqual(repr(cls), "" % (__name__, cls.__name__)) self.assert_(str(Bar()).startswith('<%s.Bar object at' % __name__)) self.assert_(str(Baz()).startswith("org.python.proxies.%s$Baz" % __name__)) def test_builtin_attributes(self): for attr, val in dict(__name__='foo', __module__='bar', __dict__={}, __flags__=1, __base__=object, __bases__=(unicode, object), __mro__=(unicode, object)).iteritems(): try: setattr(str, attr, val) except TypeError, te: self.assertEqual(str(te), self.TE_MSG) else: self.assert_(False, 'setattr str.%s expected a TypeError' % attr) try: delattr(str, attr) except TypeError, te: self.assertEqual(str(te), self.TE_MSG) else: self.assert_(False, 'delattr str.%s expected a TypeError' % attr) def test_attributes(self): class Foo(object): pass Foo.__name__ = 'Bar' self.assertEqual(Foo.__name__, 'Bar') try: del Foo.__name__ except TypeError, te: self.assertEqual(str(te), "can't delete Bar.__name__") else: self.assert_(False, 'Expected a TypeError') Foo.__module__ = 'baz' self.assertEqual(Foo.__module__, 'baz') try: del Foo.__module__ except TypeError, te: self.assertEqual(str(te), "can't delete Bar.__module__") else: self.assert_(False, 'Expected a TypeError') try: Foo.__dict__ = {} except AttributeError, ae: self.assertEqual(str(ae), "attribute '__dict__' of 'type' objects is not " "writable") else: self.assert_(False, 'Expected an AttributeError') try: del Foo.__dict__ except AttributeError, ae: self.assertEqual(str(ae), "attribute '__dict__' of 'type' objects is not " "writable") else: self.assert_(False, 'Expected an AttributeError') for attr, val in dict(__flags__=1, __base__=object, __bases__=(unicode, object), __mro__=(unicode, object)).iteritems(): try: setattr(str, attr, val) except TypeError, te: self.assertEqual(str(te), self.TE_MSG) else: self.assert_(False, 'setattr Foo.%s expected a TypeError' % attr) try: delattr(str, attr) except TypeError, te: self.assertEqual(str(te), self.TE_MSG) else: self.assert_(False, 'delattr Foo.%s expected a TypeError' % attr) def test_newstyle_new_classobj(self): # Ensure new.classobj can create new style classes class Foo(object): pass def hello(self): return 'hello' Bar = types.ClassType('Bar', (Foo,), dict(hello=hello)) self.assert_(type(Bar), type) self.assert_(issubclass(Bar, Foo)) self.assert_(hasattr(Bar, 'hello')) self.assertEquals(Bar().hello(), 'hello') def test_attribute_error_message(self): # Ensure that AttributeError matches the CPython message class Bar: pass try: Bar.bar self._assert(False) # The previous line should have raised # AttributeError except AttributeError, e: self.assertEqual("class Bar has no attribute 'bar'", str(e)) class Foo(object): pass try: Foo.bar self._assert(False) # The previous line should have raised # AttributeError except AttributeError, e: self.assertEqual("type object 'Foo' has no attribute 'bar'", str(e)) def test_inner_class_dict(self): class z: class t: def moo(self): pass # Printing this caused an NPE in Jython 2.1 keys = list(z.t.__dict__) keys.sort() self.assertEqual(str(keys), "['__doc__', '__module__', 'moo']") def test_metaclass_and_slotted_base(self): class Meta(type): pass class SlottedBase(object): __slots__ = 'foo' # A regression up until 2.5a3: Defining Bar would cause a # TypeError "mro() returned base with unsuitable layout ('Bar')" class Bar(SlottedBase): __metaclass__ = Meta def test_slotted_diamond_problem_bug(self): class A(object): __slots__ = 'foo' class B(A): pass class C(A): pass # used to raise TypeError: multiple bases have instance lay-out # conflict class D(B, C): pass def test_getitem_exceptions(self): class A: def __getitem__(self, key): raise IndexError, "Fraid not" self.assertRaises(IndexError, A().__getitem__, 'b') class ClassNamelessModuleTestCase(unittest.TestCase): def setUp(self): global __name__ self.name = __name__ del __name__ def tearDown(self): global __name__ __name__ = self.name def test_nameless_module(self): class Foo: pass self.assertEqual(Foo.__module__, '__builtin__') self.assertEqual(str(Foo), '__builtin__.Foo') self.assert_(repr(Foo).startswith('") self.assertEqual(repr(Bar), "") bar = Bar() self.assert_(str(bar).startswith('" % __name__, repr(Foo)) def test_metaclass_str(self): class Foo(type): def __repr__(cls): return 'foo' class Bar(object): __metaclass__ = Foo self.assertEqual(repr(Bar), 'foo') # type.__str__ previously broke this self.assertEqual(str(Bar), 'foo') def test_main(): test_support.run_unittest( ClassGeneralTestCase, ClassNamelessModuleTestCase, BrokenNameTestCase, ClassLocalsTestCase, IsDescendentTestCase, JavaClassNamingTestCase, ClassDefinesDunderModule, ClassMetaclassRepr) if __name__ == "__main__": test_main()