-
-
Notifications
You must be signed in to change notification settings - Fork 180
Python SDK: Add a helper for constructing data-* attributes #902
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
Python SDK: Add a helper for constructing data-* attributes #902
Conversation
3ca8474 to
b5d5c8c
Compare
b5d5c8c to
098bbc9
Compare
8bd04ce to
30091d5
Compare
|
@gazpachoking my vote is is use |
|
I think I'm leaning toward attribute_generator, but have the idiomatic usage be |
|
Hmm. I sorta like the way keyword arguments are used in ft_datastar. I might try those out for data-signals and a few others. |
I like this library, good example, works well |
Add docstrings for all attributes.
|
I added support for keyword arguments to data-signals, data-class, data-computed, and data-attr. I decided not to do any case mangling there, if you need to deal with identifiers that aren't representable as python identifiers you need to use the dict format. |
|
Added proper escaping when rendering to text. |
|
Hmm. data-computed has a bit different interface to other similar attributes, i.e. Double hmm, data-on also has the (key, value) form, but I don't see quite as nice a way to change that one. Since it has modifiers, allowing dict/kwargs form gets awkward because it could create multiple data-on attributes and there wouldn't be a nice way to add modifiers then. Especially since different -on events allow different modifiers. |
|
Made data.computed consistent with attrs and class. It takes a dict for string form, or kwargs. |
|
Feeling quite good about this now. |
|
I use python. This seems pretty useful to me. |
|
This looks good. Just want to double check that the signals method supports namespaced signals (didn't see an example) - I'm assuming it does using a dictionary argument. Otherwise LGTM - don't have an issue with this being added to the SDK. |
Let expressions_ mode work for nested signals
Yep, nested dicts, pretty much the same as you'd do it with the js objects. I did realize that the typing wasn't quite complete, and a bit wrong for the keyword form of data.signals. Fixed that up. And expressions mode wouldn't have work on namespaced signals, fixed that as well now. |
|
One thing the signals helper doesn't support is setting signal values as objects. Do we think that's important? I think it's already a bit confusing how it's supported in datastar, where Because of this ambiguity, I don't know how you'd specify using the helper that you'd like an object as a signal value rather than a namespaced signal. |
|
One conflict needs resolving before I can merge. |
# Conflicts: # sdk/python/src/datastar_py/__init__.py
|
First off, outstanding work. This is terrific for everyone. Even Jinja/Django users can use these generators to create template functions/template tags and get a lot of the benefits you mentioned. I agree that that just importing
|
I got pretty comfortable with the way it's working right now and shown in the example |
Agreed, I really like the idea of using Are you thinking that we would recommend folks use the |
Yep. Just like shown in the code snippets in the top post. (People can of course import it however they want, that's just how I would do it and show it in examples.) |
|
Is the thought that we/users might use attribute_generator for anything other than from typing import Any
from .sse import SSE_HEADERS, ServerSentEventGenerator
from .attributes import attribute_generator
data = attribute_generator #new
__all__ = ["attribute_generator", "data", "ServerSentEventGenerator", "SSE_HEADERS"] #changedIf that sounds good, what do you think about namespacing |
|
You mean just exposing it with 2 names, both attribute_generator and data? I don't quite get what you mean. I just think providing it directly as 'data' is super ambiguous, even if it is a nice way to use it |
Agree, that's why my ideal import statement would be something like |
I'm unconvinced. Adding extra packages just to namespace that single import seems a bit overkill to me (and I'm not even sure I like it better) |
9d4831d to
3587991
Compare
3587991 to
f1d2471
Compare
|
Let me know when this is ready to be merged. |
|
I think we are good to go. |
|
Merged 🚀 |
|
Hey @lllama - are these changes pulled into your datastar-py lib that can be installed through pip or the direct github install is the only way now? |
|
The pypi version does not have these changes yet, they will be included next time we do a release there |
Adds a fluent helper for constructing data-* attributes in the Python SDK.
data.computed("FooBar", "$foo")->data-computed-foo-bar__case.pascal='$foo'It doesn't (and can't) save you from identifiers that are unrepresentable, e.g.Caps_And_Underscores. (Should it error at runtime? Or just let you fail?)data.class_(foo="$bar")) If you need kabab case or anything unrepresentable with a python identifier you must use the dict form. (data.class_({'foo-bar': '$baz'}))ds = AttributeGenerator(alias='data-star-')This is most useful when using a tool to construct html in python, like htpy or Fasthtml. These libraries allow defining tags with attributes using a function with keyword arguments, but this method doesn't work for attributes that aren't valid python identifiers, like data-* attributes which have hyphens. Both of these frameworks allow falling back to providing a dictionary of attributes, but the dx isn't quite as nice. This helper allows constructing an attribute dict for datastar attributes in a nicer way.
These two issues would make compatibility with fasthtml and htpy even better:
It also works in a templating language like jinja but I don't recommend that. Jinja doesn't have the same issues (it's just text, you can already type attributes with -) nor does it get the advantages (it's untyped, so no IDE completion or type checking) It does mean errors would happen on server side when rendering the html rather than on client side if you have some invalid datastar syntax, (using non-existent modifiers for example,) so there could still be some value.
My main questions are about how this should be named and imported. Should it be called
datato mirror most closely regular usage?data.persist == data-persistThat feels a bit generic though, maybeds?ds.bind('mysignal')Either of these don't feel very descriptive when importing from the library though, so my current top contender is to provide it as a name likeattribute_generatorand let the user alias it to whatever they want. Examples would probably be shown with it imported asdataTODO:
Some examples:
To test this out before it gets merged, if you are using uv to install your dependencies: