Skip to content

pathlib: Path and PurePath cannot be subclassed #75140

Closed

Description

@sbstp
mannequin
BPO 30957
Nosy @pitrou, @stevendaprano, @serhiy-storchaka, @sbstp
Superseder
  • bpo-24132: Direct sub-classing of pathlib.Path
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2017-07-18.12:42:29.596>
    created_at = <Date 2017-07-18.06:40:11.405>
    labels = ['3.7', 'type-feature', 'library']
    title = 'pathlib: Path and PurePath cannot be subclassed'
    updated_at = <Date 2017-07-18.12:42:29.593>
    user = 'https://github.com/sbstp'

    bugs.python.org fields:

    activity = <Date 2017-07-18.12:42:29.593>
    actor = 'serhiy.storchaka'
    assignee = 'none'
    closed = True
    closed_date = <Date 2017-07-18.12:42:29.596>
    closer = 'serhiy.storchaka'
    components = ['Library (Lib)']
    creation = <Date 2017-07-18.06:40:11.405>
    creator = 'sbstp'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 30957
    keywords = []
    message_count = 3.0
    messages = ['298577', '298584', '298585']
    nosy_count = 4.0
    nosy_names = ['pitrou', 'steven.daprano', 'serhiy.storchaka', 'sbstp']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '24132'
    type = 'enhancement'
    url = 'https://bugs.python.org/issue30957'
    versions = ['Python 3.7']

    Activity

    1. sbstp commented on Jul 18, 2017

      sbstpmannequin
      MannequinAuthor

      Because of the special way Path and PurePath are instantiated, they can't be inherited like a normal class. Here's an example of the issue:

      >>> import pathlib
      >>> class MyPath(pathlib.Path):
      ...   pass
      ... 
      >>> p = MyPath('/home')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/usr/lib/python3.5/pathlib.py", line 969, in __new__
          self = cls._from_parts(args, init=False)
        File "/usr/lib/python3.5/pathlib.py", line 651, in _from_parts
          drv, root, parts = self._parse_args(args)
        File "/usr/lib/python3.5/pathlib.py", line 644, in _parse_args
          return cls._flavour.parse_parts(parts)
      AttributeError: type object 'MyPath' has no attribute '_flavour'

      A solution is to get the concrete type of Path via type(Path()) and inherit the class it yields, but it isn't pretty or intuitive. Perhaps a declaration that directs to the proper class could be added to the module.

      PlatformPath = WindowsPath if os.name == 'nt' else PosixPath
      PurePlatformPath = ...
    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Jul 18, 2017
    3. stevendaprano commented on Jul 18, 2017

      @stevendaprano
      Member

      Python 3.4, 3.5 and 3.6 are in feature-freeze, so this enhancement can only apply to 3.7.

      You say that pathlib.Path "can't be subclassed", but then immediately show an example of subclassing it:

      >>> class MyPath(pathlib.Path):
      ...   pass
      ... 

      Which works fine. If you run:

      issubclass(MyClass, pathlib.Path)

      it returns True. Unfortunately, it looks like your subclass broke one of the class invariants, but you don't find out until you try to instantiate it:

      >>> p = MyPath('/home')
      Traceback (most recent call last):
        ...
      AttributeError: type object 'MyPath' has no attribute '_flavour'

      _flavour is a private attribute, and is not documented, so I don't think subclassing is supported. If that is the case:

      • the documentation should say that subclassing is not supported;
      • or the Path class should actively prohibit subclassing (will
        probably require a metaclass);
      • or both.

      If subclassing is supported, then I think there ought to be a better way than this:

      py> class MyPath(pathlib.Path):
      ... _flavour = pathlib.Path('.')._flavour
      ...
      py> MyPath('.')
      MyPath('.')

    4. serhiy-storchaka commented on Jul 18, 2017

      @serhiy-storchaka
      Member

      This is a duplicate of bpo-24132.

    5. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.7 (EOL)end of lifestdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions