Skip to content

Install script: Windows-compatible cleanup path. #16928

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

Merged
merged 3 commits into from
Jul 8, 2024
Merged

Conversation

criemen
Copy link
Collaborator

@criemen criemen commented Jul 8, 2024

Windows might need some retrying around deleting
the target directory.

Windows might need some retrying around deleting
the target directory.
@criemen criemen requested a review from redsun82 July 8, 2024 14:28
Copy link
Contributor

@redsun82 redsun82 left a comment

Choose a reason for hiding this comment

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

I think there's a bug in the current code, or am I missing something?

if platform.system() == 'Windows':
# On Windows we might have virus scanner still looking at the path so
# attempt removal a couple of times sleeping between each attempt.
for attempt in [1, 2]:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there's a bug here:

  1. we enter the loop with attempt == 1.
  2. we try rmtree. Let's suppose we fail with winerror == 32
  3. we sleep 1s
  4. we reenter the loop with attempt == 2.
  5. we try rmtree again. Let's suppose we fail again with winerror == 32
  6. we sleep for 2s, but then...
  7. ...we exit the loop and we move on, having silently failed to remove the directory, and having slept 2s for no reason

we need to do a final rmtree after the for unless we succeeded. We could do that by adding a

else:
   shutil.rmtree(destdir)

after the for loop, but I know not all are comfortable with the for: ... else: ... construct (else is visited only if the for was not interrupted by a break)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. The code is exceedingly ugly now though :(

shutil.rmtree(destdir)
break
except OSError as e:
if e.winerror == 32:
Copy link
Contributor

Choose a reason for hiding this comment

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

can we give a name for this 32 magic number?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think python exposes a public api for this, they themselves do this: https://github.com/python/cpython/blob/8ad6067bd4556afddc86004f8e350aa672fda217/Lib/shutil.py#L456

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, I found out as much, but we can still give it a name in this script to help the reader 🙂

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

Choose a reason for hiding this comment

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

actually, as far as I could test an OSError with .winerror == 32 actually gets raised as a more specific PermissionError, but I guess the .winerror == 32 specifies this is the "still in use" error. So I just suggest we add a still_in_use_winerror = 32 and use that for readability

@criemen criemen requested a review from redsun82 July 8, 2024 15:28
Comment on lines +59 to +62
else:
shutil.rmtree(destdir)
else:
shutil.rmtree(destdir)
Copy link
Contributor

@redsun82 redsun82 Jul 8, 2024

Choose a reason for hiding this comment

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

maybe to lower the ugliness we can extract this code into our own rmtree function, replace break with return, and collapse these two elses into one fall-through

Suggested change
else:
shutil.rmtree(destdir)
else:
shutil.rmtree(destdir)
shutil.rmtree(destdir)

?

Copy link
Contributor

@redsun82 redsun82 left a comment

Choose a reason for hiding this comment

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

I'm also ok with merging as is though 🙂

Thanks!

@criemen
Copy link
Collaborator Author

criemen commented Jul 8, 2024

Let's merge this as-is, creating a function is (almost) line-count-neutral.

If we had pypi or something available here, I'd rather pull in the retry package with which this could be expressed much neater.

@criemen criemen merged commit f87e680 into main Jul 8, 2024
17 checks passed
@criemen criemen deleted the criemen/install-remove branch July 8, 2024 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants