You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First, this module defines a bin function that is not present in the documentation. Such a method should be documented or made private. Indeed, it would feel weird for a user to use from enum import * and have the standard bin() function overriden.
The commit that introcuced this function is #7aaeb2a
This function only appears to have be used by the commit for Flag.missing, where it's present two or three times
Thus, i guess this function was created for internal code refactorisation.
This is a normal use for a function. However, a function used for this should not be available to an importer of enum. It should especially not be able to cause problems in the code of the importer.
I suggest renaming the function _bin and replacing existing occurences of call to this function by a call to its new name.
Broadlier speaking, I do not see a valid reason for the import of builtins in the enum module, because it is bad practice: the only use case is builtin functions having been redefined inside the code, which is a source of confusions and errors and therefore not good practice.
This probably means they're other problems like this in the enum module. One I found is the decorator @property. I did not investigated this one further.
Indeed, it would feel weird for a user to use from enum import * and have the standard bin() function overriden
This wouldn't happen as the module defines an __all__ which, in this case, doesn't re-export bin. So users importing the module wouldn't be annoyed (or they must access it explicitly). Now, I don't know if it's was an oversight that we didn't document bin or not. Ethan, has bin ever been considered part of the public API?
The nonsense in this code, present in the class EnumCheck, is the comment about powers of 1.
This is indeed a typo, probably because it was copy-pasted from above.
Broadlier speaking, I do not see a valid reason for the import of builtins in the enum module, because it is bad practice: the only use case is builtin functions having been redefined inside the code, which is a source of confusions and errors and therefore not good practice.
Sometimes practility beats purity. If the function was meant to be public, enum.bin is clearer than anything else (it's really the same as bin with a few tweaks; calling enum_bin would be overly verbose IMO).
I understand, but it doesn't feel to me like it's meant to be public in this case. Because this function is not the kind of things one would expect to find in a module about enumerations.
As a utility function that is meant only for enums, this is the place where one would expect. It can be a helper for people who want to subclass the enum type itself. However, if it was meant to be private, we need to first deprecate it (it's publicly named and we could break stuff) and the make it private. If it was meant to be part of the public API, then we should document it. I don't really know whether it was meant to be private or not though.
Concerning the import to builtins, I think it's really because of enum.property, which is however documented: https://docs.python.org/3/library/enum.html#enum.property, so this is why we need to import builtins to be able to use it internally (here, we can't change the name of this exposed function without going through a deprecation period and probably a Discourse post and lots of discussions).
If we document enum.bin, I think we can use the docstring. It looks explaining enough to me:
`"""
Like built-in bin(), except negative values are represented in
twos-compliment, and the leading bit always indicates sign
(0=positive, 1=negative).
We could maybe ask @ethanfurman , who made the initial commit. His last commit to enum.py is from July, 10. And it look's on his contribution activity that he's still active
When a module has an __all__, that is the public API. Any functions not in __all__ do not need a leading underscore. I do intend for enum.bin() to become public at some point -- I suppose 3.15 will do.
Actually, I just saw that property is exposed in __all__. May I suggest that we don't expose bin like that as it can shadows built-ins? I don't think it has ever been an issue in practice but this should probably avoided (the OP did mention the possibility for bin to shadow the built-in bin).
Unfortunately, I don't think we can change property being in __all__ in a backwards compatible manner as we can't really know whether someone is having from enum import * and @property somewhere, without knowing that this @property is actually @enum.property (maybe their tests don't cover it).
But if we could avoid making the same thing with bin, I think it would be preferrable (enum can definitely be imported in an util.py file that uses bin for some reasons as well).
But the fact that it has an __all__ means that it should be supported right? or at least that's what I always thought. Maybe we should document that it is not recommended to do it (I don't know if it's not already documented)
__all__ has more than one function. It specifies the names for star-import, and it also specifies the public interface shown in pydoc. So names can be added to __all__ for the sake of pydoc. It does not mean that using star-import with that module is recommended.
On the other hand, sometimes (in rare cases) public names are intentionally not added to __all__ if using star-import with a module is common.
I actually thought that from enum import * was a quite well-used pattern as it's common for enum to be imported with two members (the type and auto), no members (and use enum.*) or more than two members (in which case we have a very long list of members and maybe using enum.* would make the line length overflows).
However, https://grep.app/search?q=from%20enum%20import%20* shows that the pattern is quite rare actually! so maybe we don't even need to document it and we can leave the warning to linters instead (as their warnings are usually read more often that the online docs I think).
Activity
StanFromIreland commentedon Jul 18, 2025
Please do not throw multiple things into one issue. The comment can just be a PR if you have a suggestion. For the function, I use this issue.
CC @ethanfurman
[-]A few things to correct in the enum module[/-][+]Undocumented bin() in enum[/+]picnixz commentedon Jul 18, 2025
This wouldn't happen as the module defines an
__all__which, in this case, doesn't re-exportbin. So users importing the module wouldn't be annoyed (or they must access it explicitly). Now, I don't know if it's was an oversight that we didn't documentbinor not. Ethan, hasbinever been considered part of the public API?This is indeed a typo, probably because it was copy-pasted from above.
Sometimes practility beats purity. If the function was meant to be public,
enum.binis clearer than anything else (it's really the same asbinwith a few tweaks; callingenum_binwould be overly verbose IMO).[-]Undocumented bin() in enum[/-][+]Undocumented `enum.bin`[/+]azerty-svg commentedon Jul 18, 2025
I understand, but it doesn't feel to me like it's meant to be public in this case. Because this function is not the kind of things one would expect to find in a module about enumerations.
picnixz commentedon Jul 18, 2025
As a utility function that is meant only for enums, this is the place where one would expect. It can be a helper for people who want to subclass the enum type itself. However, if it was meant to be private, we need to first deprecate it (it's publicly named and we could break stuff) and the make it private. If it was meant to be part of the public API, then we should document it. I don't really know whether it was meant to be private or not though.
Concerning the import to builtins, I think it's really because of
enum.property, which is however documented: https://docs.python.org/3/library/enum.html#enum.property, so this is why we need to importbuiltinsto be able to use it internally (here, we can't change the name of this exposed function without going through a deprecation period and probably a Discourse post and lots of discussions).[-]Undocumented `enum.bin`[/-][+]Decide the fate of `enum.bin`[/+]azerty-svg commentedon Jul 18, 2025
If we document enum.bin, I think we can use the docstring. It looks explaining enough to me:
`"""
Like built-in bin(), except negative values are represented in
twos-compliment, and the leading bit always indicates sign
(0=positive, 1=negative).
We would just need to correct the spelling mistake: it's two's complement and not compliment
picnixz commentedon Jul 18, 2025
Yes, but I first want to know if it was meant to be public (which is why I changed the issue's title).
azerty-svg commentedon Jul 18, 2025
We could maybe ask @ethanfurman , who made the initial commit. His last commit to enum.py is from July, 10. And it look's on his contribution activity that he's still active
azerty-svg commentedon Jul 18, 2025
Though he may not remember what he thought back in 2021, date of the initial commit
azerty-svg commentedon Jul 18, 2025
Looking at previous discussion, I do not see a mention of enum.bin in the initial commit nor in the pull request that came along ( #24215)
azerty-svg commentedon Jul 18, 2025
For information: I splitted this issue in 2. one fro enum.bin (this one) and another one for the comment
ethanfurman commentedon Jul 18, 2025
When a module has an
__all__, that is the public API. Any functions not in__all__do not need a leading underscore. I do intend forenum.bin()to become public at some point -- I suppose 3.15 will do.picnixz commentedon Jul 19, 2025
Actually, I just saw that
propertyis exposed in__all__. May I suggest that we don't exposebinlike that as it can shadows built-ins? I don't think it has ever been an issue in practice but this should probably avoided (the OP did mention the possibility forbinto shadow the built-inbin).Unfortunately, I don't think we can change
propertybeing in__all__in a backwards compatible manner as we can't really know whether someone is havingfrom enum import *and@propertysomewhere, without knowing that this@propertyis actually@enum.property(maybe their tests don't cover it).But if we could avoid making the same thing with
bin, I think it would be preferrable (enumcan definitely be imported in anutil.pyfile that usesbinfor some reasons as well).ethanfurman commentedon Jul 19, 2025
Using
from some_module import *on a module not designed for that usage is bad practice, and theenummodule was not designed with that usage in mind.picnixz commentedon Jul 19, 2025
But the fact that it has an
__all__means that it should be supported right? or at least that's what I always thought. Maybe we should document that it is not recommended to do it (I don't know if it's not already documented)serhiy-storchaka commentedon Jul 19, 2025
__all__has more than one function. It specifies the names for star-import, and it also specifies the public interface shown inpydoc. So names can be added to__all__for the sake ofpydoc. It does not mean that using star-import with that module is recommended.On the other hand, sometimes (in rare cases) public names are intentionally not added to
__all__if using star-import with a module is common.picnixz commentedon Jul 19, 2025
I actually thought that
from enum import *was a quite well-used pattern as it's common forenumto be imported with two members (the type and auto), no members (and useenum.*) or more than two members (in which case we have a very long list of members and maybe usingenum.*would make the line length overflows).However, https://grep.app/search?q=from%20enum%20import%20* shows that the pattern is quite rare actually! so maybe we don't even need to document it and we can leave the warning to linters instead (as their warnings are usually read more often that the online docs I think).