Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 1 | import unittest |
| 2 | from test import test_support |
| 3 | import sys, new |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 4 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 5 | class NewTest(unittest.TestCase): |
| 6 | def test_spam(self): |
| 7 | class Eggs: |
| 8 | def get_yolks(self): |
| 9 | return self.yolks |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 10 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 11 | m = new.module('Spam') |
| 12 | m.Eggs = Eggs |
| 13 | sys.modules['Spam'] = m |
| 14 | import Spam |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 15 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 16 | def get_more_yolks(self): |
| 17 | return self.yolks + 3 |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 18 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 19 | # new.classobj() |
| 20 | C = new.classobj('Spam', (Spam.Eggs,), {'get_more_yolks': get_more_yolks}) |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 21 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 22 | def break_yolks(self): |
| 23 | self.yolks = self.yolks - 2 |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 24 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 25 | # new.instancemethod() |
| 26 | c = C() |
| 27 | c.yolks = 3 |
| 28 | im = new.instancemethod(break_yolks, c, C) |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 29 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 30 | self.assertEqual(c.get_yolks(), 3, |
| 31 | 'Broken call of hand-crafted class instance') |
| 32 | self.assertEqual(c.get_more_yolks(), 6, |
| 33 | 'Broken call of hand-crafted class instance') |
Michael W. Hudson | e2749cb | 2005-03-30 16:32:10 +0000 | [diff] [blame] | 34 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 35 | im() |
| 36 | self.assertEqual(c.get_yolks(), 1, |
| 37 | 'Broken call of hand-crafted instance method') |
| 38 | self.assertEqual(c.get_more_yolks(), 4, |
| 39 | 'Broken call of hand-crafted instance method') |
Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 40 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 41 | im = new.instancemethod(break_yolks, c) |
| 42 | im() |
| 43 | self.assertEqual(c.get_yolks(), -1) |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 44 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 45 | # Verify that dangerous instance method creation is forbidden |
| 46 | self.assertRaises(TypeError, new.instancemethod, break_yolks, None) |
Barry Warsaw | 924e5d5 | 1996-12-10 16:28:53 +0000 | [diff] [blame] | 47 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 48 | # Verify that instancemethod() doesn't allow keyword args |
| 49 | self.assertRaises(TypeError, new.instancemethod, break_yolks, c, kw=1) |
Jeremy Hylton | df3f793 | 2002-07-11 18:30:27 +0000 | [diff] [blame] | 50 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 51 | def test_scope(self): |
| 52 | # It's unclear what the semantics should be for a code object compiled |
| 53 | # at module scope, but bound and run in a function. In CPython, `c' is |
| 54 | # global (by accident?) while in Jython, `c' is local. The intent of |
| 55 | # the test clearly is to make `c' global, so let's be explicit about it. |
| 56 | codestr = ''' |
| 57 | global c |
| 58 | a = 1 |
| 59 | b = 2 |
| 60 | c = a + b |
| 61 | ''' |
Jeremy Hylton | df3f793 | 2002-07-11 18:30:27 +0000 | [diff] [blame] | 62 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 63 | codestr = "\n".join(l.strip() for l in codestr.splitlines()) |
Tim Peters | bf9ac4b | 2004-08-13 03:57:22 +0000 | [diff] [blame] | 64 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 65 | ccode = compile(codestr, '<string>', 'exec') |
| 66 | # Jython doesn't have a __builtins__, so use a portable alternative |
| 67 | import __builtin__ |
| 68 | g = {'c': 0, '__builtins__': __builtin__} |
Tim Peters | bf9ac4b | 2004-08-13 03:57:22 +0000 | [diff] [blame] | 69 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 70 | # this test could be more robust |
| 71 | func = new.function(ccode, g) |
| 72 | func() |
| 73 | self.assertEqual(g['c'], 3, 'Could not create a proper function object') |
Tim Peters | bf9ac4b | 2004-08-13 03:57:22 +0000 | [diff] [blame] | 74 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 75 | def test_function(self): |
| 76 | # test the various extended flavors of function.new |
| 77 | def f(x): |
| 78 | def g(y): |
| 79 | return x + y |
| 80 | return g |
| 81 | g = f(4) |
Neal Norwitz | 221085d | 2007-02-25 20:55:47 +0000 | [diff] [blame] | 82 | new.function(f.__code__, {}, "blah") |
| 83 | g2 = new.function(g.__code__, {}, "blah", (2,), g.__closure__) |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 84 | self.assertEqual(g2(), 6) |
Neal Norwitz | 221085d | 2007-02-25 20:55:47 +0000 | [diff] [blame] | 85 | g3 = new.function(g.__code__, {}, "blah", None, g.__closure__) |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 86 | self.assertEqual(g3(5), 9) |
| 87 | def test_closure(func, closure, exc): |
Neal Norwitz | 221085d | 2007-02-25 20:55:47 +0000 | [diff] [blame] | 88 | self.assertRaises(exc, new.function, func.__code__, {}, "", None, closure) |
Tim Peters | bf9ac4b | 2004-08-13 03:57:22 +0000 | [diff] [blame] | 89 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 90 | test_closure(g, None, TypeError) # invalid closure |
| 91 | test_closure(g, (1,), TypeError) # non-cell in closure |
| 92 | test_closure(g, (1, 1), ValueError) # closure is wrong size |
Neal Norwitz | 221085d | 2007-02-25 20:55:47 +0000 | [diff] [blame] | 93 | test_closure(f, g.__closure__, ValueError) # no closure needed |
Michael W. Hudson | 6093462 | 2004-08-12 17:56:29 +0000 | [diff] [blame] | 94 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 95 | # Note: Jython will never have new.code() |
| 96 | if hasattr(new, 'code'): |
| 97 | def test_code(self): |
| 98 | # bogus test of new.code() |
| 99 | def f(a): pass |
Tim Peters | bf9ac4b | 2004-08-13 03:57:22 +0000 | [diff] [blame] | 100 | |
Neal Norwitz | 221085d | 2007-02-25 20:55:47 +0000 | [diff] [blame] | 101 | c = f.__code__ |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 102 | argcount = c.co_argcount |
| 103 | kwonlyargcount = c.co_kwonlyargcount |
| 104 | nlocals = c.co_nlocals |
| 105 | stacksize = c.co_stacksize |
| 106 | flags = c.co_flags |
| 107 | codestring = c.co_code |
| 108 | constants = c.co_consts |
| 109 | names = c.co_names |
| 110 | varnames = c.co_varnames |
| 111 | filename = c.co_filename |
| 112 | name = c.co_name |
| 113 | firstlineno = c.co_firstlineno |
| 114 | lnotab = c.co_lnotab |
| 115 | freevars = c.co_freevars |
| 116 | cellvars = c.co_cellvars |
Michael W. Hudson | 6093462 | 2004-08-12 17:56:29 +0000 | [diff] [blame] | 117 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 118 | d = new.code(argcount, kwonlyargcount, nlocals, stacksize, flags, |
| 119 | codestring, constants, names, varnames, filename, |
| 120 | name, firstlineno, lnotab, freevars, cellvars) |
Michael W. Hudson | 6093462 | 2004-08-12 17:56:29 +0000 | [diff] [blame] | 121 | |
Thomas Wouters | b213704 | 2007-02-01 18:02:27 +0000 | [diff] [blame] | 122 | # test backwards-compatibility version with no freevars or cellvars |
| 123 | d = new.code(argcount, kwonlyargcount, nlocals, stacksize, |
| 124 | flags, codestring, constants, names, varnames, |
| 125 | filename, name, firstlineno, lnotab) |
| 126 | |
| 127 | # negative co_argcount used to trigger a SystemError |
| 128 | self.assertRaises(ValueError, new.code, |
| 129 | -argcount, kwonlyargcount, nlocals, stacksize, flags, |
| 130 | codestring, constants, names, varnames, filename, name, |
| 131 | firstlineno, lnotab) |
| 132 | |
| 133 | # negative co_nlocals used to trigger a SystemError |
| 134 | self.assertRaises(ValueError, new.code, |
| 135 | argcount, kwonlyargcount, -nlocals, stacksize, flags, |
| 136 | codestring, constants, names, varnames, filename, name, |
| 137 | firstlineno, lnotab) |
| 138 | |
| 139 | # non-string co_name used to trigger a Py_FatalError |
| 140 | self.assertRaises(TypeError, new.code, |
| 141 | argcount, kwonlyargcount, nlocals, stacksize, flags, |
| 142 | codestring, constants, (5,), varnames, filename, name, |
| 143 | firstlineno, lnotab) |
| 144 | |
| 145 | # new.code used to be a way to mutate a tuple... |
| 146 | class S(str): |
| 147 | pass |
| 148 | t = (S("ab"),) |
| 149 | d = new.code(argcount, kwonlyargcount, nlocals, stacksize, |
| 150 | flags, codestring, constants, t, varnames, |
| 151 | filename, name, firstlineno, lnotab) |
| 152 | self.assert_(type(t[0]) is S, "eek, tuple changed under us!") |
| 153 | |
| 154 | def test_main(): |
| 155 | test_support.run_unittest(NewTest) |
| 156 | |
| 157 | if __name__ == "__main__": |
| 158 | test_main() |