Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow create_exception! to take expr or literal as module name instead of only ident #2946

Closed
BlueGlassBlock opened this issue Feb 12, 2023 · 1 comment · Fixed by #2979
Closed

Comments

@BlueGlassBlock
Copy link
Contributor

I'm trying to build a Python-Rust mixed project. I want to place all the Rust based types into my_module.core, however, create_exception! only allows me to place the exception at the root of the module. (I don't mind adding exception to module attribute, however replicating create_exception! manually is quite cumbersome.)

I hope that the create_exception! macro can accept a expr / literal as the module name, so that a normal dotted module name can be accepted.

Patch

diff --git a/src/exceptions.rs b/src/exceptions.rs
index 1e2572d1..622ee180 100644
--- a/src/exceptions.rs
+++ b/src/exceptions.rs
@@ -201,7 +201,7 @@ macro_rules! import_exception {
 ///
 #[macro_export]
 macro_rules! create_exception {
-    ($module: ident, $name: ident, $base: ty) => {
+    ($module: expr, $name: ident, $base: ty) => {
         #[repr(transparent)]
         #[allow(non_camel_case_types)] // E.g. `socket.herror`
         pub struct $name($crate::PyAny);
@@ -210,7 +210,7 @@ macro_rules! create_exception {

         $crate::create_exception_type_object!($module, $name, $base, ::std::option::Option::None);
     };
-    ($module: ident, $name: ident, $base: ty, $doc: expr) => {
+    ($module: expr, $name: ident, $base: ty, $doc: expr) => {
         #[repr(transparent)]
         #[allow(non_camel_case_types)] // E.g. `socket.herror`
         #[doc = $doc]
@@ -232,7 +232,7 @@ macro_rules! create_exception {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! create_exception_type_object {
-    ($module: ident, $name: ident, $base: ty, $doc: expr) => {
+    ($module: expr, $name: ident, $base: ty, $doc: expr) => {
         $crate::pyobject_native_type_core!(
             $name,
             *$name::type_object_raw($crate::Python::assume_gil_acquired()),
@@ -876,6 +876,21 @@ mod tests {
         });
     }

+    #[test]
+    fn custom_exception_dotted_module() {
+        create_exception!(mymodule.exceptions, CustomError, PyException);
+        Python::with_gil(|py| {
+            let error_type = py.get_type::<CustomError>();
+            let ctx = [("CustomError", error_type)].into_py_dict(py);
+            let type_description: String = py
+                .eval("str(CustomError)", None, Some(ctx))
+                .unwrap()
+                .extract()
+                .unwrap();
+            assert_eq!(type_description, "<class 'mymodule.exceptions.CustomError'>");
+        });
+    }
+
     #[test]
     fn custom_exception_doc() {
         create_exception!(mymodule, CustomError, PyException, "Some docs");
@davidhewitt
Copy link
Member

Seems very reasonable, I've pushed this as #2979.

@bors bors bot closed this as completed in 7cffc92 Feb 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants