Skip to content

Commit a74eee3

Browse files
committed
Implement getattr(), hasattr() and setattr() builtins
1 parent 96bfd77 commit a74eee3

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

builtin/builtin.go

+64-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ func init() {
3131
// py.NewMethod("eval", builtin_eval, 0, eval_doc),
3232
// py.NewMethod("exec", builtin_exec, 0, exec_doc),
3333
// py.NewMethod("format", builtin_format, 0, format_doc),
34-
// py.NewMethod("getattr", builtin_getattr, 0, getattr_doc),
34+
py.NewMethod("getattr", builtin_getattr, 0, getattr_doc),
3535
// py.NewMethod("globals", builtin_globals, py.METH_NOARGS, globals_doc),
36-
// py.NewMethod("hasattr", builtin_hasattr, 0, hasattr_doc),
36+
py.NewMethod("hasattr", builtin_hasattr, 0, hasattr_doc),
3737
// py.NewMethod("hash", builtin_hash, 0, hash_doc),
3838
// py.NewMethod("hex", builtin_hex, 0, hex_doc),
3939
// py.NewMethod("id", builtin_id, 0, id_doc),
@@ -52,7 +52,7 @@ func init() {
5252
py.NewMethod("print", builtin_print, 0, print_doc),
5353
// py.NewMethod("repr", builtin_repr, 0, repr_doc),
5454
py.NewMethod("round", builtin_round, 0, round_doc),
55-
// py.NewMethod("setattr", builtin_setattr, 0, setattr_doc),
55+
py.NewMethod("setattr", builtin_setattr, 0, setattr_doc),
5656
// py.NewMethod("sorted", builtin_sorted, 0, sorted_doc),
5757
// py.NewMethod("sum", builtin_sum, 0, sum_doc),
5858
// py.NewMethod("vars", builtin_vars, 0, vars_doc),
@@ -383,3 +383,64 @@ func builtin_ord(self, obj py.Object) py.Object {
383383

384384
panic(py.ExceptionNewf(py.TypeError, "ord() expected a character, but string of length %zd found", size))
385385
}
386+
387+
const getattr_doc = `getattr(object, name[, default]) -> value
388+
389+
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
390+
When a default argument is given, it is returned when the attribute doesn't
391+
exist; without it, an exception is raised in that case.`
392+
393+
func builtin_getattr(self py.Object, args py.Tuple) py.Object {
394+
var v, result, dflt py.Object
395+
var name py.Object
396+
397+
py.UnpackTuple(args, nil, "getattr", 2, 3, &v, &name, &dflt)
398+
399+
nameStr, ok := name.(py.String)
400+
if !ok {
401+
panic(py.ExceptionNewf(py.TypeError, "getattr(): attribute name must be string"))
402+
}
403+
404+
result, err := py.GetAttrErr(v, string(nameStr))
405+
if err != nil {
406+
if dflt == nil {
407+
panic(err)
408+
}
409+
result = dflt
410+
}
411+
return result
412+
}
413+
414+
const hasattr_doc = `hasattr(object, name) -> bool
415+
416+
Return whether the object has an attribute with the given name.
417+
(This is done by calling getattr(object, name) and catching AttributeError.)`
418+
419+
func builtin_hasattr(self py.Object, args py.Tuple) py.Object {
420+
var v py.Object
421+
var name py.Object
422+
py.UnpackTuple(args, nil, "hasattr", 2, 2, &v, &name)
423+
424+
nameStr, ok := name.(py.String)
425+
if !ok {
426+
panic(py.ExceptionNewf(py.TypeError, "hasattr(): attribute name must be string"))
427+
}
428+
429+
_, err := py.GetAttrErr(v, string(nameStr))
430+
return py.NewBool(err == nil)
431+
}
432+
433+
const setattr_doc = `setattr(object, name, value)
434+
435+
Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
436+
"x.y = v".`
437+
438+
func builtin_setattr(self py.Object, args py.Tuple) py.Object {
439+
var v py.Object
440+
var name py.Object
441+
var value py.Object
442+
443+
py.UnpackTuple(args, nil, "setattr", 3, 3, &v, &name, &value)
444+
445+
return py.SetAttr(v, name, value)
446+
}

py/internal.go

+2
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ func SetItem(self Object, key Object, value Object) Object {
124124
}
125125

126126
// GetAttrErr - returns the result or an err to be raised if not found
127+
//
128+
// Only AttributeErrors will be returned in err, everything else will be raised
127129
func GetAttrErr(self Object, key string) (res Object, err error) {
128130
defer func() {
129131
if r := recover(); r != nil {

0 commit comments

Comments
 (0)