diff --git a/derive-impl/src/pymodule.rs b/derive-impl/src/pymodule.rs index e6ebe6365b..329c1dcd8d 100644 --- a/derive-impl/src/pymodule.rs +++ b/derive-impl/src/pymodule.rs @@ -2,7 +2,7 @@ use crate::error::Diagnostic; use crate::util::{ format_doc, iter_use_idents, pyclass_ident_and_attrs, text_signature, AttrItemMeta, AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery, - SimpleItemMeta, ALL_ALLOWED_NAMES, + ModuleItemMeta, SimpleItemMeta, ALL_ALLOWED_NAMES, }; use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; @@ -45,7 +45,9 @@ impl FromStr for AttrName { #[derive(Default)] struct ModuleContext { name: String, - module_extend_items: ItemNursery, + function_items: FunctionNursery, + attribute_items: ItemNursery, + has_extend_module: bool, // TODO: check if `fn extend_module` exists errors: Vec, } @@ -56,7 +58,7 @@ pub fn impl_pymodule(attr: AttributeArgs, module_item: Item) -> Result Result Result = #doc; + }, + parse_quote! { + pub(crate) fn __module_def( + ctx: &::rustpython_vm::Context, + ) -> &'static ::rustpython_vm::builtins::PyModuleDef { + DEF.get_or_init(|| { + let mut def = ::rustpython_vm::builtins::PyModuleDef { + name: ctx.intern_str(MODULE_NAME), + doc: DOC.map(|doc| ctx.intern_str(doc)), + slots: Default::default(), + }; + def.slots.exec = Some(extend_module); + def + }) + } + }, + parse_quote! { + #[allow(dead_code)] + pub(crate) fn make_module( + vm: &::rustpython_vm::VirtualMachine + ) -> ::rustpython_vm::PyRef<::rustpython_vm::builtins::PyModule> { + use ::rustpython_vm::PyPayload; + let module = ::rustpython_vm::builtins::PyModule::from_def(__module_def(&vm.ctx)).into_ref(&vm.ctx); + __init_dict(vm, &module); + extend_module(vm, &module).unwrap(); + module + } + }, + ]); + } + if !is_submodule && !context.has_extend_module { + items.push(parse_quote! { + pub(crate) fn extend_module(vm: &::rustpython_vm::VirtualMachine, module: &::rustpython_vm::Py<::rustpython_vm::builtins::PyModule>) -> ::rustpython_vm::PyResult<()> { + __extend_module(vm, module); + Ok(()) + } + }); + } items.extend(iter_chain![ parse_quote! { - pub(crate) const MODULE_NAME: &'static str = #module_name; + ::rustpython_vm::common::static_cell! { + pub(crate) static DEF: ::rustpython_vm::builtins::PyModuleDef; + } + }, + parse_quote! { + pub(crate) fn __init_attributes( + vm: &::rustpython_vm::VirtualMachine, + module: &::rustpython_vm::Py<::rustpython_vm::builtins::PyModule>, + ) { + #( + super::#withs::__init_attributes(vm, module); + )* + let ctx = &vm.ctx; + #attribute_items + } }, parse_quote! { - pub(crate) const DOC: Option<&'static str> = #doc; + pub(crate) fn __extend_module( + vm: &::rustpython_vm::VirtualMachine, + module: &::rustpython_vm::Py<::rustpython_vm::builtins::PyModule>, + ) { + __init_methods(vm, module); + __init_attributes(vm, module); + } }, parse_quote! { - pub(crate) fn extend_module( + // TODO: remove once PyMethodDef done + pub(crate) fn __init_methods( vm: &::rustpython_vm::VirtualMachine, module: &::rustpython_vm::Py<::rustpython_vm::builtins::PyModule>, ) { - #module_extend_items + #( + super::#withs::__init_methods(vm, module); + )* + let ctx = &vm.ctx; + #function_items } }, parse_quote! { - #[allow(dead_code)] - pub(crate) fn make_module( - vm: &::rustpython_vm::VirtualMachine - ) -> ::rustpython_vm::PyRef<::rustpython_vm::builtins::PyModule> { - let module = vm.new_module(MODULE_NAME, vm.ctx.new_dict(), DOC); - extend_module(vm, &module); - module + pub(crate) fn __init_dict( + vm: &::rustpython_vm::VirtualMachine, + module: &::rustpython_vm::Py<::rustpython_vm::builtins::PyModule>, + ) { + ::rustpython_vm::builtins::PyModule::__init_dict_from_def(vm, module); } }, ]); @@ -248,6 +321,53 @@ where Ok((result, cfgs)) } +#[derive(Default)] +struct FunctionNursery { + items: Vec, +} + +struct FunctionNurseryItem { + py_names: Vec, + cfgs: Vec, + ident: Ident, + #[allow(dead_code)] + doc: String, + tokens: TokenStream, +} + +impl FunctionNursery { + fn add_item(&mut self, item: FunctionNurseryItem) { + self.items.push(item); + } + + fn validate(self) -> Result { + let mut name_set = HashSet::new(); + for item in &self.items { + for py_name in &item.py_names { + if !name_set.insert((py_name.to_owned(), &item.cfgs)) { + bail_span!(item.ident, "duplicate method name `{}`", py_name); + } + } + } + Ok(ValidatedFunctionNursery(self)) + } +} + +struct ValidatedFunctionNursery(FunctionNursery); + +impl ToTokens for ValidatedFunctionNursery { + fn to_tokens(&self, tokens: &mut TokenStream) { + for item in &self.0.items { + let cfgs = &item.cfgs; + let item_tokens = &item.tokens; + tokens.extend(quote! { + #(#cfgs)* + #item_tokens + }); + } + } +} + /// #[pyfunction] struct FunctionItem { inner: ContentItemInner, @@ -318,7 +438,7 @@ impl ModuleItem for FunctionItem { let py_name = item_meta.simple_name()?; let sig_doc = text_signature(func.sig(), &py_name); - let (tokens, py_names) = { + let (tokens, py_names, doc) = { let module = args.module_name(); let doc = args.attrs.doc().or_else(|| { crate::doc::Database::shared() @@ -332,10 +452,10 @@ impl ModuleItem for FunctionItem { } else { sig_doc }; - let doc = quote!(.with_doc(#doc.to_owned(), &vm.ctx)); + let with_doc = quote!(.with_doc(#doc.to_owned(), &vm.ctx)); let new_func = quote_spanned!(ident.span()=> vm.ctx.make_func_def(vm.ctx.intern_str(#py_name), #ident) - #doc + #with_doc .into_function() .with_module(vm.new_pyobj(#module.to_owned())) .into_ref(&vm.ctx) @@ -348,6 +468,7 @@ impl ModuleItem for FunctionItem { vm.__module_set_attr(module, #py_name, func).unwrap(); }}, vec![py_name], + doc, ) } else { let mut py_names = HashSet::new(); @@ -381,17 +502,18 @@ impl ModuleItem for FunctionItem { } }}, py_names, + doc, ) } }; - args.context.module_extend_items.add_item( - ident.clone(), + args.context.function_items.add_item(FunctionNurseryItem { + ident: ident.to_owned(), py_names, - args.cfgs.to_vec(), + cfgs: args.cfgs.to_vec(), + doc, tokens, - 10, - )?; + }); Ok(()) } } @@ -432,8 +554,8 @@ impl ModuleItem for ClassItem { class_meta.class_name()? }; let class_new = quote_spanned!(ident.span() => - let new_class = <#ident as ::rustpython_vm::class::PyClassImpl>::make_class(&vm.ctx); - new_class.set_attr(rustpython_vm::identifier!(vm, __module__), vm.new_pyobj(#module_name)); + let new_class = <#ident as ::rustpython_vm::class::PyClassImpl>::make_class(ctx); + new_class.set_attr(rustpython_vm::identifier!(ctx, __module__), vm.new_pyobj(#module_name)); ); (class_name, class_new) }; @@ -473,7 +595,7 @@ impl ModuleItem for ClassItem { }, }; - args.context.module_extend_items.add_item( + args.context.attribute_items.add_item( ident.clone(), py_names, args.cfgs.to_vec(), @@ -561,7 +683,7 @@ impl ModuleItem for AttributeItem { let tokens = quote_spanned! { ident.span() => vm.__module_set_attr(module, #py_name, vm.new_pyobj(#ident)).unwrap(); }; - args.context.module_extend_items.add_item( + args.context.attribute_items.add_item( ident.clone(), vec![py_name], cfgs.clone(), @@ -624,7 +746,7 @@ impl ModuleItem for AttributeItem { }; args.context - .module_extend_items + .attribute_items .add_item(ident, py_names, cfgs, tokens, 1)?; Ok(()) diff --git a/derive-impl/src/util.rs b/derive-impl/src/util.rs index 97a6aaf097..c0979f0807 100644 --- a/derive-impl/src/util.rs +++ b/derive-impl/src/util.rs @@ -197,6 +197,21 @@ impl ItemMetaInner { }; Ok(value) } + + pub fn _optional_list( + &self, + key: &str, + ) -> Result>> { + let value = if let Some((_, meta)) = self.meta_map.get(key) { + let Meta::List(syn::MetaList { path: _, nested, .. }) = meta else { + bail_span!(meta, "#[{}({}(...))] must be a list", self.meta_name(), key) + }; + Some(nested.into_iter()) + } else { + None + }; + Ok(value) + } } pub(crate) trait ItemMeta: Sized { @@ -251,6 +266,38 @@ impl ItemMeta for SimpleItemMeta { } } +pub(crate) struct ModuleItemMeta(pub ItemMetaInner); + +impl ItemMeta for ModuleItemMeta { + const ALLOWED_NAMES: &'static [&'static str] = &["name", "with", "sub"]; + + fn from_inner(inner: ItemMetaInner) -> Self { + Self(inner) + } + fn inner(&self) -> &ItemMetaInner { + &self.0 + } +} + +impl ModuleItemMeta { + pub fn sub(&self) -> Result { + self.inner()._bool("sub") + } + pub fn with(&self) -> Result> { + let mut withs = Vec::new(); + let Some(nested) = self.inner()._optional_list("with")? else { + return Ok(withs); + }; + for meta in nested { + let NestedMeta::Meta(Meta::Path(path)) = meta else { + bail_span!(meta, "#[pymodule(with(...))] arguments should be paths") + }; + withs.push(path); + } + Ok(withs) + } +} + pub(crate) struct AttrItemMeta(pub ItemMetaInner); impl ItemMeta for AttrItemMeta { diff --git a/stdlib/src/ssl.rs b/stdlib/src/ssl.rs index 8248ee41b0..063dd6e764 100644 --- a/stdlib/src/ssl.rs +++ b/stdlib/src/ssl.rs @@ -7,20 +7,11 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { openssl_probe::init_ssl_cert_env_vars(); } openssl::init(); - - let module = _ssl::make_module(vm); - #[cfg(ossl101)] - ossl101::extend_module(vm, &module); - #[cfg(ossl111)] - ossl101::extend_module(vm, &module); - #[cfg(windows)] - windows::extend_module(vm, &module); - - module + _ssl::make_module(vm) } #[allow(non_upper_case_globals)] -#[pymodule] +#[pymodule(with(ossl101, windows))] mod _ssl { use super::bio; use crate::{ @@ -1405,9 +1396,21 @@ mod _ssl { } } +#[cfg(not(ossl101))] +#[pymodule(sub)] +mod ossl101 {} + +#[cfg(not(ossl111))] +#[pymodule(sub)] +mod ossl111 {} + +#[cfg(not(windows))] +#[pymodule(sub)] +mod windows {} + #[allow(non_upper_case_globals)] #[cfg(ossl101)] -#[pymodule] +#[pymodule(sub)] mod ossl101 { #[pyattr] use openssl_sys::{ @@ -1418,14 +1421,14 @@ mod ossl101 { #[allow(non_upper_case_globals)] #[cfg(ossl111)] -#[pymodule] +#[pymodule(sub)] mod ossl111 { #[pyattr] use openssl_sys::SSL_OP_NO_TLSv1_3 as OP_NO_TLSv1_3; } #[cfg(windows)] -#[pymodule] +#[pymodule(sub)] mod windows { use crate::{ common::ascii, diff --git a/vm/src/builtins/mod.rs b/vm/src/builtins/mod.rs index f068e94a95..ae3b7eea2a 100644 --- a/vm/src/builtins/mod.rs +++ b/vm/src/builtins/mod.rs @@ -47,7 +47,7 @@ pub use mappingproxy::PyMappingProxy; pub(crate) mod memory; pub use memory::PyMemoryView; pub(crate) mod module; -pub use module::PyModule; +pub use module::{PyModule, PyModuleDef}; pub(crate) mod namespace; pub use namespace::PyNamespace; pub(crate) mod object; diff --git a/vm/src/builtins/module.rs b/vm/src/builtins/module.rs index 3de1e21417..4c77bc2677 100644 --- a/vm/src/builtins/module.rs +++ b/vm/src/builtins/module.rs @@ -5,12 +5,53 @@ use crate::{ convert::ToPyObject, function::FuncArgs, types::{GetAttr, Initializer, Representable}, - AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, + AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, }; #[pyclass(module = false, name = "module")] #[derive(Debug)] -pub struct PyModule {} +pub struct PyModuleDef { + // pub index: usize, + pub name: &'static PyStrInterned, + pub doc: Option<&'static PyStrInterned>, + // pub size: isize, + // pub methods: &'static [PyMethodDef], + pub slots: PyModuleSlots, + // traverse: traverseproc + // clear: inquiry + // free: freefunc +} + +pub type ModuleCreate = + fn(&VirtualMachine, &PyObject, &'static PyModuleDef) -> PyResult>; +pub type ModuleExec = fn(&VirtualMachine, &Py) -> PyResult<()>; + +#[derive(Default)] +pub struct PyModuleSlots { + pub create: Option, + pub exec: Option, +} + +impl std::fmt::Debug for PyModuleSlots { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PyModuleSlots") + .field("create", &self.create.is_some()) + .field("exec", &self.exec.is_some()) + .finish() + } +} + +#[allow(clippy::new_without_default)] // avoid Default implementation +#[pyclass(module = false, name = "module")] +#[derive(Debug)] +pub struct PyModule { + // PyObject *md_dict; + pub def: Option<&'static PyModuleDef>, + // state: Any + // weaklist + // for logging purposes after md_dict is cleared + pub name: Option<&'static PyStrInterned>, +} impl PyPayload for PyModule { fn class(ctx: &Context) -> &'static Py { @@ -26,9 +67,23 @@ pub struct ModuleInitArgs { } impl PyModule { - // pub(crate) fn new(d: PyDictRef) -> Self { - // PyModule { dict: d.into() } - // } + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + def: None, + name: None, + } + } + pub fn from_def(def: &'static PyModuleDef) -> Self { + Self { + def: Some(def), + name: Some(def.name), + } + } + pub fn __init_dict_from_def(vm: &VirtualMachine, module: &Py) { + let doc = module.def.unwrap().doc.map(|doc| doc.to_owned()); + module.init_module_dict(module.name.unwrap(), doc, vm); + } } impl Py { @@ -63,13 +118,13 @@ impl Py { pub(crate) fn init_module_dict( &self, name: &'static PyStrInterned, - doc: PyObjectRef, + doc: Option, vm: &VirtualMachine, ) { let dict = self.dict(); dict.set_item(identifier!(vm, __name__), name.to_object(), vm) .expect("Failed to set __name__ on module"); - dict.set_item(identifier!(vm, __doc__), doc, vm) + dict.set_item(identifier!(vm, __doc__), doc.to_pyobject(vm), vm) .expect("Failed to set __doc__ on module"); dict.set_item("__package__", vm.ctx.none(), vm) .expect("Failed to set __package__ on module"); @@ -98,7 +153,7 @@ impl Py { impl PyModule { #[pyslot] fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult { - PyModule {}.into_ref_with_type(vm, cls).map(Into::into) + PyModule::new().into_ref_with_type(vm, cls).map(Into::into) } #[pymethod(magic)] @@ -121,11 +176,7 @@ impl Initializer for PyModule { .slots .flags .has_feature(crate::types::PyTypeFlags::HAS_DICT)); - zelf.init_module_dict( - vm.ctx.intern_str(args.name.as_str()), - args.doc.to_pyobject(vm), - vm, - ); + zelf.init_module_dict(vm.ctx.intern_str(args.name.as_str()), args.doc, vm); Ok(()) } } diff --git a/vm/src/stdlib/builtins.rs b/vm/src/stdlib/builtins.rs index 0405db8bfe..a7522f097d 100644 --- a/vm/src/stdlib/builtins.rs +++ b/vm/src/stdlib/builtins.rs @@ -939,7 +939,7 @@ pub fn init_module(vm: &VirtualMachine, module: &Py) { crate::protocol::VecBuffer::make_class(&vm.ctx); - builtins::extend_module(vm, module); + builtins::extend_module(vm, module).unwrap(); let debug_mode: bool = vm.state.settings.optimize == 0; extend_module!(vm, module, { diff --git a/vm/src/stdlib/imp.rs b/vm/src/stdlib/imp.rs index 9c78afa07b..dc1bc0fe83 100644 --- a/vm/src/stdlib/imp.rs +++ b/vm/src/stdlib/imp.rs @@ -1,17 +1,9 @@ use crate::bytecode::frozen_lib::FrozenModule; -use crate::{ - builtins::{PyBaseExceptionRef, PyModule}, - PyRef, VirtualMachine, -}; - -pub fn make_module(vm: &VirtualMachine) -> PyRef { - let module = _imp::make_module(vm); - lock::extend_module(vm, &module); - module -} +use crate::{builtins::PyBaseExceptionRef, VirtualMachine}; +pub(crate) use _imp::make_module; #[cfg(feature = "threading")] -#[pymodule] +#[pymodule(sub)] mod lock { use crate::{stdlib::thread::RawRMutex, PyResult, VirtualMachine}; @@ -39,7 +31,7 @@ mod lock { } #[cfg(not(feature = "threading"))] -#[pymodule] +#[pymodule(sub)] mod lock { use crate::vm::VirtualMachine; #[pyfunction] @@ -85,12 +77,12 @@ fn find_frozen(name: &str, vm: &VirtualMachine) -> Result PyResult { let sys_modules = vm.sys_module.get_attr("modules", vm).unwrap(); - let name = spec.get_attr("name", vm)?; - let name = PyStrRef::try_from_object(vm, name)?; + let name: PyStrRef = spec.get_attr("name", vm)?.try_into_value(vm)?; - if let Ok(module) = sys_modules.get_item(&*name, vm) { - Ok(module) + let module = if let Ok(module) = sys_modules.get_item(&*name, vm) { + module } else if let Some(make_module_func) = vm.state.module_inits.get(name.as_str()) { - Ok(make_module_func(vm).into()) + make_module_func(vm).into() } else { - Ok(vm.ctx.none()) - } + vm.ctx.none() + }; + Ok(module) } #[pyfunction] diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index c5d1a1eaff..3c98c146f3 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -51,7 +51,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { let module = _io::make_module(vm); #[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))] - fileio::extend_module(vm, &module); + fileio::extend_module(vm, &module).unwrap(); let unsupported_operation = _io::UNSUPPORTED_OPERATION .get_or_init(|| _io::make_unsupportedop(ctx)) diff --git a/vm/src/stdlib/nt.rs b/vm/src/stdlib/nt.rs index 2b248727b0..713648933d 100644 --- a/vm/src/stdlib/nt.rs +++ b/vm/src/stdlib/nt.rs @@ -8,7 +8,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { module } -#[pymodule(name = "nt")] +#[pymodule(name = "nt", with(super::os::_os))] pub(crate) mod module { use crate::{ builtins::{PyStrRef, PyTupleRef}, diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 78d6910774..e016c21a12 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -299,7 +299,7 @@ fn bytes_as_osstr<'a>(b: &'a [u8], vm: &VirtualMachine) -> PyResult<&'a ffi::OsS .map_err(|_| vm.new_unicode_decode_error("can't decode path for utf-8".to_owned())) } -#[pymodule(name = "_os")] +#[pymodule(sub)] pub(super) mod _os { use super::{ errno_err, DirFd, FollowSymlinks, IOErrorBuilder, OsPath, OsPathOrFd, OutputMode, @@ -1710,8 +1710,6 @@ impl SupportFunc { } pub fn extend_module(vm: &VirtualMachine, module: &Py) { - _os::extend_module(vm, module); - let support_funcs = _os::support_funcs(); let supports_fd = PySet::default().into_ref(&vm.ctx); let supports_dir_fd = PySet::default().into_ref(&vm.ctx); diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index 0bc3ca8aeb..5846aa0009 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -18,7 +18,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { module } -#[pymodule(name = "posix")] +#[pymodule(name = "posix", with(super::os::_os))] pub mod module { use crate::{ builtins::{PyDictRef, PyInt, PyListRef, PyStrRef, PyTupleRef, PyTypeRef}, diff --git a/vm/src/stdlib/posix_compat.rs b/vm/src/stdlib/posix_compat.rs index 5ef9583e7a..3f939dce10 100644 --- a/vm/src/stdlib/posix_compat.rs +++ b/vm/src/stdlib/posix_compat.rs @@ -1,6 +1,5 @@ //! `posix` compatible module for `not(any(unix, windows))` - -use crate::{builtins::PyModule, PyObjectRef, PyRef, VirtualMachine}; +use crate::{builtins::PyModule, PyRef, VirtualMachine}; pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { let module = module::make_module(vm); @@ -8,7 +7,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { module } -#[pymodule(name = "posix")] +#[pymodule(name = "posix", with(super::os::_os))] pub(crate) mod module { use crate::{ builtins::PyStrRef, diff --git a/vm/src/stdlib/sys.rs b/vm/src/stdlib/sys.rs index dc65f097c8..780d7b4ef9 100644 --- a/vm/src/stdlib/sys.rs +++ b/vm/src/stdlib/sys.rs @@ -917,7 +917,7 @@ mod sys { } pub(crate) fn init_module(vm: &VirtualMachine, module: &Py, builtins: &Py) { - sys::extend_module(vm, module); + sys::extend_module(vm, module).unwrap(); let modules = vm.ctx.new_dict(); modules diff --git a/vm/src/stdlib/time.rs b/vm/src/stdlib/time.rs index c4b57ce610..0f9f9e0bf1 100644 --- a/vm/src/stdlib/time.rs +++ b/vm/src/stdlib/time.rs @@ -2,21 +2,9 @@ // See also: // https://docs.python.org/3/library/time.html -use crate::{builtins::PyModule, PyRef, VirtualMachine}; - pub use time::*; -pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { - let module = time::make_module(vm); - #[cfg(unix)] - unix::extend_module(vm, &module); - #[cfg(windows)] - windows::extend_module(vm, &module); - - module -} - -#[pymodule(name = "time")] +#[pymodule(name = "time", with(platform))] mod time { use crate::{ builtins::{PyStrRef, PyTypeRef}, @@ -386,15 +374,12 @@ mod time { } #[allow(unused_imports)] - #[cfg(unix)] - use super::unix::*; - #[cfg(windows)] - use super::windows::*; + use super::platform::*; } #[cfg(unix)] -#[pymodule(name = "time")] -mod unix { +#[pymodule(sub)] +mod platform { #[allow(unused_imports)] use super::{SEC_TO_NS, US_TO_NS}; #[cfg_attr(target_os = "macos", allow(unused_imports))] @@ -631,8 +616,8 @@ mod unix { } #[cfg(windows)] -#[pymodule(name = "time")] -mod windows { +#[pymodule] +mod platform { use super::{time_muldiv, MS_TO_NS, SEC_TO_NS}; use crate::{ builtins::{PyNamespace, PyStrRef}, @@ -815,3 +800,8 @@ mod windows { Ok(Duration::from_nanos((k_time + u_time) * 100)) } } + +// mostly for wasm32 +#[cfg(not(any(unix, windows)))] +#[pymodule(sub)] +mod platform {} diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs index e9f09b75c9..2e546d3d6a 100644 --- a/vm/src/vm/mod.rs +++ b/vm/src/vm/mod.rs @@ -118,7 +118,7 @@ impl VirtualMachine { // set __spec__, __loader__, etc. attributes let new_module = || { PyRef::new_ref( - PyModule {}, + PyModule::new(), ctx.types.module_type.to_owned(), Some(ctx.new_dict()), ) @@ -200,9 +200,9 @@ impl VirtualMachine { PyRc::get_mut(&mut vm.state).unwrap().frozen = frozen; vm.builtins - .init_module_dict(vm.ctx.intern_str("builtins"), vm.ctx.none(), &vm); + .init_module_dict(vm.ctx.intern_str("builtins"), None, &vm); vm.sys_module - .init_module_dict(vm.ctx.intern_str("sys"), vm.ctx.none(), &vm); + .init_module_dict(vm.ctx.intern_str("sys"), None, &vm); vm } diff --git a/vm/src/vm/vm_new.rs b/vm/src/vm/vm_new.rs index a01a7c2763..38b37f81f2 100644 --- a/vm/src/vm/vm_new.rs +++ b/vm/src/vm/vm_new.rs @@ -22,14 +22,13 @@ impl VirtualMachine { pub fn new_module(&self, name: &str, dict: PyDictRef, doc: Option<&str>) -> PyRef { let module = PyRef::new_ref( - PyModule {}, + PyModule::new(), self.ctx.types.module_type.to_owned(), Some(dict), ); module.init_module_dict( self.ctx.intern_str(name), - doc.map(|doc| self.new_pyobj(doc.to_owned())) - .unwrap_or_else(|| self.ctx.none()), + doc.map(|doc| self.ctx.new_str(doc)), self, ); module