GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — pathlib.Path._from_parsed_parts should call cls.__new__(cls) · Issue #76846 · python/cpython

pathlib.Path._from_parsed_parts should call cls.__new__(cls) #76846

New issue
Copy link
New issue
Copy link
Closed
Closed
pathlib.Path._from_parsed_parts should call cls.__new__(cls)#76846
Copy link
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-pathlibtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

qb-cea
mannequin
opened on Jan 25, 2018
Issue body actions
BPO 32665
Nosy @pitrou, @pablogsal, @qb-cea
Files
  • reproducer.py: reproducer (tested with python3.4)
  • 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 = None
    created_at = <Date 2018-01-25.12:27:25.104>
    labels = ['type-bug', 'library']
    title = 'pathlib.Path._from_parsed_parts should call cls.__new__(cls)'
    updated_at = <Date 2018-01-27.21:38:03.770>
    user = 'https://github.com/qb-cea'

    bugs.python.org fields:

    activity = <Date 2018-01-27.21:38:03.770>
    actor = 'pablogsal'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2018-01-25.12:27:25.104>
    creator = 'qb-cea'
    dependencies = []
    files = ['47409']
    hgrepos = []
    issue_num = 32665
    keywords = []
    message_count = 5.0
    messages = ['310671', '310758', '310888', '310889', '310890']
    nosy_count = 3.0
    nosy_names = ['pitrou', 'pablogsal', 'qb-cea']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue32665'
    versions = ['Python 3.6']

    Linked PRs

    • GH-76846, GH-85281: Call __new__() and __init__() on pathlib subclasses #102789
    Reacted by Mr.GoodBudd

    Activity

    1. qb-cea commented on Jan 25, 2018

      @qb-cea
      qb-ceamannequin
      on Jan 25, 2018
      MannequinAuthor
      More actions

      Hi,

      I tried subclassing pathlib.Path and provide it with a new attribute (basically an accessor to an extended attribute). I am rather new to the concept of __slots__ and __new__() but here is how I pictured it should look:

      from errno import ENODATA
      from os import getxattr, setxattr
      from pathlib import Path
      
      class Path_(type(Path())):
      
          __slots__ = ("new_attr",)
      
          def __new__(cls, *args, new_attr=None, **kwargs):
              self = super().__new__(cls, *args, **kwargs)
              self._new_attr = new_attr
              return self
      
          @property
          def new_attr(self):
              if self._new_attr:
                  return self._new_attr
          try:
              new_attr = getxattr(self, "user.new_attr")
          except OSError as exc:
              if exc.errno != ENODATA:
                  raise exc
          else:
              self._new_attr = new_attr
              return new_attr
      
              new_attr = b"something_dynamic" # for example uuid4().bytes
              setxattr(self, "user.new_attr", new_attr)
              self._new_attr = new_attr
              return new_attr

      The issue I have is that although my class defines its own __new__() method, it is not always called by the methods of pathlib.Path. For example:

      >>> Path_("/etc").parent.new_attr
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/path/to/reproducer.py", line 19, in new_attr
          if self._new_attr:
      AttributeError: _new_attr

      The current workaround I use consists in redefining pathlib.Path's _from_parsed_parts() method in my class: instead of creating a new object using:
      object.__new__(cls)
      my implementation uses:
      cls.__new__(cls)

      This is the first time I play with the __new__() special method, so it is possible I missed something, if so, sorry for the noise.

    2. qb-cea
      added
      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
      on Jan 25, 2018
    3. qb-cea commented on Jan 26, 2018

      @qb-cea
      qb-ceamannequin
      on Jan 26, 2018
      MannequinAuthor
      More actions

      Typo in the code of the previous comment:

      • __slots__ = ("new_attr",)
        + __slots__ = ("_new_attr",)
    4. qb-cea
      added
      type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
      on Jan 26, 2018
    5. pablogsal commented on Jan 27, 2018

      @pablogsal
      pablogsal
      on Jan 27, 2018
      Member
      More actions

      This behaviour is because "parent" descriptor ends calling:

          @classmethod
          def _from_parsed_parts(cls, drv, root, parts, init=True):
              self = object.__new__(cls)
              self._drv = drv
              self._root = root
              self._parts = parts
              if init:
                  self._init()
              return self

      and this calls object.__new__ and this call raises AttributeError: new_attr. Notice that object.__new__(cls) will not raise as this snippet shows:

      >>>: class A:
      ...: def __new__(*args):
      ...: raise ZeroDivisionError()
      ...:

      >> A()
      ---------------------------------------------------------------------------

      ZeroDivisionError                         Traceback (most recent call last)
      <python> in <module>()
      ----> 1 A()

      <python> in __new__(*args)
      1 class A:
      2 def __new__(*args):
      ----> 3 raise ZeroDivisionError()
      4

      ZeroDivisionError:

      >> object.__new__(A)
      >> <main.A at 0x7f6239c17860>

    6. pablogsal commented on Jan 27, 2018

      @pablogsal
      pablogsal
      on Jan 27, 2018
      Member
      More actions

      Sorry, the exception of object.__new__(cls) is AttributeError: _drv

    7. pablogsal commented on Jan 27, 2018

      @pablogsal
      pablogsal
      on Jan 27, 2018
      Member
      More actions

      Antoine, is the reason of calling object.new(cls) in _from_parsed_parts that the code does not raise on creation?

    8. ezio-melotti
      transferred this issue fromon Apr 10, 2022
    9. brettcannon
      added
      topic-pathlib
      on Jun 21, 2022
    10. barneygale commented on Jan 5, 2023

      @barneygale
      barneygale
      on Jan 5, 2023
      Contributor
      More actions

      #100481 removes _from_parsed_parts() and adds a supported route for subclassing, so would resolve this issue I believe.

    11. barneygale
      added a commit that references this issue on Feb 4, 2023

      pythonGH-101362 - Optimise pathlib by deferring path normalisation

      This issue will close once commit b428069 is merged into the 'master' branch.
      b428069
    12. barneygale
      added a commit that references this issue on Apr 3, 2023

      GH-76846, GH-85281: Call `__new__()` and `__init__()` on pathlib subc…

      11c3020
    13. barneygale commented on Apr 3, 2023

      @barneygale
      barneygale
      on Apr 3, 2023
      Contributor
      More actions

      Fixed in Python 3.12 / #102789 / 11c3020

    14. barneygale
      closed this as completedon Apr 3, 2023
    15. gaogaotiantian
      added a commit that references this issue on Apr 8, 2023

      pythonGH-76846, pythonGH-85281: Call `__new__()` and `__init__()` on …

      2658fae
    16. warsaw
      added a commit that references this issue on Apr 11, 2023

      pythonGH-76846, pythonGH-85281: Call `__new__()` and `__init__()` on …

      ecd5328
    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

      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-pathlibtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        You are visitor 01402503 — GeezerVison does not store the pages you look up.
        Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.