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 — bpo-20849: add dirs_exist_ok to shutil.copytree by jab · Pull Request #8792 · python/cpython

Conversation

@jab

@jab jab commented Aug 16, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor

It looks like the original author of #2977 lost interest, and it would still be really useful to have this, so I thought I'd pick it back up.

https://bugs.python.org/issue20849

Sorry, something went wrong.

Uh oh!

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

dannyqiu, nanonyme, thehesiod, Sir2B, twosigmajab, and vdesmond reacted with heart emoji
All reactions
  • ❤️ 6 reactions
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Aug 16, 2018
@bedevere-bot bedevere-bot added the awaiting review label Aug 16, 2018
@nanonyme

nanonyme commented Aug 16, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown

Hey, could you please fix the news check while waiting for a review? I just hit this same thing myself and was about to file a PR maybe ten minutes after you with basically same contents.

I to be honest think there's some merit to the critique on the ticket while this was my first idea as well. If you compare cp to shutil.copytree, cp has a --no-clobber so it creates directories but allows not overwriting existing files. While yours is a very backwards-compatible interpretation, I kinda think cp's way of doing it makes more sense than both the old and new Python idea of copytree

All reactions

Sorry, something went wrong.

Uh oh!

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

merwok
merwok reviewed Aug 16, 2018
View reviewed changes
Comment thread Lib/shutil.py Resolved

Uh oh!

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

@merwok

merwok commented Aug 16, 2018

Copy link
Copy Markdown
Member

Hello! Your branch contains unwanted changes to get-pip and a patch file.

If you’re using git on the command line, a nice tip is to use git add -p instead of git add . to choose what changes should be in your next commit.

Graphical git clients usually have a diff hunk selection screen that serves the same purpose.

All reactions

Sorry, something went wrong.

Uh oh!

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

@jab
jab force-pushed the copytree-exist_ok branch from 63b1c9b to 98e3668 Compare August 16, 2018 20:47
@jab

jab commented Aug 16, 2018

Copy link
Copy Markdown
Contributor Author

@merwok wrote:

Hello! Your branch contains unwanted changes to get-pip and a patch file.

Sorry about that! Fixed in the latest revision.

If you’re using git on the command line, a nice tip is to use git add -p instead of git add . to choose what changes should be in your next commit.

Nice, thanks for the tip!

@nanonyme wrote:

Hey, could you please fix the news check while waiting for a review?

Done in the latest revision.

I just hit this same thing myself and was about to file a PR maybe ten minutes after you with basically same contents.

No way! Solidarity, @nanonyme. Extra funny coincidence given how long this issue has been around.

I to be honest think there's some merit to the critique on the ticket while this was my first idea as well. If you compare cp to shutil.copytree, cp has a --no-clobber so it creates directories but allows not overwriting existing files. While yours is a very backwards-compatible interpretation, I kinda think cp's way of doing it makes more sense than both the old and new Python idea of copytree

I agree. Will wait for a maintainer to weigh in on how to proceed.

All reactions

Sorry, something went wrong.

Uh oh!

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

@jab jab mentioned this pull request Aug 16, 2018
bpo-20849: allow existing directory in shutil.copytree #2977
Closed
@jab
jab force-pushed the copytree-exist_ok branch 3 times, most recently from e783b52 to 24f03ee Compare August 17, 2018 03:28
jab
jab commented Aug 17, 2018
View reviewed changes
Comment thread Doc/library/shutil.rst Resolved

Uh oh!

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

@jab
jab force-pushed the copytree-exist_ok branch from 24f03ee to b771510 Compare August 17, 2018 15:03
@nanonyme nanonyme mentioned this pull request Aug 17, 2018
Workaround sync issues documented in #60 flathub/com.valvesoftware.Steam#110
Merged
@jab jab mentioned this pull request Sep 7, 2018
bpo-31861: Add operator.aiter and operator.anext #8895
Closed
@1st1
1st1 requested review from giampaolo and vstinner September 7, 2018 19:47
@1st1

1st1 commented Sep 7, 2018

Copy link
Copy Markdown
Member

@giampaolo @vstinner The PR looks OK to my eyes, should we merge it?

All reactions

Sorry, something went wrong.

Uh oh!

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

merwok
merwok reviewed Sep 7, 2018
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2018-08-16-16-47-15.bpo-20849.YWJECC.rst Resolved

Uh oh!

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

@jab

jab commented Sep 15, 2018

Copy link
Copy Markdown
Contributor Author

Thanks for reviewing @1st1! Since the others you pinged haven’t been able to respond yet, is there anyone else who should review before this can be merged? The rest of the month will be busy for me so hoping to land while I still have the spare cycles.

All reactions

Sorry, something went wrong.

Uh oh!

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

@jab

jab commented Dec 15, 2018

Copy link
Copy Markdown
Contributor Author

Any maintainers up for giving this a look some time soon? Cheers

3 months ago @1st1 wrote:

@giampaolo @vstinner The PR looks OK to my eyes, should we merge it?

All reactions

Sorry, something went wrong.

Uh oh!

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

@giampaolo

giampaolo commented Dec 15, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor

As I said on the bug tracker I think the new argument should be called "dirs_exists_ok" (EDIT: "dirs_exist_ok") instead of "exists_ok" so that it's clear that the behavior does not affect files. Other than that the patch is fine with me but it should be updated as it has conflicts with master.

All reactions

Sorry, something went wrong.

Uh oh!

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

@jab
jab force-pushed the copytree-exist_ok branch from 9a1016b to 2279717 Compare December 20, 2018 00:15
@jab

jab commented Dec 20, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor Author

Thanks for replying @giampaolo! This has been labeled as "awaiting review" since Aug 16 and nobody commented on bpo-20849 since I did on Aug 17, so I didn't realize you were awaiting changes on this before it could be merged.

should be updated as it has conflicts with master

Rebased on latest master. (Had to resolve conflicts from your bpo-33695 changes, which I hadn't noticed before – nice changes!) All tests are passing on CI (including the test_copytree_exist_ok this adds).

I think the new argument should be called "dirs_exists_ok" instead of "exists_ok" so that it's clear that the behavior does not affect files

I don't follow – this does affect files. Are you mistakenly thinking that this patch implements option (b) described in Éric Araujo's comment (as he said the original patch did), whereas this patch actually implements option (a) (i.e. it behaves like BSD cp)?

From the docs I wrote for this: "If exist_ok is true, the destination directory may already exist, and existing files in the destination tree will be overwritten by matching files in the source tree." (emphasis added)

Also:

  1. Matching the name of the "exist_ok" argument that os.makedirs() accepts makes this new API easier for users to remember, especially upon realizing that it's passed straight through to the underlying os.makedirs(dst, exist_ok=exist_ok) call.
  2. "dirs_exists_ok" is grammatically incorrect: "dirs" is plural and "exists" is singular.
  3. The alternatives "dir_exists_ok", "dst_exists_ok", and "dirs_exist_ok" are grammatically correct, but in each case, the longer name suggests greater precision in describing the behavior (i.e. "that's all this does"), when in fact it affects existing files too.

So can this be merged as-is before there are any further conflicts?

nanonyme 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.

jab
jab commented Dec 20, 2018
View reviewed changes
Comment thread Doc/library/shutil.rst Outdated

@jab jab Dec 20, 2018

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.

(I assumed this can't land in a 3.7.x release. Can it?)

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread Lib/shutil.py Resolved

Uh oh!

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

@jab

jab commented Dec 20, 2018

Copy link
Copy Markdown
Contributor Author
$ mkdir existing_dir
$ mkdir src_dir
$ echo "will be replaced" > existing_dir/file
$ echo "replaced" > src_dir/file
$ # behaves like `cp -R src_dir/ existing_dir` on macOS/BSD (note trailing slash):
$ ./python.exe -c "import shutil; shutil.copytree('src_dir', 'existing_dir', exist_ok=True)"
$ cat existing_dir/file
replaced

(Unfortunately GNU cp apparently treats the trailing slash inconsistently. See e.g. https://jondavidjohn.com/linux-vs-osx-the-cp-command/ )

All reactions

Sorry, something went wrong.

Uh oh!

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

@giampaolo

giampaolo commented Dec 20, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor

shutil.copytree always overwrites existing destination files. My point is that exists_ok is ambiguous in that it does not specify who's the target, whether files or directories. One may erroneously think that exists_ok=False means that src and dst files with the same name will be skipped or something. dirs_exist_ok explicitly tells who's the target and removes that ambiguity.

You're right that "exist_ok" argument matches os.makedirs's, but the main character here is shutil.copytree, not os.makedirs. The usage of os.makedirs is just an internal implementation detail.

All reactions

Sorry, something went wrong.

Uh oh!

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

@nanonyme

nanonyme commented Dec 20, 2018

Copy link
Copy Markdown

Just a bit of an out-of-the-box thought: how about replace_existing/overwrite instead of all these exist_ok and dirs_exist_ok?

All reactions

Sorry, something went wrong.

Uh oh!

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

@giampaolo

giampaolo commented Dec 20, 2018

Copy link
Copy Markdown
Contributor

Same problem (doesn't tell who's the target).

All reactions

Sorry, something went wrong.

Uh oh!

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

@jab

jab commented Dec 21, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor Author

My point is that exists_ok is ambiguous in that it does not specify who's the target, whether files or directories.

I think using the word "target" instead of "destination" is muddying the waters in this discussion. If we stick to using the word "destination" instead of "target", which is the term used in the function description itself, then isn't it clear that we're talking about the dst argument, which is a directory?

One may erroneously think that exists_ok=False means that src and dst files with the same name will be skipped or something.

I'm having trouble making any sense of this unless you meant "exist_ok=True" here. Did you?

If so, then even with "dirs_exist_ok=True", couldn't that still be misinterpreted as "files with the same name might be skipped since this only applies to directories"?

All reactions

Sorry, something went wrong.

Uh oh!

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

@giampaolo

giampaolo commented Dec 21, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor

I think using the word "target" instead of "destination" is muddying the waters in this discussion. If we stick to using the word "destination" instead of "target", which is the term used in the function description itself, then isn't it clear that we're talking about the dst argument, which is a directory?

No, it's not, because "exists_ok" is meant for directories only and what copytree is about is copying files and directories, so it's not clear what "exists_ok" argument operates on unless you read the doc. Also, the argument operates against all sub-directories (plural) with the same name which can be encountered while walking down the tree, not only dst, and that is why the argument name cannot be singular (remember: it's a recursive function). This ambiguity with the argument name has already been pointed out on the tracker and in here multiple times (see here) so I'm really not sure how else to explain it.

If so, then even with "dirs_exist_ok=True", couldn't that still be misinterpreted as "files with the same name might be skipped since this only applies to directories"?

It cannot be misinterpreted because of the "dirs_" bit. It's clear it's about directories and not about files or both.

All reactions

Sorry, something went wrong.

Uh oh!

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

@jab
jab force-pushed the copytree-exist_ok branch from 2279717 to 6cf8e53 Compare December 21, 2018 13:46
@jab jab changed the title bpo-20849: add exist_ok to shutil.copytree bpo-20849: add dirs_exist_ok to shutil.copytree Dec 21, 2018
@jab

jab commented Dec 21, 2018 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor Author

I have renamed the argument dirs_exist_ok in the latest revision. CI is all green.

I'm still not following your logic but prefer to defer so this can be merged.

This ambiguity with the argument name has already been pointed out on the tracker and in here multiple times

To be fair, that was in the context of someone else's patch from 5 years ago, which implemented behavior (b). This patch implements behavior (a).

It cannot be misinterpreted because of the "dirs_" bit. It's clear it's about directories and not about files or both.

I just meant that now the argument name says nothing about what happens to files. Before you were imagining a user who didn't read the docs and jumping to the wrong conclusion about what happens to files. I don't think the new name really prevents that.

All reactions

Sorry, something went wrong.

Uh oh!

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

giampaolo
giampaolo requested changes Dec 21, 2018
View reviewed changes
Comment thread Doc/library/shutil.rst Outdated

@giampaolo giampaolo Dec 21, 2018

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.

I would simply rephrase it as something along these lines:

*dirs_exist_ok* dictates whether to raise an exception in case *dst* as well as 
any missing parent directory already exists. 

I would not talk about the overwriting of files because the argument specifically targets directories and has nothing to do with files. When copying a big directory another process may create files in the dst directory which conflicts with the ones living in src, and they are always overwritten even when dirs_exist_ok=False.

Sorry, something went wrong.

Uh oh!

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

All reactions

@jab jab Dec 21, 2018

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.

The behavior of dirs_exist_ok=False (raising an exception) is already documented in the previous paragraph, so your rephrasing of this paragraph seems redundant. The purpose of this paragraph was to document the behavior of dirs_exist_ok=True.

I've just removed the part that talks about files.

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread Lib/test/test_shutil.py Resolved

Uh oh!

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

Comment thread Misc/NEWS.d/next/Library/2018-08-16-16-47-15.bpo-20849.YWJECC.rst Resolved

Uh oh!

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

@bedevere-bot bedevere-bot removed the awaiting review label Dec 21, 2018
@bedevere-bot

bedevere-bot commented Dec 21, 2018

Copy link
Copy Markdown

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.

All reactions

Sorry, something went wrong.

Uh oh!

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

@bedevere-bot bedevere-bot added the awaiting changes label Dec 21, 2018
@jab
jab force-pushed the copytree-exist_ok branch from 6cf8e53 to acbbd3a Compare December 21, 2018 20:32
@jab

jab commented Dec 21, 2018

Copy link
Copy Markdown
Contributor Author

@bedevere-bot I have made the requested changes; please review again

All reactions

Sorry, something went wrong.

Uh oh!

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

@bedevere-bot

bedevere-bot commented Dec 21, 2018

Copy link
Copy Markdown

Thanks for making the requested changes!

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

All reactions

Sorry, something went wrong.

Uh oh!

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

@bedevere-bot bedevere-bot added awaiting change review and removed awaiting changes labels Dec 21, 2018
giampaolo
giampaolo reviewed Dec 26, 2018
View reviewed changes
Comment thread Doc/library/shutil.rst Resolved

Uh oh!

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

@jab
jab force-pushed the copytree-exist_ok branch from acbbd3a to 8a0c7d2 Compare December 27, 2018 19:39
giampaolo
giampaolo reviewed Dec 27, 2018
View reviewed changes
Comment thread Doc/whatsnew/3.8.rst Resolved

Uh oh!

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

giampaolo
giampaolo reviewed Dec 27, 2018
View reviewed changes
Comment thread Lib/shutil.py Resolved

Uh oh!

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

@jab
jab force-pushed the copytree-exist_ok branch from 8a0c7d2 to 4a9c7ca Compare December 28, 2018 00:15
giampaolo
giampaolo reviewed Dec 28, 2018
View reviewed changes
Comment thread Lib/shutil.py Resolved

Uh oh!

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

@jab
bpo-20849: add dirs_exist_ok to shutil.copytree
dbb9162
@jab
jab force-pushed the copytree-exist_ok branch from 4a9c7ca to dbb9162 Compare December 28, 2018 14:56
@giampaolo

giampaolo commented Dec 28, 2018

Copy link
Copy Markdown
Contributor

Looks good. Merging.

thehesiod, nanonyme, logan-pugh, and vdesmond reacted with hooray emoji
All reactions
  • 🎉 4 reactions

Sorry, something went wrong.

Uh oh!

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

@giampaolo
giampaolo merged commit 9e00d9e into python:master Dec 28, 2018
@bedevere-bot bedevere-bot removed the awaiting change review label Dec 28, 2018
@jab
jab deleted the copytree-exist_ok branch December 28, 2018 18:31
@jab

jab commented Dec 28, 2018

Copy link
Copy Markdown
Contributor Author

Thanks @giampaolo! Can this be considered for backporting to 3.7.x? If so I would be happy to submit another PR for that.

All reactions

Sorry, something went wrong.

Uh oh!

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

@giampaolo

giampaolo commented Dec 28, 2018

Copy link
Copy Markdown
Contributor

;-)
No, it cannot be backported to 3.7 because this is a new feature.

All reactions

Sorry, something went wrong.

Uh oh!

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

@lorencarvalho lorencarvalho mentioned this pull request Nov 1, 2019
fix 'dir already exists' when supplying both pip_args and site_packages linkedin/shiv#116
Closed
@jab jab mentioned this pull request Jul 27, 2020
Document that shutil.copytree now accepts dirs_exist_ok mahmoud/boltons#262
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@merwok merwok merwok left review comments
@giampaolo giampaolo giampaolo requested changes
@vstinner vstinner Awaiting requested review from vstinner

Uh oh!

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

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

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

7 participants

@jab @nanonyme @merwok @1st1 @giampaolo @bedevere-bot @the-knights-who-say-ni
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.