Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 252b104

Browse filesBrowse files
committed
bam
1 parent 7678099 commit 252b104
Copy full SHA for 252b104

File tree

Expand file treeCollapse file tree

2 files changed

+195
-0
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+195
-0
lines changed
Open diff view settings
Collapse file

‎Python3-porting.txt‎

Copy file name to clipboardExpand all lines: Python3-porting.txt
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
See cgi-bin/p4_encoder.py for some proposed changes
2+
3+
14
Notes from Peter Wentworth about porting to Python 3
25
'''
36
Hi Philip - a bug in the code I sent you [NB, see: python3_viz.zip]! I
Collapse file

‎cgi-bin/p4_encoder.py‎

Copy file name to clipboard
+192Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#!/usr/bin/python3 -u
2+
3+
# Python 3 version of encoder by David Pritchard, built upon work by Peter Wentworth
4+
# (diff with pg_encoder.py, which is for Python 2)
5+
6+
7+
# given an arbitrary piece of Python data, encode it in such a manner
8+
# that it can be later encoded into JSON.
9+
# http://json.org/
10+
#
11+
# Format:
12+
# * None, int, float, str, bool - unchanged (long is removed in Python 3)
13+
# (json.dumps encodes these fine verbatim)
14+
# * list - ['LIST', unique_id, elt1, elt2, elt3, ..., eltN]
15+
# * tuple - ['TUPLE', unique_id, elt1, elt2, elt3, ..., eltN]
16+
# * set - ['SET', unique_id, elt1, elt2, elt3, ..., eltN]
17+
# * dict - ['DICT', unique_id, [key1, value1], [key2, value2], ..., [keyN, valueN]]
18+
# * instance - ['INSTANCE', class name, unique_id, [attr1, value1], [attr2, value2], ..., [attrN, valueN]]
19+
# * class - ['CLASS', class name, unique_id, [list of superclass names], [attr1, value1], [attr2, value2], ..., [attrN, valueN]]
20+
# * circular reference - ['CIRCULAR_REF', unique_id]
21+
# * other - [<type name>, unique_id, string representation of object]
22+
#
23+
#
24+
# the unique_id is derived from id(), which allows us to explicitly
25+
# capture aliasing of compound values
26+
27+
# Key: real ID from id()
28+
# Value: a small integer for greater readability, set by cur_small_id
29+
real_to_small_IDs = {}
30+
cur_small_id = 1
31+
32+
import re, types
33+
#typeRE = re.compile("<type '(.*)'>") # not used in Python 3
34+
classRE = re.compile("<class '(.*)'>")
35+
functionRE = re.compile("<function (\w*) (.*)>") # new case for Python 3
36+
37+
# When we find a <class x> and x is in this list, don't confuse the beginner by listing the inner details
38+
native_types = ['int', 'float', 'str', 'tuple', 'list', 'set', 'dict', 'bool', 'NoneType', 'bytes', 'type', 'object']
39+
40+
def encode(dat, ignore_id=False):
41+
42+
def append_attributes(ret, new_compound_obj_ids, dict):
43+
""" Put attributes onto ret. """
44+
# traverse the __dict__ to grab attributes
45+
# (filter out useless-seeming ones):
46+
47+
user_attrs = sorted([e for e in dict.keys()
48+
if e not in {'__doc__', '__module__', '__return__', '__locals__',
49+
'__weakref__', '__dict__'}
50+
])
51+
for attr in user_attrs:
52+
foo = [encode_helper(attr, new_compound_obj_ids),
53+
encode_helper(dict[attr], new_compound_obj_ids)]
54+
ret.append(foo)
55+
56+
def encode_helper(dat, compound_obj_ids):
57+
# primitive type
58+
if dat is None or type(dat) in (int, float, str, bool):
59+
return dat
60+
# compound type
61+
else:
62+
my_id = id(dat)
63+
64+
global cur_small_id
65+
if my_id not in real_to_small_IDs:
66+
if ignore_id:
67+
real_to_small_IDs[my_id] = 99999
68+
else:
69+
real_to_small_IDs[my_id] = cur_small_id
70+
cur_small_id += 1
71+
72+
if my_id in compound_obj_ids:
73+
return ['CIRCULAR_REF', real_to_small_IDs[my_id]]
74+
75+
new_compound_obj_ids = compound_obj_ids.union([my_id])
76+
77+
typ = type(dat)
78+
obj_as_string = object.__repr__(dat)
79+
80+
my_small_id = real_to_small_IDs[my_id]
81+
82+
if typ == list:
83+
ret = ['LIST', my_small_id]
84+
for e in dat: ret.append(encode_helper(e, new_compound_obj_ids))
85+
elif typ == tuple:
86+
ret = ['TUPLE', my_small_id]
87+
for e in dat: ret.append(encode_helper(e, new_compound_obj_ids))
88+
elif typ == set:
89+
ret = ['SET', my_small_id]
90+
for e in dat: ret.append(encode_helper(e, new_compound_obj_ids))
91+
elif typ == dict:
92+
ret = ['DICT', my_small_id]
93+
append_attributes(ret, new_compound_obj_ids, dat)
94+
95+
elif typ == type: # its a class. What a mess they made of it!
96+
superclass_names = [e.__name__ for e in dat.__bases__]
97+
ret = ['CLASS', dat.__name__, my_small_id, superclass_names]
98+
if dat.__name__ not in native_types:
99+
if hasattr(dat, '__dict__'):
100+
append_attributes(ret, new_compound_obj_ids, dat.__dict__)
101+
102+
elif repr(typ)[:6] == "<class" and obj_as_string.find('object') >= 0: # is it an instance?
103+
ret = ['INSTANCE', dat.__class__.__name__, my_small_id]
104+
if hasattr(dat, '__dict__'):
105+
append_attributes(ret, new_compound_obj_ids, dat.__dict__)
106+
107+
else:
108+
typeStr = repr(typ)
109+
m = classRE.match(typeStr)
110+
assert m, typ
111+
ret = [m.group(1), my_small_id , obj_as_string]
112+
113+
return ret
114+
115+
return encode_helper(dat, set())
116+
117+
118+
if __name__ == '__main__':
119+
120+
def test(actual, expected=0):
121+
""" Compare the actual to the expected value, and print a suitable message. """
122+
import sys
123+
linenum = sys._getframe(1).f_lineno # get the caller's line number.
124+
if (expected == actual):
125+
msg = "Test on line %s passed." % (linenum)
126+
else:
127+
msg = "Test on line %s failed. Expected '%s', but got '%s'." % (linenum, expected, actual)
128+
print(msg)
129+
130+
class P():
131+
p_attr1 = 123
132+
def p_method(self, x):
133+
return 2*x
134+
135+
class Q(P):
136+
pass
137+
138+
p1 = P()
139+
q1 = Q()
140+
141+
addr = 1
142+
143+
test(encode("hello"),"hello")
144+
test(encode(123),123)
145+
test(encode(123.45),123.45)
146+
test(encode(132432134423143132432134423143),132432134423143132432134423143)
147+
test(encode(False),False)
148+
test(encode(None),None)
149+
150+
151+
test(encode((1,2)), ['TUPLE', addr, 1, 2])
152+
153+
addr += 1
154+
test(encode([1,2]), ['LIST', addr, 1, 2])
155+
156+
addr += 1
157+
test(encode({1:'mon'}), ['DICT', addr, [1, 'mon']])
158+
159+
addr += 1
160+
test(encode(test), ['function', addr, 'test'])
161+
162+
addr += 1
163+
test(encode(P), ['CLASS', 'P', addr, ['object'], ['p_attr1', 123], ['p_method', ['function', addr+1, 'p_method']]])
164+
165+
addr += 2
166+
test(encode(Q), ['CLASS', 'Q', addr, ['P']])
167+
168+
addr += 1
169+
test(encode(p1), ['INSTANCE', 'P', addr])
170+
171+
addr += 1
172+
test(encode(q1), ['INSTANCE', 'Q', addr])
173+
174+
addr += 1
175+
test(encode(min), ['builtin_function_or_method', addr, '<built-in function min>'] )
176+
177+
addr += 1
178+
test(encode(range(1,3)), ['range', addr, 'range(1, 3)'])
179+
180+
addr += 1
181+
test(encode({1,2}), ['SET', addr, 1, 2])
182+
183+
addr += 1
184+
p = [1,2,3]
185+
p.append(p) # make a circular reference
186+
187+
test(encode(p), ['LIST', addr, 1, 2, 3, ['CIRCULAR_REF', addr]])
188+
189+
# Need some new tests for z = type(123)
190+
191+
192+
print(encode({"stdout": "", "func_name": "<module>", "globals": {"sum": 0, "friends": ["LIST", 1, "Joe", "Bill"], "length": 3, "f": "Joe"}, "stack_locals": [], "line": 7, "event": "step_line"}))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.