Is this a supported method for altering an existing `parametrization` class?

For an app we want to reuse the code for an existing entity (in our codebase), but want to add an extra field in the parametrization. I noticed that regular inheritance doesn’t work

# Pseudo code
from viktor.parametrization import Text
from codebase.entity_x import EntityXParametrization

# This does not work
class ExtendedParametrization(EntityXParametrization):
    extra_field = Text("Hello world")

Directly modifying the original class doesn’t seem to work either.

# Pseudo code
from viktor.parametrization import Text
from codebase.entity_x import EntityXParametrization

# This does not work
EntityXParametrization.extra_field = Text("Hello world")

After some tinkering I found out that the class variables actually do get inherited, but Viktor doesn’t recognize it correctly. I discovered that editing the __fields__ fixes that though.

# Pseudo code
from viktor.parametrization import Text
from codebase.entity_x import EntityXParametrization

EntityXParametrization.extra_field = Text("Hello world")

# This makes it work if you want to add it to the end
EntityXParametrization.__fields__ += ["extra_field"]

# This makes it work if you want to add it to the beginning
EntityXParametrization.__fields__ = (
    [field for field in EntityXParametrization.__fields__ if field.startswith("__")]
    + ["extra_field"]
    + [field for field in EntityXParametrization.__fields__ if not field.startswith("__")]
)

Is this a supported way of altering existing parametrization classes?

We see this usecase in more of our app, so it would be nice if we can actually implement it like this.

Hi,

We do not officially support directly altering the __fields__ attribute, so please be careful with it. But I must admin I admire your creativity!

We also agree that something like inheritance should be preferred, or perhaps some construction like below:

class Extended(ViktorParametrization):
    extra_field = ...
    _ = AnotherParametrization()
    another_field = ...

We still need to investigate whether this is possible.

Another approach is by breaking the source parametrization in smaller pieces and re-use them. This has the benefit of easier composability and more explicit data keys (you don’t have to go to the source parametrization to find the correct data key)

class IntroStep(Step):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.text1 = Text("""
# 👋 Welcome to the demo app! 
""")


class ReportStep(Step):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.your_name = TextField("Please enter your name")
        self.your_score = NumberField("Give yourself a score", variant='slider', min=1, max=10, default=10)


class Parametrization(ViktorParametrization):

    intro = IntroStep("Intro", views='image_view')

    report_step = ReportStep("Report", views='create_report')
    report_step.extra_field = NumberField("This field is extra")
1 Like