# Code generated by ndpgen. DO NOT EDIT. # # This file contains client wrappers for the {{.Service.Name}} host service. # It is intended for use in Navidrome plugins built with extism-py. # # IMPORTANT: Due to a limitation in extism-py, you cannot import this file directly. # The @extism.import_fn decorators are only detected when defined in the plugin's # main __init__.py file. Copy the needed functions from this file into your plugin. from dataclasses import dataclass from typing import Any{{- if .Service.HasRawMethods}}, Tuple{{end}} import extism import json {{- if .Service.HasRawMethods}} import struct {{- end}} class HostFunctionError(Exception): """Raised when a host function returns an error.""" pass {{- /* Generate raw host function imports */ -}} {{range .Service.Methods}} @extism.import_fn("extism:host/user", "{{exportName .}}") def _{{exportName .}}(offset: int) -> int: """Raw host function - do not call directly.""" ... {{- end}} {{- /* Generate dataclasses for multi-value returns */ -}} {{range .Service.Methods}} {{- if and .NeedsResultClass (not .Raw)}} @dataclass class {{pythonResultType .}}: """Result type for {{pythonFunc .}}.""" {{- range .Returns}} {{.PythonName}}: {{.PythonType}} {{- end}} {{- end}} {{- end}} {{- /* Generate wrapper functions */ -}} {{range .Service.Methods}} def {{pythonFunc .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.PythonName}}: {{$p.PythonType}}{{end}}){{if .Raw}} -> Tuple[str, bytes]{{else if .NeedsResultClass}} -> {{pythonResultType .}}{{else if .HasReturns}} -> {{(index .Returns 0).PythonType}}{{else}} -> None{{end}}: """{{if .Doc}}{{.Doc}}{{else}}Call the {{exportName .}} host function.{{end}} {{- if .HasParams}} Args: {{- range .Params}} {{.PythonName}}: {{.PythonType}} parameter. {{- end}} {{- end}} {{- if .Raw}} Returns: Tuple of (content_type, data) with the raw binary response. {{- else if .HasReturns}} Returns: {{- if .NeedsResultClass}} {{pythonResultType .}} containing{{range .Returns}} {{.PythonName}},{{end}}. {{- else}} {{(index .Returns 0).PythonType}}: The result value. {{- end}} {{- end}} Raises: HostFunctionError: If the host function returns an error. """ {{- if .HasParams}} request = { {{- range .Params}} "{{.JSONName}}": {{.PythonName}}, {{- end}} } request_bytes = json.dumps(request).encode("utf-8") {{- else}} request_bytes = b"{}" {{- end}} request_mem = extism.memory.alloc(request_bytes) response_offset = _{{exportName .}}(request_mem.offset) response_mem = extism.memory.find(response_offset) {{- if .Raw}} response_bytes = response_mem.bytes() if len(response_bytes) == 0: raise HostFunctionError("empty response from host") if response_bytes[0] == 0x01: raise HostFunctionError(response_bytes[1:].decode("utf-8")) if response_bytes[0] != 0x00: raise HostFunctionError("unknown response status") if len(response_bytes) < 5: raise HostFunctionError("malformed raw response: incomplete header") ct_len = struct.unpack(">I", response_bytes[1:5])[0] if len(response_bytes) < 5 + ct_len: raise HostFunctionError("malformed raw response: content-type overflow") content_type = response_bytes[5:5 + ct_len].decode("utf-8") data = response_bytes[5 + ct_len:] return content_type, data {{- else}} response = json.loads(extism.memory.string(response_mem)) {{if .HasError}} if response.get("error"): raise HostFunctionError(response["error"]) {{end}} {{- if .NeedsResultClass}} return {{pythonResultType .}}( {{- range .Returns}} {{.PythonName}}=response.get("{{.JSONName}}"{{pythonDefault .}}), {{- end}} ) {{- else if .HasReturns}} return response.get("{{(index .Returns 0).JSONName}}"{{pythonDefault (index .Returns 0)}}) {{- end}} {{- end}} {{- end}}