gemini-code-assist[bot] commented on code in PR #663:
URL: https://github.com/apache/tvm-ffi/pull/663#discussion_r3574212180


##########
python/tvm_ffi/_dunder.py:
##########
@@ -104,6 +114,22 @@ def __init__(self: Any, *args: Any, **kwargs: Any) -> None:
     return __init__
 
 
+def _collect_init_property_funcs(type_cls: type) -> list[tuple[str, 
Callable[..., Any]]]:
+    """Collect ``(name, func)`` pairs for all ``init_property`` fields in MRO 
order.
+
+    Walks from the most specific class toward the root.  Child definitions take
+    precedence over parent definitions of the same name (first-seen wins).
+    """
+    funcs: list[tuple[str, Callable[..., Any]]] = []
+    seen: set[str] = set()
+    for cls in type_cls.__mro__:
+        for name, func in cls.__dict__.get("__ffi_init_property_funcs__", 
{}).items():
+            if name not in seen:
+                funcs.append((name, func))
+                seen.add(name)
+    return funcs

Review Comment:
   ![high](https://www.gstatic.com/codereviewagent/high-priority.svg)
   
   In `_collect_init_property_funcs`, walking the MRO from child to parent 
(most specific to least specific) means child properties are evaluated before 
parent properties. If a child's `init_property` depends on a parent's 
`init_property` (or parent fields), it will be evaluated with 
uninitialized/default values. Walking the MRO in reverse (from root to child) 
using a dictionary ensures parent properties are evaluated first, while still 
allowing child definitions to correctly override parent definitions of the same 
name.
   
   ```python
   def _collect_init_property_funcs(type_cls: type) -> list[tuple[str, 
Callable[..., Any]]]:
       """Collect (name, func) pairs for all init_property fields in MRO order.
   
       Walks from the root toward the most specific class so that parent 
properties
       are evaluated before child properties (allowing dependent properties to 
work).
       Child definitions override parent definitions of the same name.
       """
       funcs_dict: dict[str, Callable[..., Any]] = {}
       for cls in reversed(type_cls.__mro__):
           for name, func in cls.__dict__.get("__ffi_init_property_funcs__", 
{}).items():
               funcs_dict[name] = func
       return list(funcs_dict.items())
   ```



##########
python/tvm_ffi/utils/descriptors.py:
##########
@@ -0,0 +1,61 @@
+# 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.
+"""Descriptor utilities for the tvm_ffi Python package."""
+
+from __future__ import annotations
+
+from typing import Any, Callable, Generic, TypeVar, overload
+
+_T = TypeVar("_T")
+
+
+class init_property(Generic[_T]):
+    """Auto-registered C++ field with eager computation at ``__init__`` time.
+
+    ``@py_class`` detects ``init_property`` descriptors and registers each one
+    as ``field(init=False, structural_eq="ignore")``, so the computed value
+    lives in C++ object storage and is accessible cross-language.  The value
+    is computed once — immediately after ``__ffi_init__`` — and stored via the
+    field's C++ slot.  Subsequent reads go directly to C++ memory.
+
+    The return annotation of the decorated function is injected into the class
+    ``__annotations__`` during class body execution so the field resolution
+    machinery picks it up automatically.  If no return annotation is present,
+    ``typing.Any`` is used.
+    """
+
+    def __init__(self, func: Callable[[Any], _T]) -> None:
+        self.func = func
+        self.name: str | None = None
+        self._return_annotation: Any = func.__annotations__.get("return")
+
+    @overload
+    def __get__(self, obj: None, objtype: type) -> init_property[_T]: ...
+    @overload
+    def __get__(self, obj: object, objtype: type) -> _T: ...
+    def __get__(self, obj: object | None, objtype: type) -> _T | 
init_property[_T]:
+        return self
+
+    def __set_name__(self, owner: type, name: str) -> None:
+        self.name = name
+
+        ann = self._return_annotation if self._return_annotation is not None 
else Any
+        # Inject into the owner's own __annotations__ so on_fields_resolved
+        # processes this name as a typed field.
+        if "__annotations__" not in owner.__dict__:
+            owner.__annotations__ = {}
+        owner.__annotations__[name] = ann

Review Comment:
   ![high](https://www.gstatic.com/codereviewagent/high-priority.svg)
   
   In Python 3.14+ (PEP 749), `__annotations__` is a descriptor on the class 
that lazily evaluates annotations via `__annotate__`. Assigning 
`owner.__annotations__ = {}` replaces this descriptor with a plain dictionary, 
which completely shadows and loses any other annotations declared on the class. 
Since `__annotations__` is no longer inherited in Python 3.14+, we can safely 
mutate the dictionary returned by `owner.__annotations__` directly without 
affecting parent classes, preserving other annotations.
   
   ```suggestion
           import sys
   
           ann = self._return_annotation if self._return_annotation is not None 
else Any
           # Inject into the owner's own __annotations__ so on_fields_resolved
           # processes this name as a typed field.
           if sys.version_info >= (3, 14):
               owner.__annotations__[name] = ann
           else:
               if "__annotations__" not in owner.__dict__:
                   owner.__annotations__ = {}
               owner.__annotations__[name] = ann
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to