diff --git a/derive/src/pymodule.rs b/derive/src/pymodule.rs index a1d509c1e..58b297d6a 100644 --- a/derive/src/pymodule.rs +++ b/derive/src/pymodule.rs @@ -20,8 +20,8 @@ pub fn impl_pymodule( attr: AttributeArgs, module_item: Item, ) -> std::result::Result { - let mut module_item = match module_item { - Item::Mod(m) => m, + let (doc, mut module_item) = match module_item { + Item::Mod(m) => (m.attrs.doc(), m), other => bail_span!(other, "#[pymodule] can only be on a full module"), }; let fake_ident = Ident::new("pymodule", module_item.span()); @@ -58,10 +58,24 @@ pub fn impl_pymodule( // append additional items let module_name = context.name.as_str(); let module_extend_items = context.module_extend_items; + let doc = doc.or_else(|| { + crate::doc::try_read(module_name) + .ok() + .flatten() + .map(str::to_owned) + }); + let doc = if let Some(doc) = doc { + quote!(Some(#doc)) + } else { + quote!(None) + }; items.extend(iter_chain![ parse_quote! { pub(crate) const MODULE_NAME: &'static str = #module_name; }, + parse_quote! { + pub(crate) const DOC: Option<&'static str> = #doc; + }, parse_quote! { pub(crate) fn extend_module( vm: &::rustpython_vm::VirtualMachine, @@ -75,7 +89,7 @@ pub fn impl_pymodule( pub(crate) fn make_module( vm: &::rustpython_vm::VirtualMachine ) -> ::rustpython_vm::PyObjectRef { - let module = vm.new_module(MODULE_NAME, vm.ctx.new_dict()); + let module = vm.new_module(MODULE_NAME, vm.ctx.new_dict(), DOC); extend_module(vm, &module); module } diff --git a/src/lib.rs b/src/lib.rs index 16a64f636..71a468418 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -519,7 +519,7 @@ fn write_profile(matches: &ArgMatches) -> Result<(), Box> fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> { let scope = vm.new_scope_with_builtins(); - let main_module = vm.new_module("__main__", scope.globals.clone()); + let main_module = vm.new_module("__main__", scope.globals.clone(), None); main_module .dict() .and_then(|d| { diff --git a/vm/src/import.rs b/vm/src/import.rs index 5bc0b2d58..4e42daf2e 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -130,7 +130,7 @@ pub fn import_codeobj( if set_file_attr { attrs.set_item("__file__", vm.ctx.new_utf8_str(&code_obj.source_path), vm)?; } - let module = vm.new_module(module_name, attrs.clone()); + let module = vm.new_module(module_name, attrs.clone(), None); // Store module in cache to prevent infinite loop with mutual importing libs: let sys_modules = vm.get_attribute(vm.sys_module.clone(), "modules")?; diff --git a/vm/src/macros.rs b/vm/src/macros.rs index 6997e9231..d12bb4d2b 100644 --- a/vm/src/macros.rs +++ b/vm/src/macros.rs @@ -1,7 +1,7 @@ #[macro_export] macro_rules! py_module { ( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)? }) => {{ - let module = $vm.new_module($module_name, $vm.ctx.new_dict()); + let module = $vm.new_module($module_name, $vm.ctx.new_dict(), None); $crate::extend_module!($vm, module, { $($name => $value),* }); module }}; diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 576bf8ad6..a8ff07e5e 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -574,12 +574,13 @@ impl VirtualMachine { self.ctx.new_code_object(code.into_codeobj(self)) } - pub fn new_module(&self, name: &str, dict: PyDictRef) -> PyObjectRef { + pub fn new_module(&self, name: &str, dict: PyDictRef, doc: Option<&str>) -> PyObjectRef { module::init_module_dict( self, &dict, self.new_pyobj(name.to_owned()), - self.ctx.none(), + doc.map(|doc| self.new_pyobj(doc.to_owned())) + .unwrap_or_else(|| self.ctx.none()), ); PyObject::new(PyModule {}, self.ctx.types.module_type.clone(), Some(dict)) } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 6818076c7..aaf5e13e9 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -280,7 +280,7 @@ impl WASMVirtualMachine { vm.run_code_obj(code, Scope::new(None, attrs.clone())) .into_js(vm)?; - let module = vm.new_module(&name, attrs); + let module = vm.new_module(&name, attrs, None); let sys_modules = vm .get_attribute(vm.sys_module.clone(), "modules") @@ -294,7 +294,7 @@ impl WASMVirtualMachine { #[wasm_bindgen(js_name = injectJSModule)] pub fn inject_js_module(&self, name: String, module: Object) -> Result<(), JsValue> { self.with_vm(|vm, _| { - let py_module = vm.new_module(&name, vm.ctx.new_dict()); + let py_module = vm.new_module(&name, vm.ctx.new_dict(), None); for entry in convert::object_entries(&module) { let (key, value) = entry?; let key = Object::from(key).to_string();