Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a metadata slot #898

Open
maximlt opened this issue Jan 4, 2024 · 0 comments
Open

Add a metadata slot #898

maximlt opened this issue Jan 4, 2024 · 0 comments
Labels
type-feature Feature request

Comments

@maximlt
Copy link
Member

maximlt commented Jan 4, 2024

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.

image

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)

This was recently discussed in holoviz/panel#5856.


metadata attribute in dataclasses, attrs, pydantic and traitlets:

image

Code

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')

@maximlt maximlt added the type-feature Feature request label Jan 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-feature Feature request
Projects
None yet
Development

No branches or pull requests

1 participant