[Python-ideas] IntFlags

Andrew Barnert abarnert at yahoo.com
Thu Mar 5 00:42:03 CET 2015


On Mar 4, 2015, at 7:58, Serhiy Storchaka <storchaka at gmail.com> wrote:

> On 04.03.15 17:31, Chris Angelico wrote:
>> On Thu, Mar 5, 2015 at 2:17 AM, Andrew Barnert
>> <abarnert at yahoo.com.dmarc.invalid> wrote:
>>> Another issue that came up was that C flags often have "combined" names that are ambiguous: RDWR = RDONLY | WRONLY), which is fine until you want a repr (in C, it's just going to print 3); does it have to be smart enough to show RDWR? (Or, worse, RDWR | CLOEXEC.)
>> That could probably be handled by going through the flags in iteration
>> order. If the flag is present, emit it and move on. Something like
>> this:
> 
> Yes, something like this, but with iterating flags in descended sorted order, and with special case for negative value.

I think the very fact that the two of you immediately knew which order was obvious, but you chose the opposite one as the obvious one, proves that it's not obvious.

For the record, I think your version is better, because usually the C definitions define the combined values after the individual ones, and it would be nice to be able to mirror the C definitions (or, even better, auto generate the Python from the C header*) and get the desired results.

I think you're also right that using signed 1's complement is the best way to handle negated flags, despite the tradeoffs (not being able to compare to negated C values, having a confusing numerical value in the repr, having silly str for silly cases), especially since that's what ~ already does with IntEnum (except that the result is just plain int, of course).

But regardless, the point is that these questions don't have a single obvious answer; you have to think about them, decide what makes sense, and explain the tradeoffs and why one should win (and implement it). That's why this "simple" proposal didn't make it into 3.4's enum: because it's not actually simple, and everyone who insisted that it was disagreed, and someone (Guido or Eli?) finally told everyone to shut up, flags weren't going into 3.4, and put your competing implementations on PyPI and see which one people use. Do we really want to rehash all those arguments from scratch?

---

* The parenthetical brings up another issue: if you look in your platform's sys/stat.h (or whichever header actually defines these things), S_IRWXG is probably not defined as 0o700, but as S_IRGRP | S_IWGRP | S_IXGRP. Can we do that in the enum definition? If not, it may be less readable than the C. (In fact, on many platforms, S_IRGRP is itself defined as something like _S_IREAD << _S_GRP, and S_IRWXG may be defined as (_S_IREAD | _S_IWRITE | _S_IEXEC) << _S_GRP. I think Linux took this even further and defined it as S_IRWXU >> (_S_USR - _S_GRP) or something silly. But at that point, not being able to clone the C no longer looks like a loss of readability...)



More information about the Python-ideas mailing list