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


##########
python/tvm_ffi/cython/object.pxi:
##########
@@ -261,29 +263,54 @@ cdef inline object make_ret_opaque_object(TVMFFIAny 
result):
     (<Object>obj).chandle = result.v_obj
     return obj.pyobject()
 
+cdef inline object make_fallback_cls_for_type_index(int32_t type_index):
+    cdef str type_key = _type_index_to_key(type_index)
+    cdef object type_info = _lookup_type_info_from_type_key(type_key)
+    cdef object parent_type_info = type_info.parent_type_info
+
+    class cls(parent_type_info.type_cls):
+        pass

Review Comment:
   ![critical](https://www.gstatic.com/codereviewagent/critical.svg)
   
   If an object of a derived type is returned, but neither the derived type nor 
its base type are registered on the Python side, `parent_type_info.type_cls` 
will be `None`. This will cause a `TypeError` when attempting to use it as a 
base class at line 271. A recursive call to `make_fallback_cls_for_type_index` 
for the parent type is needed to ensure the parent class is created first.
   
   ```
       cdef object parent_type_info = type_info.parent_type_info
   
       if parent_type_info.type_cls is None:
           make_fallback_cls_for_type_index(parent_type_info.type_index)
   
       class cls(parent_type_info.type_cls):
           pass
   ```



##########
python/tvm_ffi/cython/type_info.pxi:
##########
@@ -101,6 +102,21 @@ class TypeMethod:
     func: object
     is_static: bool
 
+    def as_callable(self, object cls):
+        """Create a Python method attribute for this method on ``cls``."""
+        cdef str name = self.name
+        cdef str doc = self.doc or f"Method `{name}` of class 
`{cls.__qualname__}`"
+        cdef object func = self.func
+        if self.is_static:
+            func = staticmethod(func)
+        else:
+            func = _member_method_wrapper(func)
+        func.__module__ = cls.__module__
+        func.__name__ = name
+        func.__qualname__ = f"{cls.__qualname__}.{name}"
+        func.__doc__ = doc
+        return func

Review Comment:
   ![critical](https://www.gstatic.com/codereviewagent/critical.svg)
   
   Setting attributes like `__doc__` on a `staticmethod` object will raise an 
`AttributeError` at runtime. These attributes should be set on the function 
object *before* it's wrapped by `staticmethod`. For non-static methods, the 
attributes should be set on the wrapper function. The suggested change 
refactors the logic to correctly handle both cases.
   
   ```
           cdef object func
           if self.is_static:
               func = self.func
           else:
               func = _member_method_wrapper(self.func)
   
           func.__module__ = cls.__module__
           func.__name__ = name
           func.__qualname__ = f"{cls.__qualname__}.{name}"
           func.__doc__ = doc
   
           if self.is_static:
               return staticmethod(func)
           return func
   ```



##########
python/tvm_ffi/cython/object.pxi:
##########
@@ -261,29 +263,54 @@ cdef inline object make_ret_opaque_object(TVMFFIAny 
result):
     (<Object>obj).chandle = result.v_obj
     return obj.pyobject()
 
+cdef inline object make_fallback_cls_for_type_index(int32_t type_index):
+    cdef str type_key = _type_index_to_key(type_index)
+    cdef object type_info = _lookup_type_info_from_type_key(type_key)
+    cdef object parent_type_info = type_info.parent_type_info
+
+    class cls(parent_type_info.type_cls):
+        pass
+
+    assert type_info.type_cls is None
+    assert parent_type_info is not None
+
+    attrs = dict(cls.__dict__)
+    attrs.pop("__dict__", None)
+    attrs.pop("__weakref__", None)
+    attrs["__slots__"] = ()
+    attrs["__tvm_ffi_type_info__"] = type_info
+    for field in type_info.fields:
+        attrs[field.name] = field.as_property(cls)
+    for method in type_info.methods:
+        name = method.name
+        if name == "__ffi_init__":
+            name = "__c_ffi_init__"
+        attrs[name] = method.as_callable(cls)
+    for name, val in attrs.items():
+        setattr(cls, name, val)
+    type_info.type_cls = cls
+    _update_registry(type_index, type_key, type_info, cls)
+    return cls
+
 
 cdef inline object make_ret_object(TVMFFIAny result):
-    global TYPE_INDEX_TO_INFO
-    cdef int32_t tindex
-    cdef object cls
-    tindex = result.type_index
-
-    if tindex < len(TYPE_INDEX_TO_CLS):
-        cls = TYPE_INDEX_TO_CLS[tindex]
-        if cls is not None:
-            if issubclass(cls, PyNativeObject):
-                obj = Object.__new__(Object)
-                (<Object>obj).chandle = result.v_obj
-                return cls.__from_tvm_ffi_object__(cls, obj)
-            obj = cls.__new__(cls)
-            (<Object>obj).chandle = result.v_obj
-            return obj
+    cdef int32_t type_index
+    cdef object cls, obj
+    type_index = result.type_index
 
-    # object is not found in registered entry
-    # in this case we need to report an warning
-    type_key = _type_index_to_key(tindex)
-    warnings.warn(f"Returning type `{type_key}` which is not registered via 
register_object, fallback to Object")
-    obj = _CLASS_OBJECT.__new__(_CLASS_OBJECT)
+    if type_index < len(TYPE_INDEX_TO_CLS) and (cls := 
TYPE_INDEX_TO_CLS[type_index]) is not None:
+        if issubclass(cls, PyNativeObject):
+            obj = Object.__new__(Object)
+            (<Object>obj).chandle = result.v_obj
+            return cls.__from_tvm_ffi_object__(cls, obj)
+        else:
+            pass

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   The `else: pass` block is redundant and can be removed to improve code 
clarity. The logic will correctly fall through to the object creation for 
non-`PyNativeObject` types.



-- 
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