-
Notifications
You must be signed in to change notification settings - Fork 156
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
File-like API is inconsistent with built-in file-like objects #673
Comments
I can't reproduce the issue you describe with my own bucket.
Is test.txt of nonzero length? |
Here's a full self contained example: import io
from google.cloud import storage
bucket = "foobarbaz"
client = storage.Client()
bucket = client.bucket(bucket_name=bucket)
data = b""
# create file
with open("test.txt", mode="wb") as f:
f.write(data)
bucket.blob("test.txt").upload_from_file(open("test.txt", mode="rb"))
# compare
with open("test.txt", mode="rb") as f:
f.seek(1, io.SEEK_CUR)
res = f.tell()
assert f.tell() == 1, res
with bucket.blob("test.txt").open(mode="rb") as f:
f.seek(1, io.SEEK_CUR)
res = f.tell()
assert f.tell() == 0, res # passes but shouldn't
assert f.tell() == 1, res # fails And indeed this particular discrepancy is only reproducible with an empty file. |
@andrewsg does that example reproduce for you? |
Hi @adriangb, was on vacation previously, taking a look this week. Thanks! |
No problem, but also just FYI this probably should be low priority, it's not impacting our work directly and I doubt anyone else is impacted by it in a way they can't easily work around. |
Got it. I believe resolving #462 should take care of a lot of the problems you encountered with the state machine test, though I'm not yet sure how it will impact the zero-length file issue. I think adding the state machine test or something like it is a good idea and will revisit it once that other bug is closed. Thank you! |
I have found a new inconsistent behavior between this library and the standard library. Here is an example: import io
from google.cloud import storage
bucket = "foobarbaz"
client = storage.Client()
bucket = client.bucket(bucket_name=bucket)
data = b"01234"
# create file
with open("test.txt", mode="wb") as f:
f.write(data)
bucket.blob("test.txt").upload_from_file(open("test.txt", mode="rb"))
# compare
with open("test.txt", mode="rb") as f:
# access
try:
f.seek(-1, io.SEEK_SET)
raise OSError
except OSError as err:
assert err.errno == 22
assert f.tell() == 0
assert f.seek(10, io.SEEK_SET) == 10
with bucket.blob("test.txt").open(mode="rb") as f:
try:
f.seek(-1, io.SEEK_SET) # expect OSError, but pass
raise OSError
except OSError as err:
assert err.errno == 22
assert f.tell() == 0
assert f.seek(10, io.SEEK_SET) == 10 # expect 10, but return 5 I too think that the behavior of objects should be consistent as much as possible. |
@funera1 As OSErrors are raised by the OS, and there is normally no need for a Python program to intentionally raise an OSError, I think I will decline to change this behavior. If it were a ValueError, then there would be an issue with Python code behaving differently from other Python code. But an OSError simply reflects the reality that one type of file-like object is handled by the OS and one is handled in Python. |
I understand. Thanks for the reply. |
Python's file-like object protocol is not very well documented, and there are a lot of edge cases / undefined behavior that lead to arbitrary outcomes. It seems like in at least some of these scenarios, the implementation of file-like objects in this library does not conform with what file-like objects from the standard library do. Here is an example:
It would be nice to get this inconsistencies aligned where possible. For S3 at least, it is possible to write a wrapper that uses range headers and such to get a 100% compatible API.
For a case like this, I think state machine testing works nicely.
Here's an implementation outline using hypothesis:
The text was updated successfully, but these errors were encountered: