Open autumnjolitz opened 1 month ago
Thank you for taking the time to raise this issue.
Unfortunately this feature of the py-flags
package (auto-generated values and associated data) isn't well designed, it gives too many options in a messy unorganised way. If I decided to break backwards compatibility in a version 2.0.0, I'd replace this design completely to something much simpler and stricter (allowing only enum_member = value
or enum_member = value, data
as the default behaviour with auto
as a possible value).
I found that using the auto() call from the enum stdlib package was much less verbose and cleaner to the eye than flags.UNDEFINED
What about the following hacks? :smirk:
def auto():
return flags.UNDEFINED
# OR
# Even more concise! However, "constants" in python are usually in uppercase...
auto = flags.UNDEFINED
Supporting something like the above (or a more specific/unique auto
object, like class auto: pass
) in the flags
package isn't a bad idea, and can be added in a backward compatible way.
However, these hacks wouldn't handle your special cases (like isinstance(value, (Buffer, bytes, str))
) that seem to be modifications that are specific to your application. To get that behaviour/syntax you would still need the flag_attribute_value_to_bits_and_data()
override in your code.
Adding support for auto
is a relatively small change but it triggers a cascade of tasks:
Unfortunately, I have to prepare for interviews, so I can't promise anything in the coming weeks.
In addition I discovered it's rather nice to be able to support additional data items by gathering up all values past said auto()
I guess you mean something like option 1 below:
class MyFlags(Flags):
# option 1: data = ('data_item_1', 'data_item_2')
member1 = auto(), 'data_item_1', 'data_item_2'
# option 2: data = ('data_item_1', 'data_item_2')
member2 = auto(), ('data_item_1', 'data_item_2')
Option 1 may not be a good idea. It gives the user too many options to solve the same problem (which isn't pythonic in general), just like some of my over-complicated Frankenstein designs in the past. Another unintuitive aspect of this design is that the first data item ('data_item_1'
in our example) can behave in two different ways (direct value or just an item in a tuple) depending on whether there is only one data item or more. Behaviour like this can already be added with an application-specific flag_attribute_value_to_bits_and_data()
override but in case of library-default behaviour I'd stick to a simpler intuitive implementation.
Option 2 requires typing two more characters but at the same time it makes the intention very clear. There is always only one data item (the tuple in our example) and its value is exactly what the reader can see in the code, it's intuitive. Code is generally written much less often than read so typing a few more characters to make things clearer isn't necessarily bad. Also, this option allows the user to specify a different type of container if needed.
I've used this package for years. :)
I'm glad you enjoy using this package! :-)
However, as you probably know, python 3.6 introduced enum.Flag
and enum.IntFlag
about a year after this package was released, so considering those when they meet the needs of your project might be a good idea.
I found that using the
auto()
call from theenum
stdlib package was much less verbose and cleaner to the eye thanflags.UNDEFINED
Given that I have a
types.py
module in my project that declares enhanced base types, I was able to neatly overrideflags
such that it was able to swap outauto()
for aflags.UNDEFINED
at the definition of a type.Here's how i did it:
As you can see, it's relatively approachable to support instances of
enum.auto()
and may be a nice quality of life enhancement.In addition I discovered it's rather nice to be able to support additional
data
items by gathering up all values past saidauto()
I've used this package for years. :)