This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new c5bb74fda chore(python): handle duplicate field names (#3384)
c5bb74fda is described below
commit c5bb74fda96730b1671a0deea456918b16cd8c05
Author: Eyad Hazem <[email protected]>
AuthorDate: Sat Feb 28 19:01:36 2026 +0200
chore(python): handle duplicate field names (#3384)
## Why?
This PR handles the duplicate of field names for inheritance.
## What does this PR do?
The handling is done by making every child class's field override its
parent's till the most-derived field kept.
- First, we iterate over the full class MRO (cls.__mro__) to extract
field metadata from all parent classes.
- Then, deduplicate fields so that each field name appears only once in
the resulting list with keeping the child class definition if a field is
shadowed.
- Finally, added some tests to cover:
- Single-level inheritance
- Multi-level inheritance
- Field shadowing in child and grandchild classes
- Deduplication of overridden fields
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
---
python/pyfory/meta/typedef_encoder.py | 7 ---
python/pyfory/tests/test_duplicate_field_names.py | 55 +++++++++++++++++++++++
2 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/python/pyfory/meta/typedef_encoder.py
b/python/pyfory/meta/typedef_encoder.py
index 5e0824c50..d93996c6c 100644
--- a/python/pyfory/meta/typedef_encoder.py
+++ b/python/pyfory/meta/typedef_encoder.py
@@ -15,7 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-from collections import Counter
from pyfory.meta.typedef import (
FieldInfo,
@@ -61,12 +60,6 @@ def encode_typedef(type_resolver, cls, include_fields: bool
= True):
"""
if include_fields:
field_infos = build_field_infos(type_resolver, cls)
- # Check for duplicate field names
- field_names = [field_info.name for field_info in field_infos]
- duplicate_field_names = [name for name, count in
Counter(field_names).items() if count > 1]
- if duplicate_field_names:
- # TODO: handle duplicate field names for inheritance in future
- raise ValueError(f"Duplicate field names: {duplicate_field_names}")
else:
field_infos = []
diff --git a/python/pyfory/tests/test_duplicate_field_names.py
b/python/pyfory/tests/test_duplicate_field_names.py
new file mode 100644
index 000000000..26603603a
--- /dev/null
+++ b/python/pyfory/tests/test_duplicate_field_names.py
@@ -0,0 +1,55 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Tests for field shadowing in inheritance.
+"""
+
+from dataclasses import dataclass
+from pyfory import Fory
+from pyfory.meta.typedef_encoder import encode_typedef
+
+
+@dataclass
+class Parent:
+ name: str
+ value: int
+
+
+@dataclass
+class ChildWithShadow(Parent):
+ name: str # Shadows Parent.name
+ extra: float
+
+
+def test_shadowed_fields_serialization():
+ """Serialization with shadowed and inherited fields."""
+ fory = Fory(xlang=True)
+ fory.register(Parent, namespace="test", typename="Parent")
+ fory.register(ChildWithShadow, namespace="test",
typename="ChildWithShadow")
+
+ # Verify TypeDef has exactly 3 fields (no duplicate 'name')
+ typedef = encode_typedef(fory.type_resolver, ChildWithShadow)
+ assert len(typedef.fields) == 3
+
+ obj = ChildWithShadow(name="shadowed", value=10, extra=3.14)
+ data = fory.serialize(obj)
+ result = fory.deserialize(data)
+
+ assert result.name == "shadowed"
+ assert result.value == 10 # inherited field
+ assert result.extra == 3.14
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]