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 — Add case_sensitive argument to `pathlib.PurePath.match()` · Issue #104484 · python/cpython

Add case_sensitive argument to pathlib.PurePath.match() #104484

New issue
Copy link
New issue
Copy link
Closed
Closed
Add case_sensitive argument to pathlib.PurePath.match()#104484
Copy link
Labels
topic-pathlibtype-featureA feature request or enhancementA feature request or enhancement

Description

@barneygale
barneygale
opened on May 14, 2023
Issue body actions

In #81079 we added a case_sensitive argument to pathlib.Path.glob() and rglob(). It would be good to have this functionality available in the closely-related PurePath.match() method. The rationale is much the same: this argument is useful when dealing with case-sensitive filesystems on Windows, and case-insensitive filesystems on Posix. Also, it would allow this method to be used from glob() to implement recursive globbing efficiently, which is important for #102613.

Linked PRs

  • gh-104484: Add parameter @case_sensitive to pathlib.PurePath.match() function #104565

Activity

  1. barneygale
    added
    type-featureA feature request or enhancementA feature request or enhancement
    topic-pathlib
    on May 14, 2023
  2. barneygale commented on May 14, 2023

    @barneygale
    barneygale
    on May 14, 2023
    ContributorAuthor
    More actions

    I'd like to land #101398 before I start work on this.

  3. thirumurugan-git commented on May 16, 2023

    @thirumurugan-git
    thirumurugan-git
    on May 16, 2023
    Contributor
    More actions

    Hi @barneygale,
    I believe it's a relatively simple problem that I can help fix. May I have the opportunity to work on it?

  4. thirumurugan-git commented on May 16, 2023

    @thirumurugan-git
    thirumurugan-git
    on May 16, 2023
    Contributor
    More actions

    @barneygale kindly review this PR

  5. barneygale
    added a commit that references this issue on May 18, 2023

    GH-104484: Add case_sensitive argument to `pathlib.PurePath.match()` (G…

    dcdc90d
  6. barneygale commented on May 18, 2023

    @barneygale
    barneygale
    on May 18, 2023
    ContributorAuthor
    More actions

    Added in #104565 / dcdc90d. Thank you, @thirumurugan-git!

  7. barneygale
    closed this as completedon May 18, 2023
  8. carljm
    added a commit that references this issue on May 18, 2023

    Merge branch 'main' into nestedcomps

    54095f0
  9. eryksun commented on May 18, 2023

    @eryksun
    eryksun
    on May 18, 2023
    Contributor
    More actions

    It should be noted in the docs that Path.match() has changed in 3.12 to use re.IGNORECASE instead of normalizing the path and pattern with os.path.normcase(). On Windows, os.path.normcase() is based on the system's lowercase mapping, while re.IGNORECASE is based on Python's lowercase mapping. The two differ for 200 BMP characters and 260 non-BMP characters. Thus some patterns may match a path in 3.11 but not in 3.12, and vice versa.

  10. eryksun
    reopened this on May 18, 2023
  11. barneygale commented on May 19, 2023

    @barneygale
    barneygale
    on May 19, 2023
    ContributorAuthor
    More actions

    It used str.lower() in 3.11:

    cpython/Lib/pathlib.py

    Lines 189 to 190 in d1bfefd

    def casefold_parts(self, parts):
    return [p.lower() for p in parts]

  12. eryksun commented on May 19, 2023

    @eryksun
    eryksun
    on May 19, 2023
    Contributor
    More actions

    I lost track of changes in 3.12. I thought it always used normcase() for case folding in match() as well as the hash and comparison methods. Instead, this issue restores the use of str.lower() in match(). However, the hash and comparison methods will be inconsistent on Windows because they still use _str_normcase based on os.path.normcase(). Thus match() could be true while __eq__() is false, or vice versa, given component names that contain any of the 460 characters for which str.lower() and ntpath.normcase() are different.

    Reacted by Barney Gale
  13. barneygale commented on May 24, 2023

    @barneygale
    barneygale
    on May 24, 2023
    ContributorAuthor
    More actions

    Here's a table showing how __eq__(), match() and glob() are implemented in 3.11 and 3.12:

    3.11 3.12
    __eq__() str.lower() os.path.normcase()
    match() str.lower() re.IGNORECASE
    glob() re.IGNORECASE re.IGNORECASE

    You can see that things were already inconsistent in 3.11. For 3.12, we've:

    1. Brought __eq__() more in line with Windows' filename comparisons
    2. Brought match() in line with its sister method glob()

    I wouldn't mind changing __eq__() and friends back to using lower() if you thought that best, @eryksun!

  14. eryksun commented on May 24, 2023

    @eryksun
    eryksun
    on May 24, 2023
    Contributor
    More actions

    @barneygale

    AFAIK, str.lower() and re.IGNORECASE are consistent. The inconsistency is with ntpath.normcase() on Windows. It's probably for the best if the pure comparison methods revert to using str.lower() for the sake of consistency, not only with glob() and match(), but also with using PureWindowsPath on POSIX. Maybe platform-dependent comparisons could be implemented on Path.

    On Windows, ntpath.normcase() is based on LCMapStringEx(). It turns out that this function implements a case mapping for some non-BMP characters. WinAPI CompareStringOrdinal(), on the other hand, has no case mapping for non-BMP characters, which is consistent with Microsoft's filesystems. Thus I'd prefer for a platform-dependent comparison to use CompareStringOrdinal() instead of LCMapStringEx().

    Given that any tree in a Linux ext4 filesystem can be made case insensitive, and any tree in a Windows NTFS filesystem can be made case sensitive (even a non-empty directory if the registry setting allows it), I'd prefer for a platform-dependent comparison to support partially realized behavior in this regard. Maybe the Path constructor could allow overriding the default case sensitivity for all of a path or a subtree of a path.

    Reacted by Barney Gale
  15. barneygale commented on May 25, 2023

    @barneygale
    barneygale
    on May 25, 2023
    ContributorAuthor
    More actions

    Thank you Eryk. I've logged a new issue here: #104947. Will get it fixed pronto!

    AFAIK, str.lower() and re.IGNORECASE are consistent.

    Seemingly not in all circumstances:

    >>> s = 'ı'
    >>> t = 'i'
    >>> s.lower() == t.lower()
    False
    >>> import re
    >>> re.match(s, t, flags=re.IGNORECASE)
    <re.Match object; span=(0, 1), match='i'>

    Given that any tree in a Linux ext4 filesystem can be made case insensitive, and any tree in a Windows NTFS filesystem can be made case sensitive (even a non-empty directory if the registry setting allows it), I'd prefer for a platform-dependent comparison to support partially realized behavior in this regard. Maybe the Path constructor could allow overriding the default case sensitivity for all of a path or a subtree of a path.

    This is on my to-do list :)

  16. barneygale commented on May 25, 2023

    @barneygale
    barneygale
    on May 25, 2023
    ContributorAuthor
    More actions

    Re-resolving this ticket per the above.

  17. barneygale
    closed this as completedon May 25, 2023
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

    topic-pathlibtype-featureA feature request or enhancementA feature request or enhancement

    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.