Libraries like Pydantic, attrs, Traitlets and the built-in dataclasses all offer a way to attach metadata to their field/attributes with some more or less convenient API to retrieve them. Parameters in Param doesn't have a similar slot.
From experience I know I've needed that a few times and I've definitely abused the precedence slot to attach some data to Parameters.
Another motivation to add a metadata slot is related to Panel. The Param Pane offered by Panel is very practical to turn a Parameterized class into a viewable component, Panel maintaining a mapping between Parameter types and its widget types. However, sometimes one needs to configure a widget just a bit more and in this case Panel offers two approaches shown below: (1) pass additional widget configs to pn.Param or (2) use <WidgetClass>.from_param(<parameter>, ...) to instantiate a widget manually.
import param
import panel as pn
pn.extension()
class User(param.Parameterized):
fullname = param.String()
user = User()
pn.Param(user.param, widgets={'fullname': {'width': 100}}) # 1
pn.widgets.TextInput.from_param(user.param.fullname, width=100) # 2
I tend to use option (2) as there's often something custom I need to do (e.g. adding some text in between widgets, laying them out in a special way) that isn't made possible by (1), or at least not in a straightforward way. This makes the code quite verbose. Instead Panel could leverage the metadata slot to automatically pass widget kwargs collected from a special namespace (e.g. panel_kwargs) to .from_param() (that I believe is used in the implementation of pn.Param):
class User(param.Parameterized):
fullname = param.String(metadata={'panel_kwargs': {'width': 100}})
user = User()
pn.Param(user.param)
Libraries like Pydantic, attrs, Traitlets and the built-in dataclasses all offer a way to attach metadata to their field/attributes with some more or less convenient API to retrieve them.
Parameter
s in Param doesn't have a similar slot.From experience I know I've needed that a few times and I've definitely abused the
precedence
slot to attach some data to Parameters.Another motivation to add a
metadata
slot is related to Panel. TheParam
Pane offered by Panel is very practical to turn a Parameterized class into a viewable component, Panel maintaining a mapping between Parameter types and its widget types. However, sometimes one needs to configure a widget just a bit more and in this case Panel offers two approaches shown below: (1) pass additional widget configs topn.Param
or (2) use<WidgetClass>.from_param(<parameter>, ...)
to instantiate a widget manually.I tend to use option (2) as there's often something custom I need to do (e.g. adding some text in between widgets, laying them out in a special way) that isn't made possible by (1), or at least not in a straightforward way. This makes the code quite verbose. Instead Panel could leverage the
metadata
slot to automatically pass widget kwargs collected from a special namespace (e.g.panel_kwargs
) to.from_param()
(that I believe is used in the implementation ofpn.Param
):This was recently discussed in https://github.com/holoviz/panel/issues/5856.
metadata attribute in dataclasses, attrs, pydantic and traitlets:
Code
```python metadata = {'namespace': {'key1': 'value1'}} ## `dataclasses` import dataclasses @dataclasses.dataclass class User: name: str = dataclasses.field(metadata=metadata) user = User(name='bob') dataclasses.fields(user)[0].metadata ## `attrs` import attrs @attrs.define class User: name: str = attrs.field(metadata=metadata) user = User(name='bob') attrs.fields(User)[0].metadata ## `pydantic` import pydantic class User(pydantic.BaseModel): name: str = pydantic.Field(metadata=metadata) user = User(name='bob') user.model_fields['name'].json_schema_extra['metadata'] ## `traitlets` import traitlets class User(traitlets.HasTraits): name = traitlets.Unicode().tag(**metadata) user = User(name='bob') user.trait_metadata('name', 'namespace') ```