-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix: resolved Windows file permission error #3269
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,12 @@ | |
| from tempfile import NamedTemporaryFile | ||
| from hashlib import sha1 | ||
|
|
||
| from urllib.parse import urlparse | ||
| try: | ||
| # Python 3 | ||
| from urllib.parse import urlparse | ||
| except ImportError: | ||
| # Python 2 | ||
| from urlparse import urlparse | ||
|
|
||
| from metaflow.datastore import FlowDataStore | ||
| from metaflow.datastore.content_addressed_store import BlobCache | ||
|
|
@@ -24,6 +29,22 @@ | |
|
|
||
| NEW_FILE_QUARANTINE = 10 | ||
|
|
||
| if sys.version_info[0] >= 3: | ||
| _replace = os.replace | ||
| else: | ||
| import errno | ||
|
|
||
| def _replace(src, dst): | ||
| try: | ||
| os.rename(src, dst) | ||
| except OSError as e: | ||
| if e.errno == errno.EEXIST or (os.name == "nt" and e.errno in (13, 17)): | ||
| os.remove(dst) | ||
| os.rename(src, dst) | ||
| else: | ||
| raise | ||
|
Comment on lines
+32
to
+45
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The |
||
|
|
||
|
|
||
| if sys.version_info[0] >= 3 and sys.version_info[1] >= 2: | ||
|
|
||
| def od_move_to_end(od, key): | ||
|
|
@@ -113,7 +134,8 @@ def get_log_legacy( | |
|
|
||
| log = task_ds.load_log_legacy(logtype, attempt_override=attempt) | ||
| # Store this in the file cache as well | ||
| self.create_file(path, log) | ||
| if log is not None: | ||
| self.create_file(path, log) | ||
| return log | ||
|
|
||
| def get_legacy_log_size( | ||
|
|
@@ -263,16 +285,22 @@ def create_file(self, path, value): | |
| dirname = os.path.dirname(path) | ||
| try: | ||
| FileCache._makedirs(dirname) | ||
| except: # noqa E722 | ||
| except Exception: # noqa E722 | ||
| raise FileCacheException("Could not create directory: %s" % dirname) | ||
| tmpfile = NamedTemporaryFile(dir=dirname, prefix="dlobj", delete=False) | ||
| # Now write out the file | ||
| try: | ||
| tmpfile.write(value) | ||
| tmpfile.flush() | ||
| os.rename(tmpfile.name, path) | ||
| except: # noqa E722 | ||
| os.unlink(tmpfile.name) | ||
| os.fsync(tmpfile.fileno()) | ||
| tmpfile.close() | ||
|
|
||
| _replace(tmpfile.name, path) | ||
|
|
||
| except Exception: # noqa E722 | ||
| tmpfile.close() | ||
| if os.path.exists(tmpfile.name): | ||
| os.unlink(tmpfile.name) | ||
|
Comment on lines
+300
to
+303
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
| raise | ||
| size = os.path.getsize(path) | ||
| self._total += size | ||
|
|
@@ -305,8 +333,8 @@ def _index_objects(self): | |
| sha, ext = os.path.splitext(obj) | ||
| if ext in ["cached", "blob"]: | ||
| path = os.path.join(root, obj) | ||
| objects.insert( | ||
| 0, (os.path.getctime(path), os.path.getsize(path), path) | ||
| objects.append( | ||
| (os.path.getctime(path), os.path.getsize(path), path) | ||
| ) | ||
|
|
||
| self._total = sum(size for _, size, _ in objects) | ||
|
|
||
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.
urlparsefallback unreachableMetaflow requires Python 3.6+, so the
except ImportErrorbranch importingfrom urlparse import urlparsecan never execute. The original single-line import was correct. This try/except adds noise without benefit.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
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.
The duplicate
tmpfile.close()is required. If an i/p exception occurs during write(), flush(), or fsync(), the file is never closed in the try block.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.
Your comment seems to be addressing a different change than what my comment was about — I flagged the
urlparsetry/except as dead code (since Metaflow requires Python 3.6+), while you're discussing thetmpfile.close()in theexceptblock ofcreate_file.On the
tmpfile.close()point: you're correct. Ifwrite(),flush(), orfsync()raises, thetmpfile.close()inside thetryblock is never reached, so the handle would leak without the one inexcept. That's a valid and necessary pattern.My original comment stands separately — the
urlparsetry/except wrappingfrom urllib.parse import urlparseis still unreachable dead code given Metaflow's Python 3.6+ requirement, and the original single-line import was fine.Tip: You can customize Greptile's behavior for this repo with
.greptile/rules.mdand.greptile/config.json.