Skip to content

Commit d059504

Browse files
committed
vm: implement IMPORT_NAME, IMPORT_FROM, IMPORT_STAR; py: factor Attribute code
* Re-arrange and factor Attribute handling * Fix bug in import from curent directory * Implement IMPORT_*
1 parent a20d443 commit d059504

File tree

10 files changed

+147
-37
lines changed

10 files changed

+147
-37
lines changed

builtin/builtin.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,7 @@ func builtin_getattr(self py.Object, args py.Tuple) py.Object {
411411

412412
py.UnpackTuple(args, nil, "getattr", 2, 3, &v, &name, &dflt)
413413

414-
nameStr, ok := name.(py.String)
415-
if !ok {
416-
panic(py.ExceptionNewf(py.TypeError, "getattr(): attribute name must be string"))
417-
}
418-
419-
result, err := py.GetAttrErr(v, string(nameStr))
414+
result, err := py.GetAttrErr(v, name)
420415
if err != nil {
421416
if dflt == nil {
422417
panic(err)
@@ -435,13 +430,7 @@ func builtin_hasattr(self py.Object, args py.Tuple) py.Object {
435430
var v py.Object
436431
var name py.Object
437432
py.UnpackTuple(args, nil, "hasattr", 2, 2, &v, &name)
438-
439-
nameStr, ok := name.(py.String)
440-
if !ok {
441-
panic(py.ExceptionNewf(py.TypeError, "hasattr(): attribute name must be string"))
442-
}
443-
444-
_, err := py.GetAttrErr(v, string(nameStr))
433+
_, err := py.GetAttrErr(v, name)
445434
return py.NewBool(err == nil)
446435
}
447436

py/import.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
var (
1414
// This will become sys.path one day ;-)
15-
modulePath = []string{"", "/usr/lib/python3.3", "/usr/local/lib/python3.3/dist-packages", "/usr/lib/python3/dist-packages"}
15+
modulePath = []string{"", "/usr/lib/python3.4", "/usr/local/lib/python3.4/dist-packages", "/usr/lib/python3/dist-packages"}
1616
)
1717

1818
// The workings of __import__
@@ -93,7 +93,7 @@ func ImportModuleLevelObject(name string, globals, locals StringDict, fromlist T
9393
if !ok {
9494
panic(ExceptionNewf(SystemError, "Couldn't find __file__ in globals"))
9595
}
96-
mpath = string(mpathObj.(String))
96+
mpath = path.Dir(string(mpathObj.(String)))
9797
}
9898
fullPath := path.Join(mpath, pathParts)
9999
// FIXME Read pyc/pyo too
@@ -277,7 +277,7 @@ func XImportModuleLevelObject(nameObj, given_globals, locals, given_fromlist Obj
277277
// NOTE: because of this, __initializing__ must be set *before*
278278
// stuffing the new module in sys.modules.
279279

280-
value, err = GetAttrErr(mod, "__initializing__")
280+
value, err = GetAttrStringErr(mod, "__initializing__")
281281
if err == nil {
282282
initializing = bool(MakeBool(value).(Bool))
283283
}

py/internal.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44

55
package py
66

7+
// AttributeName converts an Object to a string, raising a TypeError
8+
// if it wasn't a String
9+
func AttributeName(keyObj Object) string {
10+
if key, ok := keyObj.(String); ok {
11+
return string(key)
12+
}
13+
panic(ExceptionNewf(TypeError, "attribute name must be string, not '%s'", keyObj.Type().Name))
14+
}
15+
716
// Bool is called to implement truth value testing and the built-in
817
// operation bool(); should return False or True. When this method is
918
// not defined, __len__() is called, if it is defined, and the object
@@ -142,10 +151,10 @@ func DelItem(self Object, key Object) Object {
142151
panic(ExceptionNewf(TypeError, "'%s' object does not support item deletion", self.Type().Name))
143152
}
144153

145-
// GetAttrErr - returns the result or an err to be raised if not found
154+
// GetAttrStringErr - returns the result or an err to be raised if not found
146155
//
147156
// Only AttributeErrors will be returned in err, everything else will be raised
148-
func GetAttrErr(self Object, key string) (res Object, err error) {
157+
func GetAttrStringErr(self Object, key string) (res Object, err error) {
149158
defer func() {
150159
if r := recover(); r != nil {
151160
if IsException(AttributeError, r) {
@@ -201,9 +210,16 @@ func GetAttrErr(self Object, key string) (res Object, err error) {
201210
return
202211
}
203212

213+
// GetAttrErr - returns the result or an err to be raised if not found
214+
//
215+
// Only AttributeErrors will be returned in err, everything else will be raised
216+
func GetAttrErr(self Object, keyObj Object) (res Object, err error) {
217+
return GetAttrStringErr(self, AttributeName(keyObj))
218+
}
219+
204220
// GetAttrString gets the attribute, raising an error if not found
205221
func GetAttrString(self Object, key string) Object {
206-
res, err := GetAttrErr(self, key)
222+
res, err := GetAttrStringErr(self, key)
207223
if err != nil {
208224
panic(err)
209225
}
@@ -213,10 +229,7 @@ func GetAttrString(self Object, key string) Object {
213229
// GetAttr gets the attribute rasing an error if key isn't a string or
214230
// attribute not found
215231
func GetAttr(self Object, keyObj Object) Object {
216-
if key, ok := keyObj.(String); ok {
217-
return GetAttrString(self, string(key))
218-
}
219-
panic(ExceptionNewf(TypeError, "attribute name must be string, not '%s'", self.Type().Name))
232+
return GetAttrString(self, AttributeName(keyObj))
220233
}
221234

222235
// SetAttrString
@@ -255,10 +268,7 @@ func SetAttrString(self Object, key string, value Object) Object {
255268

256269
// SetAttr
257270
func SetAttr(self Object, keyObj Object, value Object) Object {
258-
if key, ok := keyObj.(String); ok {
259-
return GetAttrString(self, string(key))
260-
}
261-
panic(ExceptionNewf(TypeError, "attribute name must be string, not '%s'", self.Type().Name))
271+
return GetAttrString(self, AttributeName(keyObj))
262272
}
263273

264274
// DeleteAttrString
@@ -301,9 +311,5 @@ func DeleteAttrString(self Object, key string) {
301311

302312
// DeleteAttr
303313
func DeleteAttr(self Object, keyObj Object) {
304-
if key, ok := keyObj.(String); ok {
305-
DeleteAttrString(self, string(key))
306-
return
307-
}
308-
panic(ExceptionNewf(TypeError, "attribute name must be string, not '%s'", self.Type().Name))
314+
DeleteAttrString(self, AttributeName(keyObj))
309315
}

vm/eval.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ objects so they can be GCed
3535

3636
import (
3737
"runtime/debug"
38+
"strings"
3839

3940
"github.com/ncw/gpython/py"
4041
)
@@ -673,7 +674,22 @@ func do_YIELD_VALUE(vm *Vm, arg int32) {
673674
// names. This opcode implements from module import *.
674675
func do_IMPORT_STAR(vm *Vm, arg int32) {
675676
defer vm.CheckException()
676-
vm.NotImplemented("IMPORT_STAR", arg)
677+
from := vm.POP()
678+
module := from.(*py.Module)
679+
if all, ok := module.Globals["__all__"]; ok {
680+
py.Iterate(all, func(item py.Object) bool {
681+
name := py.AttributeName(item)
682+
vm.frame.Locals[name] = py.GetAttrString(module, name)
683+
return false
684+
})
685+
} else {
686+
for name, value := range module.Globals {
687+
if !strings.HasPrefix(name, "_") {
688+
vm.frame.Locals[name] = value
689+
}
690+
}
691+
}
692+
// FIXME implement STORE_FAST stuff
677693
}
678694

679695
// Removes one block from the block stack. Per frame, there is a stack
@@ -1010,7 +1026,7 @@ func do_IMPORT_FROM(vm *Vm, namei int32) {
10101026
defer vm.CheckException()
10111027
name := vm.frame.Code.Names[namei]
10121028
module := vm.TOP()
1013-
res, err := py.GetAttrErr(module, name)
1029+
res, err := py.GetAttrStringErr(module, name)
10141030
if err != nil {
10151031
// Catch AttributeError and rethrow as ImportError
10161032
if py.IsException(py.AttributeError, err) {

vm/tests/import_from.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env python3.4
2+
3+
# test IMPORT_FROM
4+
5+
from lib import libfn, libvar, libclass
6+
7+
assert libfn() == 42
8+
assert libvar == 43
9+
assert libclass().method() == 44
10+
11+
# End with this
12+
finished = True

vm/tests/import_name.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env python3.4
2+
3+
# test IMPORT_NAME
4+
5+
import lib
6+
7+
assert lib.libfn() == 42
8+
assert lib.libvar == 43
9+
assert lib.libclass().method() == 44
10+
11+
# End with this
12+
finished = True

vm/tests/import_star.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env python3.4
2+
3+
# test IMPORT_STAR
4+
5+
from lib import *
6+
7+
assert libfn() == 42
8+
assert libvar == 43
9+
assert libclass().method() == 44
10+
11+
# FIXME - exception catching not working
12+
# ok = False
13+
# try:
14+
# _libprivate
15+
# except NameError:
16+
# ok = True
17+
# assert ok
18+
19+
from lib1 import *
20+
21+
assert lib1fn() == 42
22+
assert lib1var == 43
23+
24+
# FIXME - exception handling broken
25+
# ok = False
26+
# try:
27+
# lib1class
28+
# except NameError:
29+
# ok = True
30+
# assert ok
31+
32+
# FIXME - exception handling broken
33+
# ok = False
34+
# try:
35+
# _libprivate
36+
# except NameError:
37+
# ok = True
38+
# assert ok
39+
40+
# End with this
41+
finished = True

vm/tests/lib.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env python3.4
2+
3+
# Some targets to be imported
4+
5+
def libfn():
6+
return 42
7+
8+
libvar = 43
9+
10+
class libclass:
11+
def method(self):
12+
return 44
13+
14+
_libprivate = 45

vm/tests/lib1.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python3.4
2+
3+
# Some targets to be imported
4+
5+
__all__ = [
6+
"lib1fn",
7+
"lib1var",
8+
]
9+
10+
def lib1fn():
11+
return 42
12+
13+
lib1var = 43
14+
15+
class lib1class:
16+
def method(self):
17+
return 44
18+
19+
_lib1private = 45

vm/vm_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ func TestVm(t *testing.T) {
5555
t.Fatalf("ReadDir failed: %v", err)
5656
}
5757
for _, f := range files {
58-
name := path.Join(testDir, f.Name())
59-
if strings.HasSuffix(name, ".py") {
60-
t.Logf("%s: Starting", name)
58+
name := f.Name()
59+
if !strings.HasPrefix(name, "lib") && strings.HasSuffix(name, ".py") {
60+
name := path.Join(testDir, name)
61+
t.Logf("%s: Running", name)
6162
run(t, name)
6263
}
6364
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy