Interface code generator
========================

Python-sdbus is able to generate the interfaces code from
the D-Bus introspection XML. (either from a file or live object on D-Bus)
Currently async interfaces code is generated by default.
Blocking interfaces can be generated by passing ``--block`` option.

Running code generator requires
`Jinja <https://palletsprojects.com/projects/jinja/>`_
to be installed.

.. warning:: Do NOT send the generator result to ``exec()`` function.
    Interface code MUST be inspected before running.

The generated interfaces code will be syntactically correct but NOT stylistically.
It is recommended running a code formatter on the generated code. (for example ``black``)

Generating from XML files
-------------------------

To run generator on files (such as found under ``/usr/share/dbus-1/interfaces/`` folder)
execute the ``sdbus`` module with ``gen-from-file`` first argument
and file paths to introspection XML files:

.. code-block:: shell

    python -m sdbus gen-from-file /usr/share/dbus-1/interfaces/org.gnome.Shell.Screenshot.xml

The generated interface code will be printed in to stdout. You
can use shell redirection ``>`` to save it in to file.

Multiple interface files can be passed which generates a file
containing multiple interfaces.

Generating from run-time introspection
--------------------------------------

To run generator on some service on the D-Bus execute
the ``sdbus`` module with ``gen-from-connection`` first argument,
the service connection name as second and one or more object paths:

.. code-block:: shell

    python -m sdbus gen-from-connection org.freedesktop.systemd1 /org/freedesktop/systemd1

The generated interface code will be printed in to stdout. You
can use shell redirection ``>`` to save it in to file.

Multiple object paths can be passed which generates a file
containing all interfaces encountered in the objects.

Pass ``--system`` option to use system bus instead of session bus.

Renaming interfaces and members
-------------------------------

*New in version 0.13.0.*

Some interface and member names might conflict with Python keywords when
converted from D-Bus introspection to Python code by gerator. The CLI interface
allow to override the particular interface and member names using the ``--select-*``
and ``--set-name`` options. The selector options move the cursor to a particular
interface and member

Available override options:

* ``--set-name``
    Sets the name of currently selected element as it would
    be in generated Python code. Can be used if either interface or
    member is selected.

* ``--select-interface``
    Selects the interface using its D-Bus name.

* ``--select-method``
    Selects the method using its D-Bus name.
    An interface must be selected first.

* ``--select-property``
    Selects the property using its D-Bus name.
    An interface must be selected first.

* ``--select-signal``
    Selects the signal using its D-Bus name.
    An interface must be selected first.

For example, an ``org.example.Interface`` interface has a property called ``Class``.
When automatically converted the name will become ``class`` which is a reserved Python keyword.

Using these CLI options it is possible to override the name of the property and class:

.. code-block:: shell

    python -m sdbus gen-from-file \
        org.example.interface.xml \
            --select-interface org.example.Interface \
                --set-name Example \
                --select-property Class \
                    --set-name example_class

This will generate following Python code:

.. code-block:: python

    class Example:
        @dbus_property_async(
            property_signature="s",
        )
        def example_class(self) -> str:
            raise NotImplementedError
