Skip to content

fnmatch.filter and filterfalse work with pathlikes only on non-Posix platforms #160900

Description

@JelleZijlstra

fnmatch.filter contains a check:

    if os.path is posixpath:
        # normcase on posix is NOP. Optimize it away from the loop.

It calls normcase on the paths to be filtered only on non-Posix platforms.

The check dates from 2001 and the comment was probably true then. But nowadays, os.path.normcase does do something even on Posix: it normalizes path-like objects into strs or bytes.

So on MacOS I get:

>>> import fnmatch
>>> from pathlib import Path
>>> fnmatch.filter([Path("hi")], "hi")
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    fnmatch.filter([Path("hi")], "hi")
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/Users/jelle/py/cpython/Lib/fnmatch.py", line 61, in filter
    if match(name):
       ~~~~~^^^^^^
TypeError: expected string or bytes-like object, got 'PosixPath'

But this will work on Windows.

I think this is should be fixed for two reasons:

  • It's an unnecessary difference in behavior between platforms. Python should work the same across OSes as much as possible, and there's no good reason for the behavior to differ here.
  • In general, we want path-related functions to accept path-like objects (PEP 519)

However, we've generally treated PEP 519 changes as new features, so let's change this on main only.

Discovered in python/typeshed#16647

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    type-featureA feature request or enhancement
    and removed
    type-bugAn unexpected behavior, bug, or error
    on Oct 29, 2026
  2. picnixz commented on Oct 29, 2026

    @picnixz
    Member

    Yeah, this is somethign I found when I implemented filterfalse but I was afraid to change the implementation. I don't think we need this small optimization anymore.

  3. zedzhen commented on Oct 29, 2026

    @zedzhen

    fnmatch.fnmatch normalizes both parameters (this is explicitly stated in the documentation), and the documentation says

    fnmatch.filter is the same as [n for n in names if fnmatch(n, pat)], but implemented more efficiently.

  4. added a commit that references this issue on Oct 30, 2026
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/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions