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