Commit e76e3836 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #64 from vinzenz/dir-builtin

Added implementation of 'dir'
parents e1e5f01a c5ee90e5
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "runtime/set.h" #include "runtime/set.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
#include "runtime/list.h"
namespace pyston { namespace pyston {
extern "C" Box* trap() { extern "C" Box* trap() {
...@@ -34,6 +34,47 @@ extern "C" Box* trap() { ...@@ -34,6 +34,47 @@ extern "C" Box* trap() {
return None; return None;
} }
extern "C" Box* dir1(Box* obj) {
// TODO: Recursive class traversal for lookup of types and eliminating
// duplicates afterwards
BoxedList* result = nullptr;
// If __dir__ is present just call it and return what it returns
static std::string attr_dir = "__dir__";
Box* dir_result = callattrInternal(obj, &attr_dir, CLASS_ONLY, nullptr, 0, nullptr, nullptr, nullptr, nullptr);
if (dir_result && dir_result->cls == list_cls) {
return dir_result;
}
// If __dict__ is present use its keys and add the reset below
Box* obj_dict = getattr_internal(obj, "__dict__", false, true, nullptr, nullptr);
if (obj_dict && obj_dict->cls == dict_cls) {
result = new BoxedList();
for (auto& kv : static_cast<BoxedDict*>(obj_dict)->d) {
listAppend(result, kv.first);
}
}
if (!result) {
result = new BoxedList();
}
for (auto const& kv : obj->cls->hcls->attr_offsets) {
listAppend(result, boxString(kv.first));
}
if (obj->cls->hasattrs) {
HCBox* hcb = static_cast<HCBox*>(obj);
for (auto const& kv : hcb->hcls->attr_offsets) {
listAppend(result, boxString(kv.first));
}
}
return result;
}
extern "C" Box* dir0() {
// TODO: This should actually return the elements in the current local
// scope not the content of the builtins_module
return dir1(builtins_module);
}
extern "C" Box* abs_(Box* x) { extern "C" Box* abs_(Box* x) {
if (x->cls == int_cls) { if (x->cls == int_cls) {
i64 n = static_cast<BoxedInt*>(x)->n; i64 n = static_cast<BoxedInt*>(x)->n;
...@@ -507,7 +548,9 @@ void setupBuiltins() { ...@@ -507,7 +548,9 @@ void setupBuiltins() {
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2, false))); builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2, false)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2, false))); builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2, false)));
CLFunction* dir_clf = boxRTFunction((void*)dir0, LIST, 0, false);
addRTFunction(dir_clf, (void*)dir1, LIST, 1, false);
builtins_module->giveAttr("dir", new BoxedFunction(dir_clf));
builtins_module->giveAttr("object", object_cls); builtins_module->giveAttr("object", object_cls);
builtins_module->giveAttr("str", str_cls); builtins_module->giveAttr("str", str_cls);
builtins_module->giveAttr("int", int_cls); builtins_module->giveAttr("int", int_cls);
......
import sys
__package__ = "Test"
__builtins__ = None
__doc__ = None
def fake():
# manually sorted: ['all', 'these', 'attributes', 'do', 'not', 'exist']
return ['all', 'attributes', 'do', 'exist', 'not', 'these']
class TestClass(object):
def __init__(self):
self.__dict__ = {n: n for n in fake()}
def __dir__(self):
return fake()
class TestClass2(object):
def __init__(self):
self.__dict__ = {'dictAttr': False, 'attribute1': None}
self.other_attribute = False
def method1(self):
pass
# All attributes are different between CPython 2.7.5 and pyston
# CPython has more
dir(sys.modules[__name__])
dir(TestClass())
dir(TestClass2())
dir(str())
dir(list())
dir({})
dir(int())
# dir(long())
dir(dir)
dir(fake)
dir(None)
dir()
dir(TestClass)
dir(TestClass2)
dir(sys)
dir(dict)
dir(int)
dir(str)
dir(set)
def test_in_dir(names, obj):
r = dir(obj)
print [n in r for n in names]
test_in_dir(fake(), TestClass())
test_in_dir(['attribute1', 'method1'], TestClass2)
test_in_dir(['attribute1', 'method1', 'dictAttr'], TestClass2())
test_in_dir(['__str__', '__new__', '__repr__', '__dir__', '__init__',
'__module__'] + fake(), TestClass)
test_in_dir(['__str__', '__new__', '__repr__', '__dir__', '__init__',
'__module__', 'method1', 'dictAttr', 'attribute1'], TestClass2)
test_in_dir(['attribute1', 'dictAttr', '__init__', '__module__', 'method1',
'other_attribute', '__dict__'], TestClass2())
test_in_dir(fake(), TestClass())
print len(fake()) == len(dir(TestClass()))
for t in [str, int, list, set, dict]:
test_in_dir(['__str__', '__new__', '__repr__', '__dir__', '__module__'], t)
...@@ -8,4 +8,6 @@ x = repr(empty_module) ...@@ -8,4 +8,6 @@ x = repr(empty_module)
print x[0:29] print x[0:29]
print x[-2:] print x[-2:]
print repr(math) # no path for built-ins, so we can just check as normal # cpython 2.7.5 writes "from '/usr/lib64/python2.7/lib-dynload/math.so'"
# pyston writes "(built-in)"
print repr(math)[0:15] + "(built-in)>"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment