bugfix
using python identifier in message names necessary to distinguish between dynamically created classes with same name
This commit is contained in:
parent
fd02cb6180
commit
8f535913a1
@ -20,7 +20,8 @@ pub fn create_cached_descriptor(obj: &PyAny) -> Result<MessageDescriptor> {
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
let name = obj.qualified_class_name()?;
|
||||
let cls = obj.getattr("__class__")?;
|
||||
let name = format!("{}_{}", cls.qualified_name()?, cls.py_identifier());
|
||||
if let Some(desc) = pool.get_message_by_name(&name) {
|
||||
return Ok(desc);
|
||||
}
|
||||
@ -159,6 +160,7 @@ fn add_message_to_file(
|
||||
Some("google.protobuf.Duration".to_string());
|
||||
}
|
||||
_ => {
|
||||
let cls_name = format!("{}_{}", cls_name, cls.py_identifier());
|
||||
field.type_name = Some(cls_name.clone());
|
||||
|
||||
if message_name != cls_name
|
||||
@ -179,14 +181,14 @@ fn add_message_to_file(
|
||||
},
|
||||
Type::Enum => {
|
||||
let cls = meta.get_class(field_name)?;
|
||||
let cls_name = cls.qualified_name()?;
|
||||
let cls_name = format!("{}_{}", cls.qualified_name()?, cls.py_identifier());
|
||||
field.type_name = Some(cls_name.to_string());
|
||||
|
||||
if pool.get_enum_by_name(&cls_name).is_none()
|
||||
&& !file.enum_type.iter().any(|item| item.name() == cls_name)
|
||||
{
|
||||
let mut proto = EnumDescriptorProto {
|
||||
name: Some(cls_name),
|
||||
name: Some(cls_name.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@ -194,7 +196,7 @@ fn add_message_to_file(
|
||||
let item = item?;
|
||||
proto.value.push(EnumValueDescriptorProto {
|
||||
number: Some(item.getattr("value")?.extract()?),
|
||||
name: Some(item.getattr("name")?.extract()?),
|
||||
name: Some(format!("{}_{}", cls_name, item.getattr("name")?.extract::<&str>()?)),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::error::Result;
|
||||
use pyo3::PyAny;
|
||||
use pyo3::{PyAny, Py, sync::GILOnceCell};
|
||||
|
||||
pub trait PyAnyExtras {
|
||||
fn qualified_name(&self) -> Result<String>;
|
||||
@ -9,6 +9,7 @@ pub trait PyAnyExtras {
|
||||
fn create_instance(&self, field_name: &str) -> Result<&PyAny>;
|
||||
fn is_list_field(&self, field_name: &str) -> Result<bool>;
|
||||
fn oneof_group(&self, field_name: &str) -> Result<Option<String>>;
|
||||
fn py_identifier(&self) -> u64;
|
||||
}
|
||||
|
||||
impl PyAnyExtras for PyAny {
|
||||
@ -49,4 +50,19 @@ impl PyAnyExtras for PyAny {
|
||||
.extract()?;
|
||||
Ok(opt)
|
||||
}
|
||||
|
||||
fn py_identifier(&self) -> u64 {
|
||||
static FUN_CACHE: GILOnceCell<Py<PyAny>> = GILOnceCell::new();
|
||||
let py = self.py();
|
||||
let fun = FUN_CACHE.get_or_init(py, || {
|
||||
let fun = py
|
||||
.eval("id", None, None)
|
||||
.expect("This is a valid Python expression");
|
||||
Py::from(fun)
|
||||
});
|
||||
fun.call1(py, (self,))
|
||||
.expect("Identity function is callable")
|
||||
.extract::<u64>(py)
|
||||
.expect("Identity function always returns an integer")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user