Skip to content

Python

Due to the use of a custom metaclass as part of the jsii runtime for Python, certain Python idioms require unusual syntax when jsii modules are involved.

Info

Our intention is to make working with jsii modules from Python as idiomatic as possible. Removing the custom metaclass usage without breaking existing code is a challenging task, and the situation may consequently remain sub-optional for the near future at least.

Implementing Interfaces

Traditionally, Python developers expect to be able to either implicitly implement an interface by declaring all required members, or explicitly implement interfaces by simply adding the interface to their class' or interface's inheritance chain (and implementing all required members):

Incorrect Use

from jsii_dependency import IJsiiInterface

class MyNewClass(IJsiiInterface):
    """ Traditional implementation of an interface in Python.

    This will not work with interfaces defined by jsii modules, as this will
    likely cause a metaclass conflict that the user cannot solve.
    """

    # Member implementations...

    ...

The jsii type system however does not support structural typing, and interfaces must always be explicitly implemented. In order to correctly declare implementation of an interface from a jsii module, the following syntax is used:

import jsii
from jsii_dependency import IJsiiInterface

@jsii.implements(IJsiiInterface)
class MyNewClass():
    """ A jsii-supported implementation of the `IJsiiInterface` interface

    This will correctly register the explicit interface implementation on the
    type's metadata, and ensure instances get correctly serialized to and from
    the jsii kernel.
    """

    # Member implementations...

    ...

Property Overrides

When extending or implementing types provided by jsii modules, properties must always be implemented using a dynamic accessor, ensuring the jsii runtime for Python is able to correctly process access to those by the jsii kernel. This leverages Python's standard @property decorator:

from jsii_greeter import Greeter

class Shouter(Greeter):
    """ Shouter extends Greeter up-cases the greetee's name.

    The replacement is implemented using a dynamic @property implementation so
    it works properly with the jsii kernel.
    """

    @property
    def greetee(self) -> str:
        return super().greetee.upper()

    @greetee.setter
    def greetee(self, value):
        super().greetee = value

    ...