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()
|
.lock()
|
||||||
.unwrap();
|
.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) {
|
if let Some(desc) = pool.get_message_by_name(&name) {
|
||||||
return Ok(desc);
|
return Ok(desc);
|
||||||
}
|
}
|
||||||
@ -159,6 +160,7 @@ fn add_message_to_file(
|
|||||||
Some("google.protobuf.Duration".to_string());
|
Some("google.protobuf.Duration".to_string());
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
let cls_name = format!("{}_{}", cls_name, cls.py_identifier());
|
||||||
field.type_name = Some(cls_name.clone());
|
field.type_name = Some(cls_name.clone());
|
||||||
|
|
||||||
if message_name != cls_name
|
if message_name != cls_name
|
||||||
@ -179,14 +181,14 @@ fn add_message_to_file(
|
|||||||
},
|
},
|
||||||
Type::Enum => {
|
Type::Enum => {
|
||||||
let cls = meta.get_class(field_name)?;
|
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());
|
field.type_name = Some(cls_name.to_string());
|
||||||
|
|
||||||
if pool.get_enum_by_name(&cls_name).is_none()
|
if pool.get_enum_by_name(&cls_name).is_none()
|
||||||
&& !file.enum_type.iter().any(|item| item.name() == cls_name)
|
&& !file.enum_type.iter().any(|item| item.name() == cls_name)
|
||||||
{
|
{
|
||||||
let mut proto = EnumDescriptorProto {
|
let mut proto = EnumDescriptorProto {
|
||||||
name: Some(cls_name),
|
name: Some(cls_name.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,7 +196,7 @@ fn add_message_to_file(
|
|||||||
let item = item?;
|
let item = item?;
|
||||||
proto.value.push(EnumValueDescriptorProto {
|
proto.value.push(EnumValueDescriptorProto {
|
||||||
number: Some(item.getattr("value")?.extract()?),
|
number: Some(item.getattr("value")?.extract()?),
|
||||||
name: Some(item.getattr("name")?.extract()?),
|
name: Some(format!("{}_{}", cls_name, item.getattr("name")?.extract::<&str>()?)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use pyo3::PyAny;
|
use pyo3::{PyAny, Py, sync::GILOnceCell};
|
||||||
|
|
||||||
pub trait PyAnyExtras {
|
pub trait PyAnyExtras {
|
||||||
fn qualified_name(&self) -> Result<String>;
|
fn qualified_name(&self) -> Result<String>;
|
||||||
@ -9,6 +9,7 @@ pub trait PyAnyExtras {
|
|||||||
fn create_instance(&self, field_name: &str) -> Result<&PyAny>;
|
fn create_instance(&self, field_name: &str) -> Result<&PyAny>;
|
||||||
fn is_list_field(&self, field_name: &str) -> Result<bool>;
|
fn is_list_field(&self, field_name: &str) -> Result<bool>;
|
||||||
fn oneof_group(&self, field_name: &str) -> Result<Option<String>>;
|
fn oneof_group(&self, field_name: &str) -> Result<Option<String>>;
|
||||||
|
fn py_identifier(&self) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PyAnyExtras for PyAny {
|
impl PyAnyExtras for PyAny {
|
||||||
@ -49,4 +50,19 @@ impl PyAnyExtras for PyAny {
|
|||||||
.extract()?;
|
.extract()?;
|
||||||
Ok(opt)
|
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