@@ -149,6 +149,8 @@ pub fn pymodule_module_impl(
149149 }
150150
151151 let mut pymodule_init = None ;
152+ let mut module_consts = Vec :: new ( ) ;
153+ let mut module_consts_cfg_attrs = Vec :: new ( ) ;
152154
153155 for item in & mut * items {
154156 match item {
@@ -168,7 +170,7 @@ pub fn pymodule_module_impl(
168170 Item :: Fn ( item_fn) => {
169171 ensure_spanned ! (
170172 !has_attribute( & item_fn. attrs, "pymodule_export" ) ,
171- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
173+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
172174 ) ;
173175 let is_pymodule_init =
174176 find_and_remove_attribute ( & mut item_fn. attrs , "pymodule_init" ) ;
@@ -199,7 +201,7 @@ pub fn pymodule_module_impl(
199201 Item :: Struct ( item_struct) => {
200202 ensure_spanned ! (
201203 !has_attribute( & item_struct. attrs, "pymodule_export" ) ,
202- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
204+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
203205 ) ;
204206 if has_attribute ( & item_struct. attrs , "pyclass" )
205207 || has_attribute_with_namespace (
@@ -227,7 +229,7 @@ pub fn pymodule_module_impl(
227229 Item :: Enum ( item_enum) => {
228230 ensure_spanned ! (
229231 !has_attribute( & item_enum. attrs, "pymodule_export" ) ,
230- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
232+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
231233 ) ;
232234 if has_attribute ( & item_enum. attrs , "pyclass" )
233235 || has_attribute_with_namespace ( & item_enum. attrs , Some ( pyo3_path) , & [ "pyclass" ] )
@@ -251,7 +253,7 @@ pub fn pymodule_module_impl(
251253 Item :: Mod ( item_mod) => {
252254 ensure_spanned ! (
253255 !has_attribute( & item_mod. attrs, "pymodule_export" ) ,
254- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
256+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
255257 ) ;
256258 if has_attribute ( & item_mod. attrs , "pymodule" )
257259 || has_attribute_with_namespace ( & item_mod. attrs , Some ( pyo3_path) , & [ "pymodule" ] )
@@ -278,61 +280,63 @@ pub fn pymodule_module_impl(
278280 Item :: ForeignMod ( item) => {
279281 ensure_spanned ! (
280282 !has_attribute( & item. attrs, "pymodule_export" ) ,
281- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
283+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
282284 ) ;
283285 }
284286 Item :: Trait ( item) => {
285287 ensure_spanned ! (
286288 !has_attribute( & item. attrs, "pymodule_export" ) ,
287- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
289+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
288290 ) ;
289291 }
290292 Item :: Const ( item) => {
291- ensure_spanned ! (
292- !has_attribute( & item. attrs, "pymodule_export" ) ,
293- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
294- ) ;
293+ if !find_and_remove_attribute ( & mut item. attrs , "pymodule_export" ) {
294+ continue ;
295+ }
296+
297+ module_consts. push ( item. ident . clone ( ) ) ;
298+ module_consts_cfg_attrs. push ( get_cfg_attributes ( & item. attrs ) ) ;
295299 }
296300 Item :: Static ( item) => {
297301 ensure_spanned ! (
298302 !has_attribute( & item. attrs, "pymodule_export" ) ,
299- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
303+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
300304 ) ;
301305 }
302306 Item :: Macro ( item) => {
303307 ensure_spanned ! (
304308 !has_attribute( & item. attrs, "pymodule_export" ) ,
305- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
309+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
306310 ) ;
307311 }
308312 Item :: ExternCrate ( item) => {
309313 ensure_spanned ! (
310314 !has_attribute( & item. attrs, "pymodule_export" ) ,
311- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
315+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
312316 ) ;
313317 }
314318 Item :: Impl ( item) => {
315319 ensure_spanned ! (
316320 !has_attribute( & item. attrs, "pymodule_export" ) ,
317- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
321+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
318322 ) ;
319323 }
320324 Item :: TraitAlias ( item) => {
321325 ensure_spanned ! (
322326 !has_attribute( & item. attrs, "pymodule_export" ) ,
323- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
327+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
324328 ) ;
325329 }
326330 Item :: Type ( item) => {
327331 ensure_spanned ! (
328332 !has_attribute( & item. attrs, "pymodule_export" ) ,
329- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
333+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
330334 ) ;
331335 }
332336 Item :: Union ( item) => {
333337 ensure_spanned ! (
334338 !has_attribute( & item. attrs, "pymodule_export" ) ,
335- item. span( ) => "`#[pymodule_export]` may only be used on `use` statements"
339+ item. span( ) => "`#[pymodule_export]` may only be used on `use` or `const` statements"
336340 ) ;
337341 }
338342 _ => ( ) ,
@@ -372,6 +376,8 @@ pub fn pymodule_module_impl(
372376 options. gil_used . map_or ( true , |op| op. value . value ) ,
373377 ) ;
374378
379+ let module_consts_names = module_consts. iter ( ) . map ( |i| i. unraw ( ) . to_string ( ) ) ;
380+
375381 Ok ( quote ! (
376382 #( #attrs) *
377383 #vis #mod_token #ident {
@@ -387,6 +393,12 @@ pub fn pymodule_module_impl(
387393 #( #module_items_cfg_attrs) *
388394 #module_items:: _PYO3_DEF. add_to_module( module) ?;
389395 ) *
396+
397+ #(
398+ #( #module_consts_cfg_attrs) *
399+ #pyo3_path:: types:: PyModuleMethods :: add( module, #module_consts_names, #module_consts) ?;
400+ ) *
401+
390402 #pymodule_init
391403 :: std:: result:: Result :: Ok ( ( ) )
392404 }
0 commit comments