This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: pathlib '/' operator does not resolve Enums with str mixin as expected
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: andrewni, brett.cannon, ethan.furman, xtreak
Priority: normal Keywords:

Created on 2019-12-17 23:37 by andrewni, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (4)
msg358598 - (view) Author: Andrew Ni (andrewni) Date: 2019-12-17 23:37
import os
import pathlib
import enum

class MyEnum(str, enum.Enum):
    RED = 'red'

# this resolves to: '/Users/niandrew/MyEnum.RED'
# EXPECTED: '/Users/niandrew/red'
str(pathlib.Path.home() / MyEnum.RED)

# this resolves to: '/Users/niandrew/red'
os.path.join(pathlib.Path.home(), MyEnum.RED)
msg358615 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-12-18 07:40
As per the fspath PEP https://www.python.org/dev/peps/pep-0519/#c-api the below precedence is set. So for the enum inheriting from str the object itself is returned and MyEnum.RED.__str__ is used returning MyEnum.RED. You can remove inheritance from str and implement __fspath__ for your enum class to be used as per fspath protocol.

> If the object is str or bytes, then allow it to pass through with
  an incremented refcount. If the object defines __fspath__(), then
  return the result of that method. All other types raise a TypeError.

# bpo39081.py

import os
import pathlib
import enum

class MyEnum(enum.Enum):
    RED = 'red'

    def __fspath__(self):
        return self.name

print(os.fspath(MyEnum.RED))
print(pathlib.Path.home() / MyEnum.RED)

$ python3.8 bpo39081.py
RED
/Users/kasingar/RED
msg358633 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2019-12-18 17:31
Karthikeyan is right and this is working as expected. If you want the semantics you're after you can either implement __fspath__ as was suggested or get the 'value' attribute of the enum when constructing your path.
msg358637 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2019-12-18 17:48
The other option is to continue to inherit from `str`, but override the `__str__` method:

    class MyEnum(str, enum.Enum):
        #
        def __str__(self):
            return self.value
History
Date User Action Args
2022-04-11 14:59:24adminsetgithub: 83262
2019-12-18 17:48:52ethan.furmansetmessages: + msg358637
2019-12-18 17:31:06brett.cannonsetstatus: open -> closed

nosy: + brett.cannon
messages: + msg358633

resolution: not a bug
stage: resolved
2019-12-18 07:40:18xtreaksetnosy: + xtreak, ethan.furman
messages: + msg358615
2019-12-17 23:37:20andrewnicreate