Take inspiration from streamlit-pydantic
MarcSkovMadsen opened this issue · 3 comments
streamlit-pydantic is an existing, more mature package. There might be a lot of things to learn and get inspiration from including the documentation and implementation.
The request is
- To update the the README and documentation with inspiration from streamlit-pydantic
- consider renaming to panel-pydantic similarly to streamlit-pydantic
- Evaluate whether there are things in the streamlit-pydantic implementation that could inspire or be reused. If yes then create a list of things to implement in the issue list.
Actually what inspired me to write this package was frustration with streamlit-pydantic (so i should probably add them to the credits list 😆 )
My goal for this implementation is to be the opposite of that implementation...
Im mostly joking of course, they do have a very nice README. I just dont yet feel comfortable advertising it so aggressively when its not yet stable and I dont have proper testing set up...
regarding the name change, as soon as the package is stable and feels like a "real" python package then id be happy to rename it and restart the version counter.
P.S. The only reason I'm bumping the version currently is that I'm using it in another project that is deployed with pip so I tend to bump the version even after small changes if I happen to need them in the other package.
Could you describe the issues with streamlit-pydantic that you are trying to solve? What should be done better here?
Mostly the approach. They take the model .schema() result and they have a list of supported jsonschema specs, for each property they just go one by one with a huge if-else statement and test whether it matches that property type and if it does they call the appropriate function on the rendering class. There is no support for arbitrary types and configuration, only jsonschema stuff. My approach is to use the actual python type for dispatching what widget builder to use and to use the information in the actual ModelField instance inside the widget builder to construct a widget. The dispatch system is based on the python type-system and is completely overridable, so any user can add support for arbitrary python types or override the widget builder for a supported type or only for a specific sub-class.
For instance if you have a subclass of some type, eg
import pandas as pd
class DatetimeInterval(pd.Interval):
# some logic asserting left and right are pd.Timestamp
and you wanted these intervals to be edited with a subclass of DatetimeRangePicker eg:
import pydantic_panel as pp
import panel as pn
class TimeIntervalEditor(DatetimeRangePicker):
value = param.ClassSelector(DatetimeInterval, default=None)
def _serialize_value(self, value):
value = super()._serialize_value(value)
if any([v is None for v in value]):
return None
return DatetimeInterval(left=value[0], right=value[1])
def _deserialize_value(self, value):
if isinstance(value, DatetimeInterval):
value = value.left, value.right
value = super()._deserialize_value(value)
return value
@param.depends('start', 'end', watch=True)
def _update_value_bounds(self):
pass
you would just do:
@pp.infer_widget.dispatch(precedence=2)
def infer_widget(value: DatetimeInterval, field: Optional[ModelField] = None, **kwargs):
kwargs = clean_kwargs(TimeIntervalEditor, kwargs)
return TimeIntervalEditor(value=value, **kwargs)
This kind of this is impossible in streamlit-pydantic just by nature of their design choices.