From 2bfda22532cd4eca78338c6ee876f91d4cdeb1f0 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Sun, 1 Feb 2026 12:41:26 -0500 Subject: [PATCH] Make av/descriptor pure --- av/descriptor.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++ av/descriptor.pyx | 59 ------------------------------------- 2 files changed, 75 insertions(+), 59 deletions(-) create mode 100644 av/descriptor.py delete mode 100644 av/descriptor.pyx diff --git a/av/descriptor.py b/av/descriptor.py new file mode 100644 index 000000000..20cd1a787 --- /dev/null +++ b/av/descriptor.py @@ -0,0 +1,75 @@ +import cython +import cython.cimports.libav as lib +from cython.cimports.av.option import ( + Option, + OptionChoice, + wrap_option, + wrap_option_choice, +) + +_cinit_sentinel = cython.declare(object, object()) + + +@cython.cfunc +def wrap_avclass(ptr: cython.pointer[cython.const[lib.AVClass]]) -> Descriptor | None: + if ptr == cython.NULL: + return None + obj: Descriptor = Descriptor(_cinit_sentinel) + obj.ptr = ptr + return obj + + +@cython.cclass +class Descriptor: + def __cinit__(self, sentinel): + if sentinel is not _cinit_sentinel: + raise RuntimeError("Cannot construct av.Descriptor") + + @property + def name(self): + return self.ptr.class_name if self.ptr.class_name else None + + @property + def options(self): + ptr: cython.pointer[cython.const[lib.AVOption]] = self.ptr.option + choice_ptr: cython.pointer[cython.const[lib.AVOption]] + option: Option + option_choice: OptionChoice + choice_is_default: cython.bint + if self._options is None: + options: list = [] + ptr = self.ptr.option + while ptr != cython.NULL and ptr.name != cython.NULL: + if ptr.type == lib.AV_OPT_TYPE_CONST: + ptr += 1 + continue + choices: list = [] + if ( + ptr.unit != cython.NULL + ): # option has choices (matching const options) + choice_ptr = self.ptr.option + while choice_ptr != cython.NULL and choice_ptr.name != cython.NULL: + if ( + choice_ptr.type != lib.AV_OPT_TYPE_CONST + or choice_ptr.unit != ptr.unit + ): + choice_ptr += 1 + continue + choice_is_default = ( + choice_ptr.default_val.i64 == ptr.default_val.i64 + or ptr.type == lib.AV_OPT_TYPE_FLAGS + and choice_ptr.default_val.i64 & ptr.default_val.i64 + ) + option_choice = wrap_option_choice( + choice_ptr, choice_is_default + ) + choices.append(option_choice) + choice_ptr += 1 + option = wrap_option(tuple(choices), ptr) + options.append(option) + ptr += 1 + self._options = tuple(options) + return self._options + + def __repr__(self): + return f"<{self.__class__.__name__} {self.name} at 0x{id(self):x}>" diff --git a/av/descriptor.pyx b/av/descriptor.pyx deleted file mode 100644 index 720db1625..000000000 --- a/av/descriptor.pyx +++ /dev/null @@ -1,59 +0,0 @@ -cimport libav as lib - -from .option cimport Option, OptionChoice, wrap_option, wrap_option_choice - - -cdef object _cinit_sentinel = object() - -cdef Descriptor wrap_avclass(const lib.AVClass *ptr): - if ptr == NULL: - return None - cdef Descriptor obj = Descriptor(_cinit_sentinel) - obj.ptr = ptr - return obj - - -cdef class Descriptor: - def __cinit__(self, sentinel): - if sentinel is not _cinit_sentinel: - raise RuntimeError("Cannot construct av.Descriptor") - - @property - def name(self): - return self.ptr.class_name if self.ptr.class_name else None - - @property - def options(self): - cdef const lib.AVOption *ptr = self.ptr.option - cdef const lib.AVOption *choice_ptr - cdef Option option - cdef OptionChoice option_choice - cdef bint choice_is_default - if self._options is None: - options = [] - ptr = self.ptr.option - while ptr != NULL and ptr.name != NULL: - if ptr.type == lib.AV_OPT_TYPE_CONST: - ptr += 1 - continue - choices = [] - if ptr.unit != NULL: # option has choices (matching const options) - choice_ptr = self.ptr.option - while choice_ptr != NULL and choice_ptr.name != NULL: - if choice_ptr.type != lib.AV_OPT_TYPE_CONST or choice_ptr.unit != ptr.unit: - choice_ptr += 1 - continue - choice_is_default = (choice_ptr.default_val.i64 == ptr.default_val.i64 or - ptr.type == lib.AV_OPT_TYPE_FLAGS and - choice_ptr.default_val.i64 & ptr.default_val.i64) - option_choice = wrap_option_choice(choice_ptr, choice_is_default) - choices.append(option_choice) - choice_ptr += 1 - option = wrap_option(tuple(choices), ptr) - options.append(option) - ptr += 1 - self._options = tuple(options) - return self._options - - def __repr__(self): - return f"<{self.__class__.__name__} {self.name} at 0x{id(self):x}>"