What do we mean by inject None in?
We don’t inject it in, not really.
The form template has it’s own descriptors with custom getters and setters.
The main difference is that they know ahead of time the default value.
So if a value is NOT set for a custom component property (in the case of an object
property), the custom component property returns the default value.
>>> form = CustomComponent()
>>> TemplateClass = CustomComponent.__base__
>>> TemplateClass.my_prop
<CustomComponentProperty object>
>>> TemplateClass.my_prop.__get__(form, type(form))
None
# this is the default value
# my_prop was never actually set on the form instance
# and so my_prop getter returns the default value when asked
Here is some more pseudo code for the CustomComponentProperty
descriptor class
(In reality these classes are defined in javascript, but this is largely how they look)
NOT_FOUND = object()
class CustomComponentProperty:
def __init__(self, type, default_value=None):
self._type = type
self._default_value = default_value
def __set_name__(self, owner, name):
self._name = name
def __get__(self, obj, obj_type=None):
if obj is None:
return self
rv = obj._private_custom_props.get(self._name, NOT_FOUND)
if rv is NOT_FOUND:
return self._default_value
return rv
def __set__(self, obj, value):
obj._private_custom_props[self._name] = value
class CustomComponentTemplate(ColumnPanel):
my_prop = CustomComponentProperty("object")
...
When you override a custom component property you take responsibility for the getters and the setters.
And if you take responsibility, you probably want to make sure the getter will still work if the setter was never run.
Side Note, you could pass these onto super but it’s not particularly nice
class CustomComponent(CustomComponentTemplate):
def __init__(self, **properties):
self._super_base = super(CustomComponent, type(self))
self.init_components(**properties)
@property
def my_prop(self):
return self._super_base.my_prop.__get__(self, type(self))
@my_prop.setter
def my_prop(self, value):
self._super_base.my_prop.__set__(self, value)
...
I guess you could also do some fun things with creating your own custom component property override descriptor class, but i’ll leave that as an exercise to the reader.