[Python-ideas] IntFlags
Andrew Barnert
abarnert at yahoo.com
Sat Mar 7 14:53:09 CET 2015
On Mar 7, 2015, at 12:07 AM, Ethan Furman <ethan at stoneleaf.us> wrote:
>
>> On 03/03/2015 07:52 AM, Serhiy Storchaka wrote:
>>
>> We need new type IntFlags. It is like IntEnum, but has differences:
>>
>> 1. The value of an instance should be not limited to the set of predefined constants. It can be a combination of
>> predefined constants or even arbitrary integer.
>>
>> 2. The result of "|", "&" and "~" operators for IntFlags arguments should be an instance of the same IntFlags subclass.
>>
>> 3. It should have nice str() and repr().
>
> As long as we are dreaming :)
>
> class Stat(IntFlag):
> RDONLY = 1
> NOSUID = 2
> NODEV = 4
> NOEXEC = 8
> SYNCHRONOUS = 16
> MANDLOCK = 64
> WRITE = 128
> APPEND = 256
> NOATIME = 1024
> NODIRATIME = 2048
> RELATIME = 4096
>
> a = Stat.RDONLY # creates a new instance of Stat, not a singleton
Why? Assuming the values are immutable (like int), the only difference is your is test, and I have no idea why your code would care about that. (If you're worried about the "a |=" below changing b--or, worse, changing the constant--there's no reason to worry. Just as "a = 1; a |= 2" doesn't affect any other variable holding the int 1, the same would be true here.)
> b = Stat.RDONLY
> a is b # False
> a == b # True
>
> c = a
> a |= Stat.MANDLOCK
> c.MANDLOCK # 64
> b.MANDLOCK # 0
> c is a # True
>
> repr(a) # <Stat.MANDLOCK|RDONLY: 65>
> repr(b) # <Stat.RDONLY: 1>
>
> d = b | 32 # undefined value
> repr(d) # <Stat.32|RDONLY: 33>
> d.MANDLOCK = True
> repr(d) # <Stat.MANDLOCK|32|RDONLY: 97>
>
> repr(~d) # <Stat.RELATIME|NODIRATIME|NOATIME|512|APPEND|WRITE|SYNCHONOUS|NOEXEC|NODEV|NOSUID: 8094>
>
> I'm not at all sure I have that last one correct.
That last one is the big question. In C, ~d is going to have the 8192, 16384, ... 2b bits set, not just the bits you defined and the gaps in between. Are you sure you want a different result in Python? (Especially if you're on a platform that does something with those extra bits, so you can get values back that actually have them set. Although I don't think that's an issue with stat, it is with lots of other flags from POSIX-land.)
Look at all of the alternatives that have been suggested (round up to power of 256, guess what C would do on your platform with the most likely equivalent definitions, use signed instead of unsigned so the issue moves somewhere else, handle complementing with a special bool, maybe others); why is this one better? Why is it OK to set the undefined 512 bit but not the equally-undefined 8192 bit when someone does ~ on a value of 32?
More information about the Python-ideas
mailing list