Skip to content

bpo-37144: Convert path-like object to regular path #13817

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from

Conversation

0x29a
Copy link
Contributor

@0x29a 0x29a commented Jun 4, 2019

Steps to reproduce the issue:

  1. Create gzipped tar.
echo "test" > test
tar -cvzf test.tar.gz test
  1. Try to pass path-like object in tarfile.open:
import tarfile
import pathlib
path = pathlib.Path('test.tar.gz')
tarfile.open(path, 'w|gz')

Result will be:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/tarfile.py", line 1599, in open
    stream = _Stream(name, filemode, comptype, fileobj, bufsize)
  File "/usr/lib/python3.6/tarfile.py", line 382, in __init__
    self._init_write_gz()
  File "/usr/lib/python3.6/tarfile.py", line 430, in _init_write_gz
    if self.name.endswith(".gz"):
AttributeError: 'PosixPath' object has no attribute 'endswith'

https://bugs.python.org/issue37144

Lib/tarfile.py Outdated
@@ -349,7 +349,7 @@ def __init__(self, name, mode, comptype, fileobj, bufsize):
fileobj = _StreamProxy(fileobj)
comptype = fileobj.getcomptype()

self.name = name or ""
self.name = os.path.abspath(name) if name else ""
Copy link
Member

Choose a reason for hiding this comment

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

os.fspath looks like a good solution to me. Please add a test in Lib/test/test_tarfile.py that opens gzipname with mode 'w|gz' flag to make sure there is no AttributeError

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tirkarthi after opening gzipname with mode w|gz all remaining tests, that need to extract data from gzipname will not pass, because opening rewrites file content.

I added test to StreamWriteTest class, where I open for write tmpname, because it's designed for writing and insensitive to content change. Also, since this test inside of StreamWriteTest, opening by path-like filename will be performed for each mode (gz, lz, bz).

@0x29a 0x29a force-pushed the fix-issue-37144 branch from cab805b to dd30c0d Compare June 5, 2019 01:48
Lib/tarfile.py Outdated
@@ -1468,7 +1468,7 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None,
if hasattr(fileobj, "mode"):
self._mode = fileobj.mode
self._extfileobj = True
self.name = os.path.abspath(name) if name else None
self.name = os.fspath(name) if name else None
Copy link
Contributor

Choose a reason for hiding this comment

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

these lines are not equal.
The correct code should be something like:

name = os.fspath(name)
self.name = os.path.abspath(name)

I've skipped the check for empty/None name.

Lib/tarfile.py Outdated
@@ -1943,7 +1943,7 @@ def add(self, name, arcname=None, recursive=True, *, filter=None):
arcname = name

# Skip if somebody tries to archive the archive...
if self.name is not None and os.path.abspath(name) == self.name:
if self.name is not None and os.fspath(name) == self.name:
Copy link
Contributor

Choose a reason for hiding this comment

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

the same

@bedevere-bot
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 phrase I 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.

@@ -1421,6 +1421,11 @@ def test_file_mode(self):
finally:
os.umask(original_umask)

def test_open_by_path_object(self):
# Test for issue #37144: broken open for stream write by path-like object
tar = tarfile.open(pathlib.Path(tmpname), self.mode)
Copy link
Member

Choose a reason for hiding this comment

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

You can use a context manager that automatically calls close on the object.

with tarfile.open(pathlib.Path(tmpname), self.mode) as f:
	pass

@0x29a
Copy link
Contributor Author

0x29a commented Jun 5, 2019

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@asvetlov: please review the changes made to this pull request.

@@ -1421,6 +1421,11 @@ def test_file_mode(self):
finally:
os.umask(original_umask)

def test_open_by_path_object(self):
# Test for issue #37144: broken open for stream write by path-like object
Copy link
Contributor

@asvetlov asvetlov Jun 5, 2019

Choose a reason for hiding this comment

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

Too long line as well.
Please break it into the two-lines comment.
The comment is valuable, thanks

@bedevere-bot
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 phrase I 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.

Lib/tarfile.py Outdated
@@ -1943,7 +1945,7 @@ def add(self, name, arcname=None, recursive=True, *, filter=None):
arcname = name

# Skip if somebody tries to archive the archive...
if self.name is not None and os.path.abspath(name) == self.name:
if self.name is not None and os.path.abspath(os.fspath(name)) == self.name:
Copy link
Contributor

Choose a reason for hiding this comment

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

Please move os.fspath(name) to the very beginning of the function, just after self._check(...).

@0x29a 0x29a force-pushed the fix-issue-37144 branch from 3f02bda to 82882dd Compare June 6, 2019 15:20
@0x29a
Copy link
Contributor Author

0x29a commented Jun 6, 2019

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@asvetlov: please review the changes made to this pull request.

Lib/tarfile.py Outdated
@@ -1468,6 +1468,8 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None,
if hasattr(fileobj, "mode"):
self._mode = fileobj.mode
self._extfileobj = True

name = os.fspath(name) if name else None
Copy link
Contributor

@asvetlov asvetlov Jun 7, 2019

Choose a reason for hiding this comment

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

Move this line before if not fileobj: the code calls os.path.exists() and bltn_open() with name.

Both functions acceptpathlib.Path object but let's be consistent in Path -> str conversion, please

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@asvetlov
Oh, finally I got It. Updated.

@bedevere-bot
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 phrase I 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.

@asvetlov
Copy link
Contributor

asvetlov commented Jun 7, 2019

Now looks much better!

After briefly looking in tarfile.py I see that gettarinfo(), extractall, extract, _getmember should convert their name and path arguments too.

@@ -1368,7 +1368,7 @@ def write(self, data):

f = BadFile()
with self.assertRaises(exctype):
tar = tarfile.open(tmpname, self.mode, fileobj=f,
tarfile.open(tmpname, self.mode, fileobj=f,
format=tarfile.PAX_FORMAT,
pax_headers={'non': 'empty'})
Copy link
Contributor

Choose a reason for hiding this comment

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

These two arguments should be indented under tmpname.

Copy link
Member

Choose a reason for hiding this comment

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

you need to keep the same indent.

@@ -1468,6 +1469,7 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None,
if hasattr(fileobj, "mode"):
self._mode = fileobj.mode
self._extfileobj = True

Copy link
Member

Choose a reason for hiding this comment

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

remove this line, we have to get a minimalist diff for the merge. Thank you

@@ -1368,7 +1368,7 @@ def write(self, data):

f = BadFile()
with self.assertRaises(exctype):
tar = tarfile.open(tmpname, self.mode, fileobj=f,
tarfile.open(tmpname, self.mode, fileobj=f,
format=tarfile.PAX_FORMAT,
pax_headers={'non': 'empty'})
Copy link
Member

Choose a reason for hiding this comment

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

you need to keep the same indent.

@@ -1421,6 +1421,12 @@ def test_file_mode(self):
finally:
os.umask(original_umask)

def test_open_by_path_object(self):
# Test for issue #37144:
Copy link
Member

Choose a reason for hiding this comment

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

remove these comments.

@csabella
Copy link
Contributor

@0x29a, please address the code reviews. Thank you!

@0x29a 0x29a closed this Oct 1, 2023
@0x29a 0x29a deleted the fix-issue-37144 branch October 1, 2023 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants