Skip to content

Commit 74c91ed

Browse files
committed
py: implement builtin vars
1 parent e20a7a4 commit 74c91ed

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

py/method.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const (
8484
InternalMethodImport
8585
InternalMethodEval
8686
InternalMethodExec
87+
InternalMethodVars
8788
)
8889

8990
var MethodType = NewType("method", "method object")

stdlib/builtin/builtin.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func init() {
6363
py.MustNewMethod("setattr", builtin_setattr, 0, setattr_doc),
6464
py.MustNewMethod("sorted", builtin_sorted, 0, sorted_doc),
6565
py.MustNewMethod("sum", builtin_sum, 0, sum_doc),
66-
// py.MustNewMethod("vars", builtin_vars, 0, vars_doc),
66+
py.MustNewMethod("vars", py.InternalMethodVars, 0, vars_doc),
6767
}
6868
globals := py.StringDict{
6969
"None": py.None,
@@ -1189,6 +1189,11 @@ const globals_doc = `globals() -> dictionary
11891189
11901190
Return the dictionary containing the current scope's global variables.`
11911191

1192+
const vars_doc = `vars([object]) -> dictionary
1193+
1194+
Without an argument, equivalent to locals().
1195+
With an argument, equivalent to object.__dict__.`
1196+
11921197
const sum_doc = `sum($module, iterable, start=0, /)
11931198
--
11941199
Return the sum of a \'start\' value (default: 0) plus an iterable of numbers

stdlib/builtin/tests/builtin.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,39 @@ def fn(x):
107107
assert locals()["x"] == 1
108108
fn(1)
109109

110+
doc="vars"
111+
def fn(x):
112+
assert vars()["x"] == 1
113+
fn(1)
114+
115+
# Test vars() with an object that has __dict__ (function objects have __dict__)
116+
def test_func():
117+
pass
118+
119+
assert vars(test_func) == test_func.__dict__
120+
assert isinstance(vars(test_func), dict)
121+
122+
ok = False
123+
try:
124+
vars(test_func, test_func)
125+
except TypeError:
126+
ok = True
127+
assert ok, "TypeError not raised for too many arguments"
128+
129+
ok = False
130+
try:
131+
vars(x=1)
132+
except TypeError:
133+
ok = True
134+
assert ok, "TypeError not raised for keyword arguments"
135+
136+
ok = False
137+
try:
138+
vars(test_func, y=1)
139+
except TypeError:
140+
ok = True
141+
assert ok, "TypeError not raised for keyword arguments with object"
142+
110143
def func(p):
111144
return p[1]
112145

vm/eval.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,23 @@ func callInternal(fn py.Object, args py.Tuple, kwargs py.StringDict, f *py.Frame
15991599
case py.InternalMethodExec:
16001600
f.FastToLocals()
16011601
return builtinExec(f.Context, args, kwargs, f.Locals, f.Globals, f.Builtins)
1602+
case py.InternalMethodVars:
1603+
if len(kwargs) > 0 {
1604+
return nil, py.ExceptionNewf(py.TypeError, "vars() takes no keyword arguments")
1605+
}
1606+
switch len(args) {
1607+
case 0:
1608+
f.FastToLocals()
1609+
return f.Locals, nil
1610+
case 1:
1611+
attr, err := py.GetAttrString(args[0], "__dict__")
1612+
if err != nil {
1613+
return nil, err
1614+
}
1615+
return attr, nil
1616+
default:
1617+
return nil, py.ExceptionNewf(py.TypeError, "vars() takes at most 1 argument (%d given)", len(args))
1618+
}
16021619
default:
16031620
return nil, py.ExceptionNewf(py.SystemError, "Internal method %v not found", x)
16041621
}

0 commit comments

Comments
 (0)