Skip to content

Commit 05c0bc3

Browse files
author
hartsantler
committed
made __getattr__ correct, it first checks if instance has the attribute before calling the user defined __getattr__
1 parent f263361 commit 05c0bc3

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

pythonscript/python_to_pythonjs.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def getvalue(self):
5656

5757
MINI_STDLIB = {
5858
'time': {
59-
'time': 'function time() { return new Date().getTime(); }'
59+
'time': 'function time() { return new Date().getTime() / 1000.0; }'
6060
},
6161
'random': {
6262
'random': 'var random = Math.random'
@@ -102,6 +102,25 @@ def visit_ImportFrom(self, node):
102102
def visit_Yield(self, node):
103103
return 'yield %s' % self.visit(node.value)
104104

105+
def _gen_getattr_helper(self, class_name, func_name):
106+
'''
107+
This helper is used to emulate how Python works, __getattr__ is only supposed
108+
to be called when the attribute is not found on the instance.
109+
'''
110+
a = [
111+
'def __%s____getattr_helper(args, kwargs):' %class_name,
112+
' var(signature, arguments)',
113+
' signature = JSObject(kwargs=JSObject(), args=JSArray("self", "name"))',
114+
' arguments = get_arguments(signature, args, kwargs)',
115+
''' JS("var self = arguments['self']")''',
116+
''' JS("var name = arguments['name']")''',
117+
' if name in get_attribute(self, "__dict__"):',
118+
' return get_attribute(getattr, "__call__")( JSArray(self,name), JSObject() )',
119+
' else:',
120+
' return %s( [self, name] )' %func_name
121+
]
122+
return '\n'.join(a)
123+
105124
def visit_ClassDef(self, node):
106125
name = node.name
107126
self._classes[ name ] = list() ## method names
@@ -119,6 +138,10 @@ def visit_ClassDef(self, node):
119138
item.name = '__%s_%s' % (name, item_name)
120139
self.visit(item) # this will output the code for the function
121140
writer.write('__%s_attrs.%s = %s' % (name, item_name, item.name))
141+
142+
if item_name == '__getattr__':
143+
writer.write( self._gen_getattr_helper(name, item.name) )
144+
122145
elif isinstance(item, Assign):
123146
item_name = item.targets[0].id
124147
item.targets[0].id = '__%s_%s' % (name.id, item_name)
@@ -222,7 +245,7 @@ def visit_Attribute(self, node):
222245
if name in self._instances: ## support '.' operator overloading
223246
klass = self._instances[ name ]
224247
if '__getattr__' in self._classes[ klass ]:
225-
return '__%s___getattr__( [%s, "%s"] )' % (klass, name, node.attr)
248+
return '__%s____getattr_helper( [%s, "%s"] )' % (klass, name, node.attr)
226249
else:
227250
return 'get_attribute(%s, "%s")' % (name, node.attr)
228251
else:
@@ -422,6 +445,7 @@ def visit_While(self, node):
422445
writer.pull()
423446

424447

448+
425449
def main(script):
426450
input = parse(script)
427451
PythonToPythonJS().visit(input)

0 commit comments

Comments
 (0)