Python lets us attach our own data to existing objects (buttons, text fields, etc.), by name, e.g.
button1.my_new_member = "data for use by click-handler"
However, this runs the risk of conflicting with an implementation detail (current or future) of the same name. Is there an approved naming convention we can use, to prevent such conflicts?
This is an excellent question. We’re actually about to deprecate the “feature” that you can add arbitrary attributes to component objects, for precisely the reason you mention - people often accidentally create conflicts, or fail to notice typos.
We will move to an implementation where every component has a ‘tag
’ attribute, which will be an object on which you can set any attributes you wish. You will also be able to replace it completely. For example:
b = Button()
b.tag = "Here is some arbitrary data"
or
b = Button()
b.tag.foo = "Some data"
b.tag.bar = "Some more data"
Of course we will make this change gradually, so existing apps won’t break, but if you want to minimise changes you might have to make, you should use the ‘tag
’ attribute as in the first example above.
Hope that helps. Let me know if it makes sense!
3 Likes
Great! Just what I need. I’ll start following this convention immediately.
Thank you!
Until then, when adding a tag
of my own, what type should it have?
Anything you like! Whatever we will put into tag
by default, you can always overwrite it
My apologies. I’m aiming for forward compatibility of my own, interim, tag
implementation. Below, I try to be more clear.
For now, my code must create tag
. But it must do so with forward-compatibility in mind. If I create tag
as a dict
, for example, that will likely break other, third-party code down the line, that uses the same tag
member. Such code likely assumes tag
was of the type you created.
Here’s my attempt at forward-compatibility. I create tag
as follows:
class Tag : pass
anvil_component.tag = Tag() # interim
anvil_component.tag.user_variable_here = value
So far it works. The hope is that it continues to work (with the 1st 2 lines removed) later on. If clearly not, please advise.
To prevent name-collisions, and accommodate a hierarchy of scopes, nesting can go as deep as necessary (e.g., naming the company/organization, framework/library, application, etc.).
anvil_component.tag.library_name = Tag()
anvil_component.tag.library_name.library_variable = value
This seems quite likely with third-party add-ons (libraries/frameworks) aimed at Anvil developers. If nesting gets any deeper, though, the caller should probably consider refactoring and/or layering.
1 Like
Looks good to me! That’s exactly what we’ll be doing with the official tag
, and your code will continue to work.