-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
build_meta doesn't use a fresh dist directory, which causes ValueError unpacking tuple #1671
Comments
I could be wrong, but I think we can somewhat trivially fix this by changing sys.argv = sys.argv[:1] + ['bdist_wheel'] + \
config_settings["--global-option"]
_run_setup()
if wheel_directory != 'dist':
shutil.rmtree(wheel_directory)
shutil.copytree('dist', wheel_directory) Would turn to: sys.argv = sys.argv[:1] + ['bdist_wheel', '--dist-dir=%s' % wheel_directory] + \
config_settings["--global-option"]
_run_setup() I'm not sure what happens if |
FYI pypa/pip@51086b3 |
@pradyunsg Is this causing major problems? I put it in my mental backlog and left as a possible sprint item just because it seemed like it would only affect maintainers who leave build artifacts around in their source directories. If it's causing real problems for other people, I'll at least bump it up in priority from "minor". |
Nope -- this is pretty minor IMO. I wanted to note here that this showed up while testing |
Because of a bug in setuptools (pypa/setuptools#1671), building our files in `dist/` can cause build failures if dist/ is not cleaned out between builds, so for now we target dists/.
Because of a bug in setuptools (pypa/setuptools#1671), building our files in `dist/` can cause build failures if dist/ is not cleaned out between builds, so for now we target dists/.
Hi, can the title of this issue be changed to include "ValueError: too many values to unpack" ? This bug is easily triggered in this (not very far-fetched) scenario:
|
Not sure we need to change the title of the issue, that's a fairly generic title for the issue. I've changed the issue title to mention ValueError in case that helps. Hopefully this won't persist very long as it's a fairly easy issue to fix, the hardest part of the issue will be writing a test for it, but even that shouldn't be too tough since it just requires translating my reproduction steps into Python. |
If it can help, I've implemented a test here: https://github.com/florisla/setuptools/commit/3c3c6e568feaad654efda4bfe1275643f0f4872d . It produces 'ValueError: too many values to unpack' as expected. |
@florisla Yes that would be very useful. Can you mark it as The name can also be shortened pretty considerably - the |
Hi, I'm using Upon release I want to create the wheels for my application and all its dependencies in order to push them on a local PyPI repo. To do that Because of the Is this a valid use case or I'm just doing it wrong? Thanks. |
@ariciputi This is definitely a bug in |
@pganssle thanks for the hint. |
…anylinux_wheels.sh, to leave all wheels in the wheelhouse after a run until a final run step in the circle config moves them all into the dist folder. this is to workaround the bug where pip errors out when multiple wheels are in the dist dir (pypa/setuptools#1671)
@pganssle FTR this is affecting building a bunch of |
@pganssle I've spent almost an entire day today with this and turns out that your advice from #1671 (comment) doesn't exactly work in case if there was So the problem is that it's hard-coded. In my Then, I Finally, I copy stuff back to The problem was that I was running two containers (x86_64 and i686). So the first one creates Now I have ideas on how to work around this properly but I think that this issue is important enough to be solved ASAP because I think that may manylinux1 wheels maintainers will hit it sooner or later. And it's quite tricky to debug. The bug originates here (in particular): setuptools/setuptools/build_meta.py Lines 168 to 170 in 64e60fc
|
@webknjaz Yes, I believe I explained how to solve this issue in this comment, that's why it's tagged "good first issue". You can work around it by never using Most of the work of the PR would be properly designing a test. |
Yeah... It was just not immediately obvious to me why it was still failing after changing |
This introduces workaround for setuptools' bug in PEP517 build backend: pypa/setuptools#1671
I had a look at this and as @pganssle mentioned, the issue is that build_meta.build_wheel (and also build_meta.build_sdist) assume that there will only be 1 If we agree that a user could possibly want to populate a self.run_setup() is the method that creates the wheel / tar on the directory that was provided to it. If this method could return the path of the final That leaves us with an option of heuristically determining, amongst a list of possible I don't think this would work since the issue is that the build_directory provided by the caller could have existing things and the problem here is determining what in that dir was just built. But I could be wrong given my limited knowledge. So we could fall back to the original idea in the main issue:
Implement this by checking if the I could raise a PR to do this if it sounds sensible? |
That's what I was thinking: setuptools/build_meta.py | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git i/setuptools/build_meta.py w/setuptools/build_meta.py
index 47cbcbf6..51113856 100644
--- i/setuptools/build_meta.py
+++ w/setuptools/build_meta.py
@@ -32,6 +32,7 @@
import tokenize
import shutil
import contextlib
+import tempfile
import setuptools
import distutils
@@ -182,14 +183,15 @@ def build_wheel(self, wheel_directory, config_settings=None,
metadata_directory=None):
config_settings = self._fix_config(config_settings)
wheel_directory = os.path.abspath(wheel_directory)
- sys.argv = sys.argv[:1] + ['bdist_wheel'] + \
- config_settings["--global-option"]
- self.run_setup()
- if wheel_directory != 'dist':
- shutil.rmtree(wheel_directory)
- shutil.copytree('dist', wheel_directory)
-
- return _file_with_extension(wheel_directory, '.whl')
+ with tempfile.TemporaryDirectory(dir=wheel_directory) as tmp_dist_dir:
+ sys.argv = sys.argv[:1] + [
+ 'bdist_wheel', '--dist-dir', tmp_dist_dir
+ ] + config_settings["--global-option"]
+ self.run_setup()
+ wheel_basename = _file_with_extension(tmp_dist_dir, '.whl')
+ os.rename(os.path.join(tmp_dist_dir, wheel_basename),
+ os.path.join(wheel_directory, wheel_basename))
+ return wheel_basename
def build_sdist(self, sdist_directory, config_settings=None):
config_settings = self._fix_config(config_settings) |
@shashanksingh28 No need to do anything quite so complicated, we can just use the temporary directory provided to us by the PEP 517 front-end, as in the solution I described in this comment. The most difficult part of making this PR will be creating a test for it. One trivial way to do that is to do something like this test, but using files = {
'setup.py': DALS("""
__import__('setuptools').setup(
name='foo',
version='0.1.0',
)"""),
'dist/foo-0.0.0-py2.py3-none-any.whl'
} I'd add the test first to make sure it triggers the bug. Another option is to basically implement the MWE from the original post as a test, and run |
@benoit-pierre Why? I'm pretty sure I think it's fine to add a temporary directory on top of it, I guess. That will be helpful if someone configures their frontend to not build the wheels in a clean directory for whatever reason. |
It's not explicitly mentioned in the PEP that it's a temporary directory, at least not in the |
OK, I don't think there's any harm in creating our own temporary directory for this. In that case we'll probably also want to add a test (we can just parametrize the first test) for the situation where |
I like @benoit-pierre's proposal with a tmpdir. It's clean and easy to understand. One minor suggestion: move the |
Er, hold up, I just remembered that #1726 already implements a test for this and was just blocked on a bug that has since been fixed. Let me merge that. |
#1726 should merge as soon as CI passes. @shashanksingh28 Feel free to submit a PR based on it that:
|
Add failing test for issue #1671 (ValueError when .whl is present)
Just realized that the tempdir idea won't cut it. Turns out run_setup() always creates the A possible solution would be to get the latest Something like: def _file_with_extension(directory, extension):
"return the latest file with given extension in the directory"
matching = (os.path.join(directory, f) for f in os.listdir(directory) if f.endswith(extension))
matching = sorted(matching, key=os.path.getctime)
return os.path.basename(matching[-1]) Is it necessary for a given This approach will still have inconsistencies.. If one does : |
I wonder if really the simplest solution is to ensure |
I'm not seeing any issue with my patch above, and the test pass. |
|
Ah I see why. Because you explicitly pass the tempdir as the Thanks 👍, will put something that is compatible with python2 as well that mimics your patch |
`build_meta.build_wheel` assumes that the only wheel in its output directory is the one it builds, but prior to this, it also used the `dist/` folder as its working output directory. This commit uses a temporary directory instead, preventing an error that was triggered when previously-generated wheel files were still sitting in `dist/`. Fixes GH pypa#1671
`build_meta.build_wheel` assumes that the only wheel in its output directory is the one it builds, but prior to this, it also used the `dist/` folder as its working output directory. This commit uses a temporary directory instead, preventing an error that was triggered when previously-generated wheel files were still sitting in `dist/`. Fixes GH pypa#1671
@pganssle now that it's fixed. May I ask for a new bugfix release, please? |
@webknjaz I have no objections, but I won't have much time until this weekend at the earliest. @benoit-pierre or @jaraco feel free to cut a release. |
I'll do it. |
@benoit-pierre thank you! |
If you use
pip install .
on a source directory that already has adist
, the existing directory structure is used when preparing the wheel. This causes an exception if an existing wheel with a different name exists, because build_meta assumes there's only one wheel indist
.Here's a script to create a MWE repo:
At this point your repo looks like this:
Create a wheel in
dist
, then change the version:Now try to create a wheel from the repo:
This is pretty easy to work around, obviously, since the user can just remove
dist
before invoking anypip
commands, but it might be better to do the wheel build in a clean directory if possible.The text was updated successfully, but these errors were encountered: