--- /dev/null
+#!/usr/bin/env python
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import unittest
+
+# Import from this module's parent directory.
+import os
+import sys
+sys.path.insert(0, os.pardir)
+import introspect
+del sys.path[0]
+del sys
+del os
+
+
+"""
+These unittest methods are preferred:
+-------------------------------------
+self.assert_(expr, msg=None)
+self.assertEqual(first, second, msg=None)
+self.assertRaises(excClass, callableObj, *args, **kwargs)
+self.fail(msg=None)
+self.failIf(expr, msg=None)
+"""
+
+
+class ModuleTestCase(unittest.TestCase):
+
+ def test_module(self):
+ module = introspect
+ self.assert_(module.__author__)
+ self.assert_(module.__cvsid__)
+ self.assert_(module.__revision__)
+ self.assert_(module.getAllAttributeNames)
+ self.assert_(module.getAttributeNames)
+ self.assert_(module.getAutoCompleteList)
+ self.assert_(module.getBaseObject)
+ self.assert_(module.getCallTip)
+ self.assert_(module.getConstructor)
+ self.assert_(module.getRoot)
+ self.assert_(module.rtrimTerminus)
+
+
+class RtrimTerminusTestCase(unittest.TestCase):
+
+ def test_rtrimTerminus(self):
+ values = (
+ ('', '', ''),
+ ('', None, ''),
+ ('', '.', ''),
+ ('', '(', ''),
+
+ ('.', '', '.'),
+ ('.', None, '.'),
+ ('.', '.', '.'),
+ ('.', '(', '.'),
+
+ ('(', '', '('),
+ ('(', None, '('),
+ ('(', '.', '('),
+ ('(', '(', '('),
+
+ ('spam', '', 'spam'),
+ ('spam', None, 'spam'),
+ ('spam', '.', 'spam'),
+ ('spam', '(', 'spam'),
+
+ ('spam.', '', 'spam.'),
+ ('spam.', None, 'spam.'),
+ ('spam.', '.', 'spam.'),
+ ('spam.', '(', 'spam.'),
+
+ ('spam(', '', 'spam('),
+ ('spam(', None, 'spam('),
+ ('spam(', '.', 'spam('),
+ ('spam(', '(', 'spam('),
+
+ ('spam.eggs', '.', 'spam.'),
+ ('spam.eggs.', '.', 'spam.eggs.'),
+ ('spam.eggs(', '(', 'spam.eggs('),
+ ('spam.eggs.', '(', 'spam.eggs.'),
+ ('spam.eggs(', '.', 'spam.'),
+
+ ('x = spam.', '.', 'x = spam.'),
+ ('x = spam.eggs', '.', 'x = spam.'),
+ ('x = spam.eggs.', '.', 'x = spam.eggs.'),
+ ('x = spam.eggs(', '(', 'x = spam.eggs('),
+ )
+ for input, terminator, output in values:
+ result = introspect.rtrimTerminus(input, terminator)
+ self.assertEqual(result, output,
+ ':in: %r :t: %r :out: %r :result: %r' %
+ (input, terminator, output, result))
+
+
+class GetRootTestCase(unittest.TestCase):
+
+ def _checkRoot(self, input, terminator, output):
+ root = introspect.getRoot(command=input, terminator=terminator)
+ self.assertEqual(root, output,
+ ':in: %r :t: %r :out: %r :root: %r' %
+ (input, terminator, output, root))
+
+ def test_getRoot(self):
+ values = (
+ ('', '', ''),
+ ('', None, ''),
+ ('', '.', ''),
+ ('', '(', ''),
+
+ ('.', '', '.'),
+ ('.', None, '.'),
+ ('.', '.', ''),
+ ('.', '(', '.'),
+
+ ('(', '', ''),
+ ('(', None, ''),
+ ('(', '.', ''),
+ ('(', '(', ''),
+
+ ('spam', '', 'spam'),
+ ('spam', None, 'spam'),
+ ('spam', '.', ''),
+ ('spam', '(', 'spam'),
+
+ ('spam.', '', 'spam.'),
+ ('spam.', None, 'spam.'),
+ ('spam.', '.', 'spam'),
+ ('spam.', '(', 'spam.'),
+
+ ('spam(', '', ''),
+ ('spam(', None, ''),
+ ('spam(', '.', ''),
+ ('spam(', '(', 'spam'),
+
+ ('spam.eggs', '.', 'spam'),
+ ('spam.eggs.', '.', 'spam.eggs'),
+ ('spam.eggs(', '(', 'spam.eggs'),
+ ('spam.eggs.', '(', 'spam.eggs.'),
+ ('spam.eggs(', '.', 'spam'),
+
+ ('x = spam.', '.', 'spam'),
+ ('x = spam.eggs', '.', 'spam'),
+ ('x = spam.eggs.', '.', 'spam.eggs'),
+ ('x = spam.eggs(', '(', 'spam.eggs'),
+
+ ('for n in range(3):\n d.', '.', 'd'),
+ ('for n in range(3):\n... d.', '.', 'd'),
+ )
+ for input, terminator, output in values:
+ self._checkRoot(input, terminator, output)
+
+ def test_getRoot_Advanced(self):
+ values = (
+ ('spam_', '', 'spam_'),
+ ('spam_', None, 'spam_'),
+ ('spam_', '.', ''),
+ ('spam_', '(', 'spam_'),
+
+ ('_spam', '', '_spam'),
+ ('_spam', None, '_spam'),
+ ('_spam', '.', ''),
+ ('_spam', '(', '_spam'),
+
+ ('spam_eggs', '', 'spam_eggs'),
+ ('spam_eggs', None, 'spam_eggs'),
+ ('spam_eggs', '.', ''),
+ ('spam_eggs', '(', 'spam_eggs'),
+
+ ('spam123', '', 'spam123'),
+ ('spam123', None, 'spam123'),
+ ('spam123', '.', ''),
+ ('spam123', '(', 'spam123'),
+
+ ('spam_123', '', 'spam_123'),
+ ('spam_123', None, 'spam_123'),
+ ('spam_123', '.', ''),
+ ('spam_123', '(', 'spam_123'),
+ )
+ for input, terminator, output in values:
+ self._checkRoot(input, terminator, output)
+
+## The original intent was to detect when we were inside a string.
+## That has proven to be very difficult, for little benefit.
+## The fact that autocomplete or calltips might be triggered inside
+## a string is not a big deal. Sometimes it is even helpful.
+
+## def test_getRoot_InsideStrings(self):
+## values = (
+## ('x = ".', '.', ''),
+## ("x = '.", '.', ''),
+## ('x = """.', '.', ''),
+## ("x = '''.", '.', ''),
+##
+## ('x = "(', '(', ''),
+## ("x = '(", '(', ''),
+## ('x = """(', '(', ''),
+## ("x = '''(", '(', ''),
+##
+## ('x = "spam', '.', ''),
+## ('x = "spam.', '.', ''),
+## ("x = 'spam.", '.', ''),
+## ('x = """spam.', '.', ''),
+## ("x = '''spam.", '.', ''),
+##
+## ('x = "spam', '(', ''),
+## ('x = "spam(', '(', ''),
+## ("x = 'spam(", '(', ''),
+## ('x = """spam(', '(', ''),
+## ("x = '''spam(", '(', ''),
+##
+## ('x = "spam.eggs.', '.', ''),
+## ("x = 'spam.eggs.", '.', ''),
+## ('x = """spam.eggs.', '.', ''),
+## ("x = '''spam.eggs.", '.', ''),
+##
+## ('x = "spam.eggs(', '(', ''),
+## ("x = 'spam.eggs(", '(', ''),
+## ('x = """spam.eggs(', '(', ''),
+## ("x = '''spam.eggs(", '(', ''),
+## )
+## for input, terminator, output in values:
+## self._checkRoot(input, terminator, output)
+
+ def test_getRoot_EmptyTypes(self):
+ values = (
+ ("''.", '.', "''"),
+ ('"".', '.', '""'),
+ ('"""""".', '.', '""""""'),
+ ("''''''.", '.', "''''''"),
+
+ ('[].', '.', '[]'),
+ ('().', '.', '()'),
+ ('{}.', '.', '{}'),
+
+ ('[](', '(', '[]'),
+ ('()(', '(', '()'),
+ ('{}(', '(', '{}'),
+
+ ("x = ''.", '.', "''"),
+ ('x = "".', '.', '""'),
+ ('x = """""".', '.', '""""""'),
+ ("x = ''''''.", '.', "''''''"),
+
+ ('x = [].', '.', '[]'),
+ ('x = ().', '.', '()'),
+ ('x = {}.', '.', '{}'),
+
+ ('x = [](', '(', '[]'),
+ ('x = ()(', '(', '()'),
+ ('x = {}(', '(', '{}'),
+
+ ('print [].', '.', '[]'),
+ ('print ().', '.', '()'),
+ ('print {}.', '.', '{}'),
+
+ ('print [](', '(', '[]'),
+ ('print ()(', '(', '()'),
+ ('print {}(', '(', '{}'),
+
+ ("''.attr.", '.', "''.attr"),
+ ('"".attr.', '.', '"".attr'),
+ ('"""""".attr.', '.', '"""""".attr'),
+ ("''''''.attr.", '.', "''''''.attr"),
+
+ ('[].attr.', '.', '[].attr'),
+ ('().attr.', '.', '().attr'),
+ ('{}.attr.', '.', '{}.attr'),
+
+ ('[].attr(', '(', '[].attr'),
+ ('().attr(', '(', '().attr'),
+ ('{}.attr(', '(', '{}.attr'),
+
+ ('spam().', '.', ''),
+ ('spam_().', '.', ''),
+ ('spam5().', '.', ''),
+ ('spam[]().', '.', ''),
+ ('spam()[].', '.', ''),
+ ('spam[]{}.', '.', ''),
+
+ ("spam(''.", '.', "''"),
+ ('spam("".', '.', '""'),
+ ('spam("""""".', '.', '""""""'),
+ ("spam(''''''.", '.', "''''''"),
+
+ ('spam([].', '.', '[]'),
+ ('spam(().', '.', '()'),
+ ('spam({}.', '.', '{}'),
+ ('spam[[].', '.', '[]'),
+ ('spam[().', '.', '()'),
+ ('spam[{}.', '.', '{}'),
+ ('x = {[].', '.', '[]'),
+ ('x = {().', '.', '()'),
+ ('x = {{}.', '.', '{}'),
+
+ ('spam,[].', '.', '[]'),
+ ('spam+[].', '.', '[]'),
+ ('spam-[].', '.', '[]'),
+ ('spam*[].', '.', '[]'),
+ ('spam/[].', '.', '[]'),
+ ('spam=[].', '.', '[]'),
+ ('spam%[].', '.', '[]'),
+ ('spam<[].', '.', '[]'),
+ ('spam>[].', '.', '[]'),
+ ('spam&[].', '.', '[]'),
+ ('spam|[].', '.', '[]'),
+ ('spam^[].', '.', '[]'),
+ ('spam~[].', '.', '[]'),
+ ('spam:[].', '.', '[]'),
+
+ ('spam,().', '.', '()'),
+ ('spam+().', '.', '()'),
+ ('spam-().', '.', '()'),
+ ('spam*().', '.', '()'),
+ ('spam/().', '.', '()'),
+ ('spam=().', '.', '()'),
+ ('spam%().', '.', '()'),
+ ('spam<().', '.', '()'),
+ ('spam>().', '.', '()'),
+ ('spam&().', '.', '()'),
+ ('spam|().', '.', '()'),
+ ('spam^().', '.', '()'),
+ ('spam~().', '.', '()'),
+ ('spam:().', '.', '()'),
+
+ ('spam,{}.', '.', '{}'),
+ ('spam+{}.', '.', '{}'),
+ ('spam-{}.', '.', '{}'),
+ ('spam*{}.', '.', '{}'),
+ ('spam/{}.', '.', '{}'),
+ ('spam={}.', '.', '{}'),
+ ('spam%{}.', '.', '{}'),
+ ('spam<{}.', '.', '{}'),
+ ('spam>{}.', '.', '{}'),
+ ('spam&{}.', '.', '{}'),
+ ('spam|{}.', '.', '{}'),
+ ('spam^{}.', '.', '{}'),
+ ('spam~{}.', '.', '{}'),
+ ('spam:{}.', '.', '{}'),
+ )
+ for input, terminator, output in values:
+ self._checkRoot(input, terminator, output)
+
+
+# Support for GetBaseObjectTestCase and GetAttributeNamesTestCase.
+
+class Foo:
+ def __init__(self):
+ pass
+
+ def __del__(self):
+ pass
+
+ def _private(self):
+ pass
+
+class Bar:
+ pass
+
+class Spam:
+ def __call__(self):
+ pass
+
+ def foo(self):
+ pass
+
+ def bar(spam):
+ # It shouldn't matter what we call "self".
+ pass
+
+ def eggs(self):
+ pass
+
+def ham(eggs):
+ pass
+
+class GetBaseObjectTestCase(unittest.TestCase):
+
+ def test_getBaseObject(self):
+ spam = Spam()
+ eggs = Spam.eggs
+ listappend = [].append
+ spamda = lambda: None
+ values = (
+ ('spam', 'spam', 0),
+ (123, 123, 0),
+ (12.3, 12.3, 0),
+ ([], [], 0),
+ ((), (), 0),
+ ({}, {}, 0),
+ # Builtin function.
+ (len, len, 0),
+ # Builtin method.
+ (listappend, listappend, 0),
+ # User function.
+ (ham, ham, 0),
+ # Byte-compiled code.
+ (ham.func_code, ham.func_code, 0),
+ # Lambda.
+ (spamda, spamda, 0),
+ # Class with init.
+ (Foo, Foo.__init__.im_func, 1),
+ # Class with no init.
+ (Bar, Bar, 0),
+ # Bound method.
+ (spam.foo, spam.foo.im_func, 1),
+ # Bound method with self named something else (spam).
+ (spam.bar, spam.bar.im_func, 1),
+ # Unbound method. (Do not drop the self argument.)
+ (eggs, eggs.im_func, 0),
+ # Callable instance.
+ (spam, spam.__call__.im_func, 1),
+ )
+ for object, baseObject, dropSelf in values:
+ result = introspect.getBaseObject(object)
+ self.assertEqual(result, (baseObject, dropSelf))
+
+
+class GetAttributeTestCase(unittest.TestCase):
+ """Base class for other test case classes."""
+
+ def setUp(self):
+ self.values = (
+ '__abs__',
+ '__add__',
+ '__and__',
+ '__base__',
+ '__bases__',
+ '__basicsize__',
+ '__builtins__',
+ '__call__',
+ '__class__',
+ '__cmp__',
+ '__coerce__',
+ '__contains__',
+ '__del__',
+ '__delattr__',
+ '__delitem__',
+ '__delslice__',
+ '__dict__',
+ '__dictoffset__',
+ '__div__',
+ '__divmod__',
+ '__doc__',
+ '__eq__',
+ '__file__',
+ '__flags__',
+ '__float__',
+ '__floordiv__',
+ '__ge__',
+ '__get__',
+ '__getattr__',
+ '__getattribute__',
+ '__getitem__',
+ '__getslice__',
+ '__gt__',
+ '__hash__',
+ '__hex__',
+ '__iadd__',
+ '__imul__',
+ '__init__',
+ '__int__',
+ '__invert__',
+ '__itemsize__',
+ '__iter__',
+ '__le__',
+ '__len__',
+ '__long__',
+ '__lshift__',
+ '__lt__',
+ '__mod__',
+ '__module__',
+ '__mro__',
+ '__mul__',
+ '__name__',
+ '__ne__',
+ '__neg__',
+ '__new__',
+ '__nonzero__',
+ '__oct__',
+ '__or__',
+ '__path__',
+ '__pos__',
+ '__pow__',
+ '__radd__',
+ '__rand__',
+ '__rdiv__',
+ '__rdivmod__',
+ '__reduce__',
+ '__repr__',
+ '__rfloordiv__',
+ '__rlshift__',
+ '__rmod__',
+ '__rmul__',
+ '__ror__',
+ '__rpow__',
+ '__rrshift__',
+ '__rshift__',
+ '__rsub__',
+ '__rtruediv__',
+ '__rxor__',
+ '__self__',
+ '__setattr__',
+ '__setitem__',
+ '__setslice__',
+ '__str__',
+ '__sub__',
+ '__subclasses__',
+ '__truediv__',
+ '__warningregistry__',
+ '__weakrefoffset__',
+ '__xor__',
+ 'append',
+ 'capitalize',
+ 'center',
+ 'clear',
+ 'close',
+ 'closed',
+ 'co_argcount',
+ 'co_cellvars',
+ 'co_code',
+ 'co_consts',
+ 'co_filename',
+ 'co_firstlineno',
+ 'co_flags',
+ 'co_freevars',
+ 'co_lnotab',
+ 'co_name',
+ 'co_names',
+ 'co_nlocals',
+ 'co_stacksize',
+ 'co_varnames',
+ 'conjugate',
+ 'copy',
+ 'count',
+ 'decode',
+ 'encode',
+ 'endswith',
+ 'expandtabs',
+ 'extend',
+ 'fileno',
+ 'find',
+ 'flush',
+ 'func_closure',
+ 'func_code',
+ 'func_defaults',
+ 'func_dict',
+ 'func_doc',
+ 'func_globals',
+ 'func_name',
+ 'get',
+ 'has_key',
+ 'im_class',
+ 'im_func',
+ 'im_self',
+ 'imag',
+ 'index',
+ 'insert',
+ 'isalnum',
+ 'isalpha',
+ 'isatty',
+ 'isdigit',
+ 'islower',
+ 'isspace',
+ 'istitle',
+ 'isupper',
+ 'items',
+ 'iteritems',
+ 'iterkeys',
+ 'itervalues',
+ 'join',
+ 'keys',
+ 'ljust',
+ 'lower',
+ 'lstrip',
+ 'mode',
+ 'mro',
+ 'name',
+ 'pop',
+ 'popitem',
+ 'real',
+ 'read',
+ 'readinto',
+ 'readline',
+ 'readlines',
+ 'remove',
+ 'replace',
+ 'reverse',
+ 'rfind',
+ 'rindex',
+ 'rjust',
+ 'rstrip',
+ 'seek',
+ 'setdefault',
+ 'softspace',
+ 'sort',
+ 'split',
+ 'splitlines',
+ 'start',
+ 'startswith',
+ 'step',
+ 'stop',
+ 'strip',
+ 'swapcase',
+ 'tell',
+ 'title',
+ 'tolist',
+ 'translate',
+ 'truncate',
+ 'update',
+ 'upper',
+ 'values',
+ 'write',
+ 'writelines',
+ 'xreadlines',
+ )
+
+# Since getAllAttributeNames() calls str(object),
+# we need to test for a broken __str__ method.
+class BrokenStr:
+ def __str__(self):
+ raise Exception
+
+brokenStr = BrokenStr()
+
+class GetAttributeNamesTestCase(GetAttributeTestCase):
+
+ def setUp(self):
+ GetAttributeTestCase.setUp(self)
+ import PyCrust
+ spam = Spam()
+ self.f = open('test_introspect.py')
+ self.items = (
+ None,
+ int(123),
+ long(123),
+ float(123),
+ complex(123),
+ "",
+ unicode(""),
+ [],
+ (),
+ xrange(0),
+ {},
+ # Builtin function.
+ len,
+ # Builtin method.
+ [].append,
+ # User function.
+ ham,
+ # Byte-compiled code.
+ ham.func_code,
+ # Lambda.
+ lambda: None,
+ # Class with no init.
+ Bar,
+ # Instance with no init.
+ Bar(),
+ # Class with init and del.
+ Foo,
+ # Instance with init and del.
+ Foo(),
+ # Bound method.
+ spam.foo,
+ # Unbound method.
+ Spam.eggs,
+ # Callable instance.
+ spam,
+ # Module.
+ introspect,
+ # Package.
+ PyCrust,
+ # Buffer.
+ buffer(''),
+ # File.
+ self.f,
+ # Slice.
+ slice(0),
+ # Ellipsis.
+ Ellipsis,
+ # BrokenStr class.
+ BrokenStr,
+ # BrokenStr instance.
+ brokenStr,
+ )
+
+ def tearDown(self):
+ self.items = None
+ self.f.close()
+
+ def test_getAttributeNames(self):
+ for item in self.items:
+ self._checkAttributeNames(item)
+ if __builtins__.has_key('object'):
+ self._checkAttributeNames(object)
+
+ def test_getAttributeNames_NoSingle(self):
+ for item in self.items:
+ result = introspect.getAttributeNames(item, includeSingle=0)
+ attributes = [attribute for attribute in result \
+ if attribute[0] != '_' or attribute[:2] == '__']
+ self.assertEqual(result, attributes,
+ ':item: %r' % (item,))
+
+ def test_getAttributeNames_NoDouble(self):
+ for item in self.items:
+ result = introspect.getAttributeNames(item, includeDouble=0)
+ attributes = [attribute for attribute in result \
+ if attribute[:2] != '__']
+ self.assertEqual(result, attributes,
+ ':item: %r' % (item,))
+
+ def test_getAttributeNames_NoSingleOrDouble(self):
+ for item in self.items:
+ result = introspect.getAttributeNames(item, includeSingle=0,
+ includeDouble=0)
+ attributes = [attribute for attribute in result \
+ if attribute[0] != '_']
+ self.assertEqual(result, attributes,
+ ':item: %r' % (item,))
+
+ def _checkAttributeNames(self, item):
+ result = introspect.getAttributeNames(item)
+ attributes = [attribute for attribute in self.values \
+ if hasattr(item, attribute)]
+ for attribute in attributes:
+ self.assert_(attribute in result,
+ ':item: %r :attribute: %r' % (item, attribute))
+
+
+class GetAutoCompleteListTestCase(GetAttributeTestCase):
+
+ def setUp(self):
+ GetAttributeTestCase.setUp(self)
+ self.items = (
+ 'None.',
+ '123 .',
+ '"".',
+ '[].',
+ '().',
+ '{}.',
+ # Builtin function.
+ 'len.',
+ # Builtin method.
+ '[].append.',
+ )
+
+ def test_getAutoCompleteList(self):
+ for item in self.items:
+ result = introspect.getAutoCompleteList(item)
+ object = eval(item[:-1])
+ attributes = [attribute for attribute in self.values \
+ if hasattr(object, attribute)]
+ for attribute in attributes:
+ self.assert_(attribute in result,
+ ':item: %r :attribute: %r' % (item, attribute))
+
+ def test_getAutoCompleteList_NoSingle(self):
+ for item in self.items:
+ result = introspect.getAutoCompleteList(item, includeSingle=0)
+ attributes = [attribute for attribute in result \
+ if attribute[0] != '_' or attribute[:2] == '__']
+ self.assertEqual(result, attributes,
+ ':item: %r' % (item,))
+
+ def test_getAutoCompleteList_NoDouble(self):
+ for item in self.items:
+ result = introspect.getAutoCompleteList(item, includeDouble=0)
+ attributes = [attribute for attribute in result \
+ if attribute[:2] != '__']
+ self.assertEqual(result, attributes,
+ ':item: %r' % (item,))
+
+ def test_getAutoCompleteList_NoSingleOrDouble(self):
+ for item in self.items:
+ result = introspect.getAutoCompleteList(item, includeSingle=0,
+ includeDouble=0)
+ attributes = [attribute for attribute in result \
+ if attribute[0] != '_']
+ self.assertEqual(result, attributes,
+ ':item: %r' % (item,))
+
+
+# Support for GetConstructorTestCase.
+
+class A1:
+ def __init__(self, a):
+ self.a = a
+
+class B1(A1):
+ def __init__(self, b):
+ self.b = b
+
+class C1(A1):
+ pass
+
+class D1(C1, B1):
+ pass
+
+if __builtins__.has_key('object'):
+ class A2(object):
+ def __init__(self, a):
+ self.a = a
+
+ class B2(A2):
+ def __init__(self, b):
+ self.b = b
+
+ class C2(A2):
+ pass
+
+ class D2(C2, B2):
+ pass
+
+class N:
+ pass
+
+class O:
+ def __init__(self, a, b=2, *args, **kwargs):
+ pass
+
+class P(O):
+ pass
+
+class Q(P):
+ def __init__(self, c, d=4):
+ pass
+
+class GetConstructorTestCase(unittest.TestCase):
+
+ def test_getConstructor(self):
+ args = ('self', 'a', 'b', 'args', 'kwargs')
+ varnames = introspect.getConstructor(O).func_code.co_varnames
+ self.assertEqual(varnames, args)
+ varnames = introspect.getConstructor(P).func_code.co_varnames
+ self.assertEqual(varnames, args)
+ args = ('self', 'c', 'd')
+ varnames = introspect.getConstructor(Q).func_code.co_varnames
+ self.assertEqual(varnames, args)
+
+ def test_getConstructor_None(self):
+ values = (N, 1, 'spam', {}, [], (), dir)
+ for value in values:
+ self.assertEqual(introspect.getConstructor(N), None)
+
+ def test_getConstructor_MultipleInheritance(self):
+ # Test old style inheritance rules.
+ args = ('self', 'a')
+ varnames = introspect.getConstructor(D1).func_code.co_varnames
+ self.assertEqual(varnames, args)
+ if __builtins__.has_key('object'):
+ # Test new style inheritance rules as well.
+ args = ('self', 'b')
+ varnames = introspect.getConstructor(D2).func_code.co_varnames
+ self.assertEqual(varnames, args)
+
+
+if __name__ == '__main__':
+ unittest.main()