• Re: Dynamic classes (Posting On Python-List Prohibited)

    From Lawrence D'Oliveiro@21:1/5 to Stefan Ram on Thu May 22 00:19:50 2025
    On 21 May 2025 11:20:55 GMT, Stefan Ram wrote:

    ... I have this setup where I lay out a table to map out my markup
    language [1] and then use some dynamic code to spin up the classes
    based on that table [0] ...

    The main way I like to do it is start with a basic class object,
    assign some basic attributes like __name__ and __doc__, and
    dynamically attach additional members to it with setattr.

    Here’s a partial example, taken from <https://gitlab.com/ldo/dbussy>.
    Note the heavy use of lexical binding:

    class proxy(BusPeer.Object.ProxyInterface) :
    # class that will be constructed, to be instantiated for a given connection,
    # destination and path.

    # class field _iface_name contains interface name.
    __slots__ = ("_parent", "_conn", "_dest", "_path", "_timeout")

    def __init__(self, *, parent, connection, dest, path, timeout = DBUS.TIMEOUT_USE_DEFAULT) :
    if is_async :
    assert connection.loop != None, "no event loop to attach coroutines to"
    #end if
    self._parent = parent
    self._conn = connection
    self._dest = dest
    self._path = path
    self._timeout = timeout
    #end __init__

    # rest filled in dynamically below.

    #end proxy

    def def_method(intr_method) :
    # constructs a method-call method.

    if is_async :

    async def call_method(self, *args, **kwargs) :
    message = dbus.Message.new_method_call \
    (
    destination = self._dest,
    path = dbus.unsplit_path(self._path),
    iface = self._iface_name,
    method = intr_method.name
    )
    _append_args(message, intr_method, args, kwargs)
    if intr_method.expect_reply :
    reply = await self._conn.send_await_reply(message, self._timeout)
    result = reply.expect_return_objects(intr_method.out_signature)
    else :
    message.no_reply = True
    self._conn.send(message)
    result = None
    #end if
    return \
    result
    #end call_method

    else :

    def call_method(self, *args, **kwargs) :
    message = dbus.Message.new_method_call \
    (
    destination = self._dest,
    path = dbus.unsplit_path(self._path),
    iface = self._iface_name,
    method = intr_method.name
    )
    _append_args(message, intr_method, args, kwargs)
    if intr_method.expect_reply :
    reply = self._conn.send_with_reply_and_block(message, self._timeout)
    result = reply.expect_return_objects(intr_method.out_signature)
    else :
    message.no_reply = True
    self._conn.send(message)
    result = None
    #end if
    return \
    result
    #end call_method

    #end if

    #begin def_method
    call_method.__name__ = intr_method.name
    call_method.__doc__ = \
    (
    "method, %(args)s, %(result)s"
    %
    {
    "args" :
    (
    lambda : "no args",
    lambda : "args %s" % dbus.unparse_signature(intr_method.in_signature),
    )[len(intr_method.in_signature) != 0](),
    "result" :
    (
    lambda : "no result",
    lambda : "result %s" % dbus.unparse_signature(intr_method.out_signature),
    )[len(intr_method.out_signature) != 0](),
    }
    )
    setattr(proxy, intr_method.name, call_method)
    #end def_method

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)