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 — Respect `os.Pathlike` by George-Ogden · Pull Request #2086 · gitpython-developers/GitPython

Conversation

@George-Ogden

@George-Ogden George-Ogden commented Nov 27, 2025

Copy link
Copy Markdown
Contributor

Fixes #2085
Replaces instances of str(path) with path.__fspath__() for more general usage.
I also moved the clone tests into a separate file that existed before but only contained a single test.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
George-Ogden added 5 commits November 27, 2025 17:32
@George-Ogden
Move clone tests into dedicated file
e3f38ff
@George-Ogden
Allow Pathlike urls and destinations when cloning
24abf10
@George-Ogden
Simplify logic with direct path conversion
ad1ae5f
@George-Ogden
Allow Pathlike paths when creating a git repo
5d26325
@George-Ogden
Fix missing path conversion
59c3c80
@George-Ogden

George-Ogden commented Nov 27, 2025

Copy link
Copy Markdown
Contributor Author

Also, I notice you skip mypy because it produces errors. Why not pin the version and increment it periodically?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron
Byron requested a review from Copilot November 28, 2025 06:44
Copilot started reviewing on behalf of Byron November 28, 2025 06:45
View session
Copilot finished reviewing on behalf of Byron November 28, 2025 06:45
@Byron

Byron commented Nov 28, 2025

Copy link
Copy Markdown
Member

That's a great incentive, thanks so much! Using __fspath__() seems like it's using a private API, so it looks strange to my untrained eye. But if it's correct, I guess it's worth doing anyway?

Also, I notice you skip mypy because it produces errors. Why not pin the version and increment it periodically?

I don't see why this wouldn't work, great idea! Please feel free to set this up in your next PR :).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron
Byron requested review from Copilot and removed request for Copilot November 28, 2025 07:00
Copilot started reviewing on behalf of Byron November 28, 2025 07:00
View session
Copilot finished reviewing on behalf of Byron November 28, 2025 07:00
@Byron

Byron commented Nov 28, 2025

Copy link
Copy Markdown
Member

It seems that I won't get my copilot review here, so I wonder why you'd not be calling os.fspath(path) instead?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron Byron added the waiting for feedback label Nov 28, 2025
@George-Ogden
Use os.fspath instead of __fspath__ for reading paths
91d4cc5
@George-Ogden

George-Ogden commented Nov 28, 2025

Copy link
Copy Markdown
Contributor Author

It seems that I won't get my copilot review here, so I wonder why you'd not be calling os.fspath(path) instead?
I agree that's much nicer and also gets rid of the if not isinstance(path, str) checks.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden

George-Ogden commented Nov 28, 2025

Copy link
Copy Markdown
Contributor Author

I don't see why this wouldn't work, great idea! Please feel free to set this up in your next PR :).

Sure thing

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Copilot AI reviewed Nov 28, 2025

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
George-Ogden added 3 commits November 28, 2025 21:28
@George-Ogden
Replace extra occurrences of str with fspath
0414bf7
@George-Ogden
Convert paths in constructors and large function calls
3801505
@George-Ogden
Fix union type conversion to path
086e832
Byron
Byron requested changes Nov 29, 2025
View reviewed changes

@Byron Byron left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

This looks better indeed.
Something I think will be desirable is to actually add tests for non-decodable paths for the functions/types that are affected. Otherwise, how do we know it's working?

Feel free to use AI for that, it's quite good at this usually.

The idea is to prove that the changes actually make something possible that wasn't possible before.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread git/repo/base.py
# When pathlib.Path or other class-based path is passed
if not isinstance(path, str):
path = str(path)
url = os.fspath(url)

@Byron Byron Nov 29, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

URL is not a path though.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@George-Ogden George-Ogden Nov 29, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Here, url can be a path if you're cloning a local repo, and if it's not os.fspath will leave strings alone.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@Byron
Byron requested a review from Copilot November 29, 2025 10:00
Copilot started reviewing on behalf of Byron November 29, 2025 10:01
View session
Copilot finished reviewing on behalf of Byron November 29, 2025 10:02
Copilot AI reviewed Nov 29, 2025
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread git/index/util.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread git/refs/symbolic.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread git/refs/symbolic.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

George-Ogden and others added 2 commits November 29, 2025 11:56
@George-Ogden
Use converted file path
b3908ed
Co-authored-by: Copilot <[email protected]>
@George-Ogden
Remove redundant fspath
50aea99
Co-authored-by: Copilot <[email protected]>
@George-Ogden
Remove redundant str call
1722561
@George-Ogden

George-Ogden commented Nov 29, 2025

Copy link
Copy Markdown
Contributor Author

I've added a few tests, but lots of the calls work on internal APIs, so they won't make much difference. In these cases, calling os.fspath is still better as it makes the intention clearer. I also made a tool to check for redundant uses and the only one is git/util.py:420.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden
Limit mypy version due to Cygwin errors
921ca8a
Byron
Byron reviewed Nov 29, 2025
View reviewed changes

@Byron Byron left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

That's great, thanks a lot!

What should be shown in the tests is that it can now handle filepaths that don't decode with the standard encoding.

Candidate tests are:

  • clone from a filesystem path
  • index.add with a strange path
  • and probably more - you could intentionally break a piece of code that changed fspath and see which tests fail, then it's clear where to add a test with a 'special' path.

Thanks for making this happen, and thanks for your understanding - we can't just make changes hoping it will work or doesn't make things work, but there must be real evidence that this is desirable. And we can only have that with tests that fail without this change.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread git/repo/base.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

George-Ogden added 3 commits November 29, 2025 20:21
@George-Ogden
Merge branch 'main' into true-pathlike
b5abe0f
@George-Ogden
Validate every fspath with tests
12e15ba
@George-Ogden
Fix type hints
8434967
@Byron Byron removed the waiting for feedback label Nov 30, 2025
@Byron
Byron marked this pull request as draft November 30, 2025 08:44
@Byron

Byron commented Nov 30, 2025

Copy link
Copy Markdown
Member

I am putting the PR back to draft until there are tests that use the new "can handle paths encoding independently from the runtime encoding" to prove the changes are effective. Thanks again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden

George-Ogden commented Nov 30, 2025

Copy link
Copy Markdown
Contributor Author

Sorry, I meant to add this comment with the changes I made yesterday:
I've gone through all the changes and made sure that they apply (and removed the ones that didn't). As a result, there are more tests for submodules and index, as well as the existing ones I added.

For example, the clone_from_pathlike test means that all the fs.path conversions in Repo.base are required and removing them will cause that test to fail. Is that what you mean by "can handle paths encoding independently from the runtime encoding"? If not, I can add tests that will do that.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron

Byron commented Dec 1, 2025

Copy link
Copy Markdown
Member

No problem!

What I mean is that the point of this conversion is to prevent decoding issues related to paths. I.e. the user passes a filesystem path, but internally GitPython runs str() on it which then tries to re-encode the path-bytes to the python runtime default encoding. This typically fails as soon as there is one non-ascii character.

You'd have to go back to main and add such tests which should fail, to then show that this now works with the changes in this branch, for a particular scenario - like one of the ones I mentioned, but there might be more.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden
Add tests with non-ascii characters
1710626
@George-Ogden

George-Ogden commented Dec 1, 2025

Copy link
Copy Markdown
Contributor Author

I've added some non-ASCII characters into the tests. However, the main point of the pull request is with objects that follow the os.Pathlike type hint, such as this:

import os
from dataclasses import dataclass

@dataclass
class CustomPathlike:
    path: str
    def __fspath__(self) -> str:
        return self.path

custom_pathlike = CustomPathlike("folder/file")
str(custom_pathlike) # "CustomPathlike(path='folder/file')" - fails in "git add CustomPathlike(path='folder/file')"
os.fspath(custom_pathlike) # "folder/file"  - works in "git add folder/file"

I realise that that was unclear in both the PR and the original issue (so I've added this example to the original issue).

Byron reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron

Byron commented Dec 2, 2025

Copy link
Copy Markdown
Member

Thanks a lot, this definitely helped me understand that these changes aren't meant to address that one thing I thought they do 😅.

My feeling is that the added tests don't actually fail on master, and thus should be removed. But if they do, please feel free to put them into a separate PR so I see them failing.
Either way, once I hear from you I think the PR can be merged.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden George-Ogden mentioned this pull request Dec 2, 2025
Failing Path Tests #2088
Closed
@George-Ogden

George-Ogden commented Dec 2, 2025

Copy link
Copy Markdown
Contributor Author

See #2088 for failing tests

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden
George-Ogden marked this pull request as ready for review December 2, 2025 08:56
@Byron

Byron commented Dec 2, 2025

Copy link
Copy Markdown
Member

Thanks for giving it a shot. Admittedly, @2088 is surprisingly complex and fails in more places than just the two I thought it would fail in. To my mind, a cherry-pick of 1710626 onto master would have done the trick (or a manual port of these tests), instead there is a lot of new commits.

Do you want to try again, or remove the added tests here in absence of a demonstration of failure?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden George-Ogden mentioned this pull request Dec 2, 2025
Failing Pathlike Tests #2089
Closed
@George-Ogden

George-Ogden commented Dec 2, 2025

Copy link
Copy Markdown
Contributor Author

I've done that in #2089

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron

Byron commented Dec 4, 2025

Copy link
Copy Markdown
Member

Thanks a lot for your patience, just one more thing: 1710626 adds tests which I believe should have shown that they won't work on master, but work here. The idea is that the encoding of the files can't be determined if Python would try to decode them, which a lot of code here does.

If you don't feel like this has a chance to be fixed, then I think these tests can be removed by force-pushing without this commit for this PR to be merged. Otherwise, there can be a PR on master that shows how these two tests are failing because of some decoding issue, and this PR will be merged as well.

Thank you, and… we will get there :).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden

George-Ogden commented Dec 4, 2025

Copy link
Copy Markdown
Contributor Author

However, both

GitPython/test/test_clone.py

Lines 86 to 98 in 1710626

def test_clone_from_with_path_contains_unicode(self):
with tempfile.TemporaryDirectory() as tmpdir:
unicode_dir_name = "\u0394"
path_with_unicode = os.path.join(tmpdir, unicode_dir_name)
os.makedirs(path_with_unicode)
try:
Repo.clone_from(
url=self._small_repo_url(),
to_path=path_with_unicode,
)
except UnicodeEncodeError:
self.fail("Raised UnicodeEncodeError")

and

GitPython/test/test_index.py

Lines 985 to 994 in 0fcf291

def test_add_utf8P_path(self, rw_dir):
# NOTE: fp is not a Unicode object in Python 2
# (which is the source of the problem).
fp = osp.join(rw_dir, "ø.txt")
with open(fp, "wb") as fs:
fs.write("content of ø".encode("utf-8"))
r = Repo.init(rw_dir)
r.index.add([fp])
r.index.commit("Added orig and prestable")

Ran on main successfully (and were included before this PR)

The difference in

GitPython/test/test_index.py

Lines 1216 to 1222 in 1710626

def test_index_add_pathlike_unicode(self, rw_repo):
git_dir = Path(rw_repo.git_dir)
file = git_dir / "file-áēñöưḩ̣.txt"
file.touch()
rw_repo.index.add(PathLikeMock(str(file)))

which fails on main is that the path is wrapped in a PathLikeMock, which has an interface similar to the one described above:

GitPython/test/lib/helper.py

Lines 55 to 60 in 1710626

@dataclass
class PathLikeMock:
path: str
def __fspath__(self) -> str:
return self.path

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron

Byron commented Dec 5, 2025

Copy link
Copy Markdown
Member

I see, thanks for clarifying and digging out the non-unicode tests on main which have been there before and seemed to be working already.

Then I even more so think that the tests in 1710626 as duplicates of the tests above serve no purpose. The PathLike test is already done.
What am I missing?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden
Revert "Add tests with non-ascii characters"
0cb55fb
This reverts commit 1710626.
@George-Ogden

George-Ogden commented Dec 5, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

All reverted! I agree that the tests don't add much.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron

Byron commented Dec 6, 2025

Copy link
Copy Markdown
Member

Alright, let's do this!
Thanks for bearing with me here.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron
Byron merged commit eecc28d into gitpython-developers:main Dec 6, 2025
27 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@George-Ogden

George-Ogden commented Dec 6, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Thanks, that's great 🥳. Can you release a new version please?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Byron

Byron commented Dec 7, 2025

Copy link
Copy Markdown
Member

I will do this at the end of the year, time for more fixes and features to be collected.

George-Ogden reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

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

Reviewers

@Byron Byron Byron requested changes
Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Pathlike type hint is not respected

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@George-Ogden @Byron
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.