summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py124
1 files changed, 104 insertions, 20 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py
index 7e98f7c46f..18dca4743a 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py
+++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py
@@ -1,14 +1,33 @@
{%- let obj = ci|get_object_definition(name) %}
-
-class {{ type_name }}:
+{%- let (protocol_name, impl_name) = obj|object_names %}
+{%- let methods = obj.methods() %}
+{%- let protocol_docstring = obj.docstring() %}
+
+{% include "Protocol.py" %}
+
+{% if ci.is_name_used_as_error(name) %}
+class {{ impl_name }}(Exception):
+{%- else %}
+class {{ impl_name }}:
+{%- endif %}
+ {%- call py::docstring(obj, 4) %}
_pointer: ctypes.c_void_p
{%- match obj.primary_constructor() %}
{%- when Some with (cons) %}
+{%- if cons.is_async() %}
+ def __init__(self, *args, **kw):
+ raise ValueError("async constructors not supported.")
+{%- else %}
def __init__(self, {% call py::arg_list_decl(cons) -%}):
+ {%- call py::docstring(cons, 8) %}
{%- call py::setup_args_extra_indent(cons) %}
self._pointer = {% call py::to_ffi_call(cons) %}
+{%- endif %}
{%- when None %}
+ {# no __init__ means simple construction without a pointer works, which can confuse #}
+ def __init__(self, *args, **kwargs):
+ raise ValueError("This class has no default constructor")
{%- endmatch %}
def __del__(self):
@@ -17,6 +36,9 @@ class {{ type_name }}:
if pointer is not None:
_rust_call(_UniffiLib.{{ obj.ffi_object_free().name() }}, pointer)
+ def _uniffi_clone_pointer(self):
+ return _rust_call(_UniffiLib.{{ obj.ffi_object_clone().name() }}, self._pointer)
+
# Used by alternative constructors or any methods which return this type.
@classmethod
def _make_instance_(cls, pointer):
@@ -29,17 +51,32 @@ class {{ type_name }}:
{%- for cons in obj.alternate_constructors() %}
@classmethod
+{%- if cons.is_async() %}
+ async def {{ cons.name()|fn_name }}(cls, {% call py::arg_list_decl(cons) %}):
+ {%- call py::docstring(cons, 8) %}
+ {%- call py::setup_args_extra_indent(cons) %}
+
+ return await _uniffi_rust_call_async(
+ _UniffiLib.{{ cons.ffi_func().name() }}({% call py::arg_list_lowered(cons) %}),
+ _UniffiLib.{{ cons.ffi_rust_future_poll(ci) }},
+ _UniffiLib.{{ cons.ffi_rust_future_complete(ci) }},
+ _UniffiLib.{{ cons.ffi_rust_future_free(ci) }},
+ {{ ffi_converter_name }}.lift,
+ {% call py::error_ffi_converter(cons) %}
+ )
+{%- else %}
def {{ cons.name()|fn_name }}(cls, {% call py::arg_list_decl(cons) %}):
+ {%- call py::docstring(cons, 8) %}
{%- call py::setup_args_extra_indent(cons) %}
# Call the (fallible) function before creating any half-baked object instances.
pointer = {% call py::to_ffi_call(cons) %}
return cls._make_instance_(pointer)
+{%- endif %}
{% endfor %}
{%- for meth in obj.methods() -%}
{%- call py::method_decl(meth.name()|fn_name, meth) %}
-{% endfor %}
-
+{%- endfor %}
{%- for tm in obj.uniffi_traits() -%}
{%- match tm %}
{%- when UniffiTrait::Debug { fmt } %}
@@ -51,37 +88,84 @@ class {{ type_name }}:
if not isinstance(other, {{ type_name }}):
return NotImplemented
- return {{ eq.return_type().unwrap()|lift_fn }}({% call py::to_ffi_call_with_prefix("self._pointer", eq) %})
+ return {{ eq.return_type().unwrap()|lift_fn }}({% call py::to_ffi_call_with_prefix("self._uniffi_clone_pointer()", eq) %})
def __ne__(self, other: object) -> {{ ne.return_type().unwrap()|type_name }}:
if not isinstance(other, {{ type_name }}):
return NotImplemented
- return {{ ne.return_type().unwrap()|lift_fn }}({% call py::to_ffi_call_with_prefix("self._pointer", ne) %})
+ return {{ ne.return_type().unwrap()|lift_fn }}({% call py::to_ffi_call_with_prefix("self._uniffi_clone_pointer()", ne) %})
{%- when UniffiTrait::Hash { hash } %}
{%- call py::method_decl("__hash__", hash) %}
-{% endmatch %}
-{% endfor %}
-
-
-class {{ ffi_converter_name }}:
+{%- endmatch %}
+{%- endfor %}
+
+{%- if obj.has_callback_interface() %}
+{%- let ffi_init_callback = obj.ffi_init_callback() %}
+{%- let vtable = obj.vtable().expect("trait interface should have a vtable") %}
+{%- let vtable_methods = obj.vtable_methods() %}
+{% include "CallbackInterfaceImpl.py" %}
+{%- endif %}
+
+{# Objects as error #}
+{%- if ci.is_name_used_as_error(name) %}
+{# Due to some mismatches in the ffi converter mechanisms, errors are forced to be a RustBuffer #}
+class {{ ffi_converter_name }}__as_error(_UniffiConverterRustBuffer):
@classmethod
def read(cls, buf):
- ptr = buf.read_u64()
- if ptr == 0:
- raise InternalError("Raw pointer value was null")
- return cls.lift(ptr)
+ raise NotImplementedError()
@classmethod
def write(cls, value, buf):
- if not isinstance(value, {{ type_name }}):
- raise TypeError("Expected {{ type_name }} instance, {} found".format(type(value).__name__))
- buf.write_u64(cls.lower(value))
+ raise NotImplementedError()
@staticmethod
def lift(value):
- return {{ type_name }}._make_instance_(value)
+ # Errors are always a rust buffer holding a pointer - which is a "read"
+ with value.consume_with_stream() as stream:
+ return {{ ffi_converter_name }}.read(stream)
@staticmethod
def lower(value):
- return value._pointer
+ raise NotImplementedError()
+
+{%- endif %}
+
+class {{ ffi_converter_name }}:
+ {%- if obj.has_callback_interface() %}
+ _handle_map = _UniffiHandleMap()
+ {%- endif %}
+
+ @staticmethod
+ def lift(value: int):
+ return {{ impl_name }}._make_instance_(value)
+
+ @staticmethod
+ def check_lower(value: {{ type_name }}):
+ {%- if obj.has_callback_interface() %}
+ pass
+ {%- else %}
+ if not isinstance(value, {{ impl_name }}):
+ raise TypeError("Expected {{ impl_name }} instance, {} found".format(type(value).__name__))
+ {%- endif %}
+
+ @staticmethod
+ def lower(value: {{ protocol_name }}):
+ {%- if obj.has_callback_interface() %}
+ return {{ ffi_converter_name }}._handle_map.insert(value)
+ {%- else %}
+ if not isinstance(value, {{ impl_name }}):
+ raise TypeError("Expected {{ impl_name }} instance, {} found".format(type(value).__name__))
+ return value._uniffi_clone_pointer()
+ {%- endif %}
+
+ @classmethod
+ def read(cls, buf: _UniffiRustBuffer):
+ ptr = buf.read_u64()
+ if ptr == 0:
+ raise InternalError("Raw pointer value was null")
+ return cls.lift(ptr)
+
+ @classmethod
+ def write(cls, value: {{ protocol_name }}, buf: _UniffiRustBuffer):
+ buf.write_u64(cls.lower(value))