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 — `os.path.isabs` change in behavior in Python 3.13 on MS-Windows · Issue #125283 · python/cpython

os.path.isabs change in behavior in Python 3.13 on MS-Windows #125283

New issue
Copy link
New issue
Copy link
Closed as not planned
Closed as not planned
os.path.isabs change in behavior in Python 3.13 on MS-Windows#125283
Copy link
Labels
3.13only security fixesonly security fixesOS-windowsstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@ikappaki
ikappaki
opened on Oct 10, 2024
Issue body actions

Bug report

Bug description:

I'm not sure if this is a fix or a regression issue?

os.path.isabs use to return True when a windows path started with /.

In python 3.13

Python 3.13.0 (tags/v3.13.0:60403a5, Oct  7 2024, 09:38:07) [MSC v.1941 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os.path
>>> os.path.isabs("/c:")
False

In python 3.12

Python 3.12.7 (tags/v3.12.7:0b05ead, Oct  1 2024, 03:06:41) [MSC v.1941 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os.path
>>> os.path.isabs("/c:")
True

CPython versions tested on:

3.13

Operating systems tested on:

Windows

Activity

  1. ikappaki
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Oct 10, 2024
  2. ZeroIntensity
    added
    OS-windows
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    3.13only security fixesonly security fixes
    on Oct 11, 2024
  3. nineteendo commented on Oct 11, 2024

    @nineteendo
    nineteendo
    on Oct 11, 2024
    Contributor
    More actions

    Works as intended: #113829, maybe a new function could be considered to check if a path is rooted?

  4. ikappaki commented on Oct 11, 2024

    @ikappaki
    ikappaki
    on Oct 11, 2024
    Author
    More actions

    Works as intended: #113829, maybe a new function could be considered to check if a path is rooted?

    This behavior changes how os.path.isabs interacts with urllib.parse.urlparse when dealing with absolute paths in Windows URIs. In Python 3.12, paths parsed from local file URIs (drive and network paths) were recognized as absolute, but in Python 3.13, they no longer are

    import os.path
    import pathlib
    import urllib.parse
    
    >>> urllib.parse.urlparse(pathlib.Path('c:\\xyz').as_uri())
    ParseResult(scheme='file', netloc='', path='/c:/xyz', params='', query='', fragment='')
    >>> urllib.parse.urlparse(pathlib.Path('\\\\machine\\xyz').as_uri())
    ParseResult(scheme='file', netloc='machine', path='/xyz/', params='', query='', fragment='')

    In Python 3.12, os.path.isabs would correctly identify these paths as absolute, including network paths:

    >>> os.path.isabs(urllib.parse.urlparse(pathlib.Path('c:\\xyz').as_uri()).path)
    True
    >>> os.path.isabs(urllib.parse.urlparse(pathlib.Path('\\\\machine\\xyz').as_uri()).path)
    True

    but not any more in 3.13

    >>> os.path.isabs(urllib.parse.urlparse(pathlib.Path('c:\\xyz').as_uri()).path)
    False
    >>> os.path.isabs(urllib.parse.urlparse(pathlib.Path('\\\\machine\\xyz').as_uri()).path)
    False

    It seems as if os.path.isabs was never intended to be used with ParseResult paths. I suppose a more appropriate solution would be to directly check if the path starts with '/', which would indicate that it's absolute.

  5. nineteendo commented on Oct 11, 2024

    @nineteendo
    nineteendo
    on Oct 11, 2024
    Contributor
    More actions

    You can use pathlib.Path.from_uri() starting from 3.13:

    >>> import pathlib
    >>> pathlib.Path.from_uri(pathlib.Path('c:/xyz').as_uri())
    WindowsPath('c:/xyz')
    >>> pathlib.Path.from_uri(pathlib.Path('//server/drive/xyz').as_uri())
    WindowsPath('//server/drive/xyz')

    This doesn't roundtrip:

    >>> import pathlib
    >>> import urllib.parse
    >>> pathlib.Path(urllib.parse.urlparse(pathlib.Path('c:/xyz').as_uri()).path)
    WindowsPath('/c:/xyz')
    >>> pathlib.Path(urllib.parse.urlparse(pathlib.Path('//server/drive/xyz').as_uri()).path)
    WindowsPath('/drive/xyz')

    Also, aren't uri's always absolute?

  6. marc-hb commented on Oct 11, 2024

    @marc-hb
    marc-hb
    on Oct 11, 2024
    More actions

    Also, aren't uri's always absolute?

    Relative URLs work perfectly fine.

    EDIT: I meant in general in life, not related to Python.

  7. nineteendo commented on Oct 11, 2024

    @nineteendo
    nineteendo
    on Oct 11, 2024
    Contributor
    More actions

    Well, at least pathlib doesn't allow creating them.

  8. barneygale commented on Oct 11, 2024

    @barneygale
    barneygale
    on Oct 11, 2024
    Contributor
    More actions

    It seems as if os.path.isabs was never intended to be used with ParseResult paths. I suppose a more appropriate solution would be to directly check if the path starts with '/', which would indicate that it's absolute.

    Checking whether it starts with a / makes most sense to me. Another option is posixpath.isabs().

    Reacted by Nice Zombies
  9. nineteendo commented on Oct 11, 2024

    @nineteendo
    nineteendo
    on Oct 11, 2024
    Contributor
    More actions

    Use p.scheme and p.netloc and p.path.startswith("/") to check if an uri is absolute, an absolute path doesn't change when joined with another path:

    >>> import urllib.parse
    >>> urllib.parse.urljoin("file://netloc/foo/", "bar")
    'file://netloc/foo/bar'
    >>> urllib.parse.urljoin("file://netloc/foo/", "/bar")
    'file://netloc/bar'
    >>> urllib.parse.urljoin("file://netloc/foo/", "//netloc2/bar")
    'file://netloc2/bar'
    >>> urllib.parse.urljoin("file://netloc/foo/", "file://netloc2/bar")
    'file://netloc2/bar'
    

    That's also why we changed the behaviour of os.path.isabs():

    >>> import os.path
    >>> os.path.join(r"c:\foo", "bar")
    'c:\\foo\\bar'
    >>> os.path.join(r"c:\foo", r"\bar")
    'c:\\bar'
    >>> os.path.join(r"c:\foo", r"d:\bar")
    'd:\\bar'
    
    Reacted by Barney Gale and ikappaki
  10. nineteendo commented on Oct 11, 2024

    @nineteendo
    nineteendo
    on Oct 11, 2024
    Contributor
    More actions

    I think this can be closed.

    Reacted by Barney Gale
  11. barneygale commented on Oct 11, 2024

    @barneygale
    barneygale
    on Oct 11, 2024
    Contributor
    More actions

    Thanks @nineteendo! Closing.

    Reacted by Nice Zombies
  12. barneygale
    closed this as not plannedon Oct 11, 2024
  13. kayychou commented on Dec 3, 2024

    @kayychou
    kayychou
    on Dec 3, 2024
    More actions

    Works as intended: #113829, maybe a new function could be considered to check if a path is rooted?

    hi @nineteendo, @barneygale,

    the doc updated in #113829 still indicates the following behavior:

    Return ``True`` if *path* is an absolute pathname.  On Unix, that means it
    begins with a slash, on Windows that it begins with two (back)slashes, or a
    drive letter, colon, and (back)slash together.
    

    whereas the intended behavior, as illustrated in Lib/test/test_ntpath.py, appears to be now :

    >>> os.path.isabs("/foo/bar") # path beginning with a slash on windows
    False
    >>> os.path.isabs("\\foo\\bar") # path beginning with two backslashes on windows
    False
    

    maybe I'm missing something under the hood

    Thanks for your help!

  14. barneygale commented on Dec 3, 2024

    @barneygale
    barneygale
    on Dec 3, 2024
    Contributor
    More actions

    Hey @kayychou - "\\foo\\bar" expresses a string that begins with a single backslash. If you want two backslashes, you could use a raw string (r"\\foo\bar") or double the backslashes ("\\\\foo\\bar")

    For more info: https://docs.python.org/3/reference/lexical_analysis.html#escape-sequences

    Reacted by Nice Zombies and kayychou
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.13only security fixesonly security fixesOS-windowsstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-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.