Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-74453: Deprecate os.path.commonprefix#144436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
sethmlarson wants to merge6 commits intopython:main
base:main
Choose a base branch
Loading
fromsethmlarson:deprecate-os-path-commonprefix

Conversation

@sethmlarson
Copy link
Contributor

@sethmlarsonsethmlarson commentedFeb 3, 2026
edited by github-actionsbot
Loading

Follow-up from#144401, this PR moves to deprecateos.path.commonprefix() in favor of the correctly behavingos.path.commonpath() and the behavior-describingstring.commonprefix().

I'm not sure if this is all I have to do to deprecate an API, if there is more documentation that needs to happen let me know.


📚 Documentation preview 📚:https://cpython-previews--144436.org.readthedocs.build/

Copy link
Member

@picnixzpicnixz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You need a What's New entry for that.

Comment on lines 61 to 62
import os
m = tuple(map(os.fspath, m))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I'm not really fond of this. string.commonprefix() should be specific to strings and should not care about pathlike objects.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yeah, this is only done for backwards compatibility. I would be happy to get rid of it, but I figured that this would be not allowed considering we're doing a "rename", not a new API.

hugovk reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

There is no backwards compatibility here. We create a new function in a module that is not related to filepaths at all. I do not consider this as a rename, I really consider this as a new API. Instead, I would keep the implementation ofos.path.commonpath as is and add in a follow-up PRstring.commonprefix which does not do the fspath computation. We then document that os.path.commonpath should be reimplemented asstring.commonprefix(tuple(map(os.fspath, m))) if needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I believe this newstring.commonprefix() should be a direct, one-to-one, drop-in replacement for the oldos.path.commonprefix().

We're not doing anyone favours by changing the behaviour and making them [have to decide whether they need to] jump through extra hoops.

Chances are they should be usingos.path.commonpath() instead, but if not, let them just replace the module name and keep the same old behaviour.

I doubt there's significant performance improvement from changing it either.

sethmlarson reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

For me this isn't about performance, it's about semantics.string contains string-related utilities, not path-related ones. I am really opposed to havingstring.commonprefix being smart here. I know that we are not necessarily doing the user a favor but I don't want to have unrelated utilities instring. It is, for me, the wrong module for that.

Copy link
Member

@hugovkhugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Please also list inDoc/deprecations/pending-removal-in-future.rst.

https://docs.python.org/dev/deprecations/index.html#pending-removal-in-future-versions

sethmlarson reacted with thumbs up emoji
Comment on lines 61 to 62
import os
m = tuple(map(os.fspath, m))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I believe this newstring.commonprefix() should be a direct, one-to-one, drop-in replacement for the oldos.path.commonprefix().

We're not doing anyone favours by changing the behaviour and making them [have to decide whether they need to] jump through extra hoops.

Chances are they should be usingos.path.commonpath() instead, but if not, let them just replace the module name and keep the same old behaviour.

I doubt there's significant performance improvement from changing it either.

sethmlarson reacted with thumbs up emoji
sethmlarsonand others added2 commitsFebruary 3, 2026 12:28
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
@sethmlarson
Copy link
ContributorAuthor

Alright, most recent two commits should address all review comments. I have preserved backwards compatibility in the drop-in replacementstring.commonprefix().

hugovk reacted with thumbs up emoji

@sethmlarsonsethmlarson requested review fromhugovk andpicnixz and removed request forpicnixzFebruary 3, 2026 18:33
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Copy link
Member

@picnixzpicnixz left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I am sorry, but I do not wantstring.commonprefix to be equivalent toos.path.commonprefix. Semantically it doesn't make sense to have an os-related utility instring.

In addition, we only talk about "strings" in the documentation. Having an implicitos.fspath conversion should be documented otherwise. If we want to mimicos.path.commonpath in the first place, I do not see why we can't just keep it but soft-deprecate it.

Note thatcommonprefix does not care about the fact that we are strings. It also works forany sequence, as long as the elements can be ordered (e.g., we can usecommonprefix for list of lists):

>>>os.path.commonpath([[1], [1,3]])[1]

Since we expose it instring, anyone using a non-string as the first argument willnot be able to make it work (because we raise a TypeError inos.fspath). So I would expect a string-like object to be acceptable but because ofos.fspath it wouldn't be. This would be contrary to what thestring module stands for.

If we want a commonprefix utility, I would suggest adding one toitertools, and use the latter. I believe it makes more sense to have something related tocommonprefix out there. Or for strings only, have it indifflib.

@bedevere-app
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phraseI have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

And if you don't make the requested changes, you will be put in the comfy chair!

@sethmlarson
Copy link
ContributorAuthor

Because I want to prioritize warning users about this function, I am okay with not providing astring.commonprefix() function and simply raising aDeprecationWarning in this PR. I want to avoid this warning getting delayed further, as has happened for the past ~30 years since the confusing behavior has been reported.

sethmlarsonand others added2 commitsFebruary 3, 2026 21:56
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
@sethmlarsonsethmlarsonforce-pushed thedeprecate-os-path-commonprefix branch fromd4c0bb4 to166c39dCompareFebruary 3, 2026 23:06
@sethmlarson
Copy link
ContributorAuthor

sethmlarson commentedFeb 3, 2026
edited
Loading

@picnixz@hugovk I have removedstring.commonprefix in166c39d, I will happily revert or change this if there is a suggestion that should be completed in this PR.

(I have made the requested changes; please review again)

Comment on lines 36 to +38
deftest_commonprefix(self):
commonprefix=self.pathmodule.commonprefix
self.assertEqual(
commonprefix([]),
""
)
self.assertEqual(
commonprefix(["/home/swenson/spam","/home/swen/spam"]),
"/home/swen"
)
self.assertEqual(
commonprefix(["/home/swen/spam","/home/swen/eggs"]),
"/home/swen/"
)
self.assertEqual(
commonprefix(["/home/swen/spam","/home/swen/spam"]),
"/home/swen/spam"
)
self.assertEqual(
commonprefix(["home:swenson:spam","home:swen:spam"]),
"home:swen"
)
self.assertEqual(
commonprefix([":home:swen:spam",":home:swen:eggs"]),
":home:swen:"
)
self.assertEqual(
commonprefix([":home:swen:spam",":home:swen:spam"]),
":home:swen:spam"
)

self.assertEqual(
commonprefix([b"/home/swenson/spam",b"/home/swen/spam"]),
b"/home/swen"
)
self.assertEqual(
commonprefix([b"/home/swen/spam",b"/home/swen/eggs"]),
b"/home/swen/"
)
self.assertEqual(
commonprefix([b"/home/swen/spam",b"/home/swen/spam"]),
b"/home/swen/spam"
)
self.assertEqual(
commonprefix([b"home:swenson:spam",b"home:swen:spam"]),
b"home:swen"
)
self.assertEqual(
commonprefix([b":home:swen:spam",b":home:swen:eggs"]),
b":home:swen:"
)
self.assertEqual(
commonprefix([b":home:swen:spam",b":home:swen:spam"]),
b":home:swen:spam"
)

testlist= ['','abc','Xbcd','Xb','XY','abcd',
'aXc','abd','ab','aX','abcX']
fors1intestlist:
fors2intestlist:
p=commonprefix([s1,s2])
self.assertStartsWith(s1,p)
self.assertStartsWith(s2,p)
ifs1!=s2:
n=len(p)
self.assertNotEqual(s1[n:n+1],s2[n:n+1])
withwarnings_helper.check_warnings((".*commonpath().*",DeprecationWarning)):
commonprefix=self.pathmodule.commonprefix
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

May I suggest that you have:

deftest_commonprefix(self):withwarnings_helper...:self.do_test_commonprefix()defdo_test_commonprefix(self):# the original test

That way, the diff will be smaller

@@ -298,12 +299,13 @@ def test_isabs(self):
tester('ntpath.isabs("\\\\.\\C:")', 1)

def test_commonprefix(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Ditto

Comment on lines +26 to +32
m=sorted(m)
prefix=m[0]
foriteminm[1:]:
foriinrange(len(prefix)):
ifitem[i]!=prefix[i]:
prefix=prefix[:i]
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Can we use the min/max + enumerate approach instead?

s='%s[%d chars]%s'% (s[:prefixlen],skip,s[len(s)-suffixlen:])
returns

def_commonprefix(m,/):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
def_commonprefix(m,/):
def_commonprefix(m):

as it's private, no need to enforce the /

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@picnixzpicnixzpicnixz requested changes

@hugovkhugovkhugovk approved these changes

@vstinnervstinnerAwaiting requested review from vstinner

@StanFromIrelandStanFromIrelandAwaiting requested review from StanFromIreland

Assignees

No one assigned

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

4 participants

@sethmlarson@hugovk@picnixz@StanFromIreland

[8]ページ先頭

©2009-2026 Movatter.jp