PageRenderTime 73ms CodeModel.GetById 15ms app.highlight 54ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_funcattrs.py

http://unladen-swallow.googlecode.com/
Python | 282 lines | 265 code | 9 blank | 8 comment | 8 complexity | 3512f058d8ad358e964385ac4480c570 MD5 | raw file
  1from test import test_support
  2import types
  3import unittest
  4
  5class FuncAttrsTest(unittest.TestCase):
  6    def setUp(self):
  7        class F:
  8            def a(self):
  9                pass
 10        def b():
 11            return 3
 12        self.f = F
 13        self.fi = F()
 14        self.b = b
 15
 16    def cannot_set_attr(self,obj, name, value, exceptions):
 17        # This method is not called as a test (name doesn't start with 'test'),
 18        # but may be used by other tests.
 19        try: setattr(obj, name, value)
 20        except exceptions: pass
 21        else: self.fail("shouldn't be able to set %s to %r" % (name, value))
 22        try: delattr(obj, name)
 23        except exceptions: pass
 24        else: self.fail("shouldn't be able to del %s" % name)
 25
 26
 27class FunctionPropertiesTest(FuncAttrsTest):
 28    # Include the external setUp method that is common to all tests
 29    def test_module(self):
 30        self.assertEqual(self.b.__module__, __name__)
 31
 32    def test_dir_includes_correct_attrs(self):
 33        self.b.known_attr = 7
 34        self.assert_('known_attr' in dir(self.b),
 35            "set attributes not in dir listing of method")
 36        # Test on underlying function object of method
 37        self.f.a.im_func.known_attr = 7
 38        self.assert_('known_attr' in dir(self.f.a),
 39            "set attribute on unbound method implementation in class not in "
 40                     "dir")
 41        self.assert_('known_attr' in dir(self.fi.a),
 42            "set attribute on unbound method implementations, should show up"
 43                     " in next dir")
 44
 45    def test_duplicate_function_equality(self):
 46        # Body of `duplicate' is the exact same as self.b
 47        def duplicate():
 48            'my docstring'
 49            return 3
 50        self.assertNotEqual(self.b, duplicate)
 51
 52    def test_copying_func_code(self):
 53        def test(): pass
 54        self.assertEqual(test(), None)
 55        test.func_code = self.b.func_code
 56        self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily
 57
 58    def test_func_globals(self):
 59        self.assertEqual(self.b.func_globals, globals())
 60        self.cannot_set_attr(self.b, 'func_globals', 2, TypeError)
 61
 62    def test_func_name(self):
 63        self.assertEqual(self.b.__name__, 'b')
 64        self.assertEqual(self.b.func_name, 'b')
 65        self.b.__name__ = 'c'
 66        self.assertEqual(self.b.__name__, 'c')
 67        self.assertEqual(self.b.func_name, 'c')
 68        self.b.func_name = 'd'
 69        self.assertEqual(self.b.__name__, 'd')
 70        self.assertEqual(self.b.func_name, 'd')
 71        # __name__ and func_name must be a string
 72        self.cannot_set_attr(self.b, '__name__', 7, TypeError)
 73        self.cannot_set_attr(self.b, 'func_name', 7, TypeError)
 74        # __name__ must be available when in restricted mode. Exec will raise
 75        # AttributeError if __name__ is not available on f.
 76        s = """def f(): pass\nf.__name__"""
 77        exec s in {'__builtins__': {}}
 78        # Test on methods, too
 79        self.assertEqual(self.f.a.__name__, 'a')
 80        self.assertEqual(self.fi.a.__name__, 'a')
 81        self.cannot_set_attr(self.f.a, "__name__", 'a', AttributeError)
 82        self.cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError)
 83
 84    def test_func_code(self):
 85        num_one, num_two = 7, 8
 86        def a(): pass
 87        def b(): return 12
 88        def c(): return num_one
 89        def d(): return num_two
 90        def e(): return num_one, num_two
 91        for func in [a, b, c, d, e]:
 92            self.assertEqual(type(func.func_code), types.CodeType)
 93        self.assertEqual(c(), 7)
 94        self.assertEqual(d(), 8)
 95        d.func_code = c.func_code
 96        self.assertEqual(c.func_code, d.func_code)
 97        self.assertEqual(c(), 7)
 98        # self.assertEqual(d(), 7)
 99        try: b.func_code = c.func_code
100        except ValueError: pass
101        else: self.fail(
102            "func_code with different numbers of free vars should not be "
103            "possible")
104        try: e.func_code = d.func_code
105        except ValueError: pass
106        else: self.fail(
107            "func_code with different numbers of free vars should not be "
108            "possible")
109
110    def test_blank_func_defaults(self):
111        self.assertEqual(self.b.func_defaults, None)
112        del self.b.func_defaults
113        self.assertEqual(self.b.func_defaults, None)
114
115    def test_func_default_args(self):
116        def first_func(a, b):
117            return a+b
118        def second_func(a=1, b=2):
119            return a+b
120        self.assertEqual(first_func.func_defaults, None)
121        self.assertEqual(second_func.func_defaults, (1, 2))
122        first_func.func_defaults = (1, 2)
123        self.assertEqual(first_func.func_defaults, (1, 2))
124        self.assertEqual(first_func(), 3)
125        self.assertEqual(first_func(3), 5)
126        self.assertEqual(first_func(3, 5), 8)
127        del second_func.func_defaults
128        self.assertEqual(second_func.func_defaults, None)
129        try: second_func()
130        except TypeError: pass
131        else: self.fail(
132            "func_defaults does not update; deleting it does not remove "
133            "requirement")
134
135class ImplicitReferencesTest(FuncAttrsTest):
136    def test_im_class(self):
137        self.assertEqual(self.f.a.im_class, self.f)
138        self.assertEqual(self.fi.a.im_class, self.f)
139        self.cannot_set_attr(self.f.a, "im_class", self.f, TypeError)
140        self.cannot_set_attr(self.fi.a, "im_class", self.f, TypeError)
141
142    def test_im_func(self):
143        self.f.b = self.b
144        self.assertEqual(self.f.b.im_func, self.b)
145        self.assertEqual(self.fi.b.im_func, self.b)
146        self.cannot_set_attr(self.f.b, "im_func", self.b, TypeError)
147        self.cannot_set_attr(self.fi.b, "im_func", self.b, TypeError)
148
149    def test_im_self(self):
150        self.assertEqual(self.f.a.im_self, None)
151        self.assertEqual(self.fi.a.im_self, self.fi)
152        self.cannot_set_attr(self.f.a, "im_self", None, TypeError)
153        self.cannot_set_attr(self.fi.a, "im_self", self.fi, TypeError)
154
155    def test_im_func_non_method(self):
156        # Behavior should be the same when a method is added via an attr
157        # assignment
158        self.f.id = types.MethodType(id, None, self.f)
159        self.assertEqual(self.fi.id(), id(self.fi))
160        self.assertNotEqual(self.fi.id(), id(self.f))
161        # Test usage
162        try: self.f.id.unknown_attr
163        except AttributeError: pass
164        else: self.fail("using unknown attributes should raise AttributeError")
165        # Test assignment and deletion
166        self.cannot_set_attr(self.f.id, 'unknown_attr', 2, AttributeError)
167        self.cannot_set_attr(self.fi.id, 'unknown_attr', 2, AttributeError)
168
169    def test_implicit_method_properties(self):
170        self.f.a.im_func.known_attr = 7
171        self.assertEqual(self.f.a.known_attr, 7)
172        self.assertEqual(self.fi.a.known_attr, 7)
173
174class ArbitraryFunctionAttrTest(FuncAttrsTest):
175    def test_set_attr(self):
176        self.b.known_attr = 7
177        self.assertEqual(self.b.known_attr, 7)
178        for func in [self.f.a, self.fi.a]:
179            try: func.known_attr = 7
180            except AttributeError: pass
181            else: self.fail("setting attributes on methods should raise error")
182
183    def test_delete_unknown_attr(self):
184        try: del self.b.unknown_attr
185        except AttributeError: pass
186        else: self.fail("deleting unknown attribute should raise TypeError")
187
188    def test_setting_attrs_duplicates(self):
189        try: self.f.a.klass = self.f
190        except AttributeError: pass
191        else: self.fail("setting arbitrary attribute in unbound function "
192                        " should raise AttributeError")
193        self.f.a.im_func.klass = self.f
194        for method in [self.f.a, self.fi.a, self.fi.a.im_func]:
195            self.assertEqual(method.klass, self.f)
196
197    def test_unset_attr(self):
198        for func in [self.b, self.f.a, self.fi.a]:
199            try:  func.non_existent_attr
200            except AttributeError: pass
201            else: self.fail("using unknown attributes should raise "
202                            "AttributeError")
203
204class FunctionDictsTest(FuncAttrsTest):
205    def test_setting_dict_to_invalid(self):
206        self.cannot_set_attr(self.b, '__dict__', None, TypeError)
207        self.cannot_set_attr(self.b, 'func_dict', None, TypeError)
208        from UserDict import UserDict
209        d = UserDict({'known_attr': 7})
210        self.cannot_set_attr(self.f.a.im_func, '__dict__', d, TypeError)
211        self.cannot_set_attr(self.fi.a.im_func, '__dict__', d, TypeError)
212
213    def test_setting_dict_to_valid(self):
214        d = {'known_attr': 7}
215        self.b.__dict__ = d
216        # Setting dict is only possible on the underlying function objects
217        self.f.a.im_func.__dict__ = d
218        # Test assignment
219        self.assertEqual(d, self.b.__dict__)
220        self.assertEqual(d, self.b.func_dict)
221        # ... and on all the different ways of referencing the method's func
222        self.assertEqual(d, self.f.a.im_func.__dict__)
223        self.assertEqual(d, self.f.a.__dict__)
224        self.assertEqual(d, self.fi.a.im_func.__dict__)
225        self.assertEqual(d, self.fi.a.__dict__)
226        # Test value
227        self.assertEqual(self.b.known_attr, 7)
228        self.assertEqual(self.b.__dict__['known_attr'], 7)
229        self.assertEqual(self.b.func_dict['known_attr'], 7)
230        # ... and again, on all the different method's names
231        self.assertEqual(self.f.a.im_func.known_attr, 7)
232        self.assertEqual(self.f.a.known_attr, 7)
233        self.assertEqual(self.fi.a.im_func.known_attr, 7)
234        self.assertEqual(self.fi.a.known_attr, 7)
235
236    def test_delete_func_dict(self):
237        try: del self.b.__dict__
238        except TypeError: pass
239        else: self.fail("deleting function dictionary should raise TypeError")
240        try: del self.b.func_dict
241        except TypeError: pass
242        else: self.fail("deleting function dictionary should raise TypeError")
243
244    def test_unassigned_dict(self):
245        self.assertEqual(self.b.__dict__, {})
246
247    def test_func_as_dict_key(self):
248        value = "Some string"
249        d = {}
250        d[self.b] = value
251        self.assertEqual(d[self.b], value)
252
253class FunctionDocstringTest(FuncAttrsTest):
254    def test_set_docstring_attr(self):
255        self.assertEqual(self.b.__doc__, None)
256        self.assertEqual(self.b.func_doc, None)
257        docstr = "A test method that does nothing"
258        self.b.__doc__ = self.f.a.im_func.__doc__ = docstr
259        self.assertEqual(self.b.__doc__, docstr)
260        self.assertEqual(self.b.func_doc, docstr)
261        self.assertEqual(self.f.a.__doc__, docstr)
262        self.assertEqual(self.fi.a.__doc__, docstr)
263        self.cannot_set_attr(self.f.a, "__doc__", docstr, AttributeError)
264        self.cannot_set_attr(self.fi.a, "__doc__", docstr, AttributeError)
265
266    def test_delete_docstring(self):
267        self.b.__doc__ = "The docstring"
268        del self.b.__doc__
269        self.assertEqual(self.b.__doc__, None)
270        self.assertEqual(self.b.func_doc, None)
271        self.b.func_doc = "The docstring"
272        del self.b.func_doc
273        self.assertEqual(self.b.__doc__, None)
274        self.assertEqual(self.b.func_doc, None)
275
276def test_main():
277    test_support.run_unittest(FunctionPropertiesTest, ImplicitReferencesTest,
278                              ArbitraryFunctionAttrTest, FunctionDictsTest,
279                              FunctionDocstringTest)
280
281if __name__ == "__main__":
282    test_main()