Merge pull request #990 from skinny121/simple_namespace

Add SimpleNamespace and sys.implementation
This commit is contained in:
coolreader18
2019-05-19 14:02:24 -05:00
committed by GitHub
8 changed files with 80 additions and 1 deletions

View File

@@ -13,7 +13,7 @@ FunctionType = type(_f)
LambdaType = type(lambda: None) # Same as FunctionType
CodeType = type(_f.__code__)
MappingProxyType = type(type.__dict__)
# SimpleNamespace = type(sys.implementation)
SimpleNamespace = type(sys.implementation)
def _g():
yield 1

View File

@@ -0,0 +1,10 @@
import types
from testutils import assertRaises
ns = types.SimpleNamespace(a=2, b='Rust')
assert ns.a == 2
assert ns.b == "Rust"
with assertRaises(AttributeError):
_ = ns.c

View File

@@ -7,3 +7,6 @@ assert sys.platform == "linux" or sys.platform == "darwin" or sys.platform == "w
assert isinstance(sys.builtin_module_names, tuple)
assert 'sys' in sys.builtin_module_names
assert isinstance(sys.implementation.name, str)
assert isinstance(sys.implementation.cache_tag, str)

View File

@@ -157,6 +157,19 @@ macro_rules! extend_class {
}
}
#[macro_export]
macro_rules! py_namespace {
( $vm:expr, { $($name:expr => $value:expr),* $(,)* }) => {
{
let namespace = $vm.ctx.new_namespace();
$(
$vm.set_attr(&namespace, $name, $value).unwrap();
)*
namespace
}
}
}
/// Macro to match on the built-in class of a Python object.
///
/// Like `match`, `match_class!` must be exhaustive, so a default arm with

View File

@@ -23,6 +23,7 @@ pub mod objmap;
pub mod objmappingproxy;
pub mod objmemory;
pub mod objmodule;
pub mod objnamespace;
pub mod objnone;
pub mod objobject;
pub mod objproperty;

View File

@@ -0,0 +1,32 @@
use crate::function::KwArgs;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{PyClassImpl, PyContext, PyRef, PyResult, PyValue};
use crate::vm::VirtualMachine;
/// A simple attribute-based namespace.
///
/// SimpleNamespace(**kwargs)
#[pyclass(name = "SimpleNamespace")]
#[derive(Debug)]
pub struct PyNamespace;
impl PyValue for PyNamespace {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.ctx.namespace_type()
}
}
#[pyimpl]
impl PyNamespace {
#[pymethod(name = "__init__")]
fn init(zelf: PyRef<Self>, kwargs: KwArgs, vm: &VirtualMachine) -> PyResult<()> {
for (name, value) in kwargs.into_iter() {
vm.set_attr(zelf.as_object(), name, value)?;
}
Ok(())
}
}
pub fn init(context: &PyContext) {
PyNamespace::extend_class(context, &context.namespace_type);
}

View File

@@ -40,6 +40,7 @@ use crate::obj::objmap;
use crate::obj::objmappingproxy;
use crate::obj::objmemory;
use crate::obj::objmodule::{self, PyModule};
use crate::obj::objnamespace::{self, PyNamespace};
use crate::obj::objnone::{self, PyNone, PyNoneRef};
use crate::obj::objobject;
use crate::obj::objproperty;
@@ -158,6 +159,7 @@ pub struct PyContext {
pub property_type: PyClassRef,
pub readonly_property_type: PyClassRef,
pub module_type: PyClassRef,
pub namespace_type: PyClassRef,
pub bound_method_type: PyClassRef,
pub weakref_type: PyClassRef,
pub weakproxy_type: PyClassRef,
@@ -250,6 +252,7 @@ impl PyContext {
let dict_type = create_type("dict", &type_type, &object_type);
let module_type = create_type("module", &type_type, &object_type);
let namespace_type = create_type("SimpleNamespace", &type_type, &object_type);
let classmethod_type = create_type("classmethod", &type_type, &object_type);
let staticmethod_type = create_type("staticmethod", &type_type, &object_type);
let function_type = create_type("function", &type_type, &object_type);
@@ -366,6 +369,7 @@ impl PyContext {
readonly_property_type,
generator_type,
module_type,
namespace_type,
bound_method_type,
weakref_type,
weakproxy_type,
@@ -407,6 +411,7 @@ impl PyContext {
objweakproxy::init(&context);
objnone::init(&context);
objmodule::init(&context);
objnamespace::init(&context);
objmappingproxy::init(&context);
exceptions::init(&context);
context
@@ -464,6 +469,10 @@ impl PyContext {
self.module_type.clone()
}
pub fn namespace_type(&self) -> PyClassRef {
self.namespace_type.clone()
}
pub fn set_type(&self) -> PyClassRef {
self.set_type.clone()
}
@@ -658,6 +667,10 @@ impl PyContext {
)
}
pub fn new_namespace(&self) -> PyObjectRef {
PyObject::new(PyNamespace, self.namespace_type(), Some(self.new_dict()))
}
pub fn new_rustfunc<F, T, R>(&self, f: F) -> PyObjectRef
where
F: IntoPyNativeFunc<T, R>,

View File

@@ -48,6 +48,12 @@ fn sys_intern(value: PyStringRef, _vm: &VirtualMachine) -> PyStringRef {
pub fn make_module(vm: &VirtualMachine, module: PyObjectRef, builtins: PyObjectRef) {
let ctx = &vm.ctx;
// TODO Add crate version to this namespace
let implementation = py_namespace!(vm, {
"name" => ctx.new_str("RustPython".to_string()),
"cache_tag" => ctx.new_str("rustpython-01".to_string()),
});
let path_list = match env::var_os("PYTHONPATH") {
Some(paths) => env::split_paths(&paths)
.map(|path| {
@@ -154,6 +160,7 @@ settrace() -- set the global debug tracing function
"builtin_module_names" => ctx.new_tuple(module_names.iter().map(|v| v.into_pyobject(vm).unwrap()).collect()),
"getrefcount" => ctx.new_rustfunc(sys_getrefcount),
"getsizeof" => ctx.new_rustfunc(sys_getsizeof),
"implementation" => implementation,
"intern" => ctx.new_rustfunc(sys_intern),
"maxsize" => ctx.new_int(std::usize::MAX),
"path" => path,