Skip to content
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

An almost working implementation to install from .whl #3

Closed
wants to merge 16 commits into from

Conversation

uranusjr
Copy link
Member

@uranusjr uranusjr commented May 2, 2020

I implemented the whole workflow to identify what are the missing pieces. And it’s almost working!

$ py examples/whl.py <..whl> <directory> [--installer <installer-name>]

(See pypa/pip#8156 for background of the installer name feature.)

There are two areas I have not implemented:

  • Script generation. This is probably the most hairy part unimplmented. I’ll probably go copy reference parts of distlib.
  • PEP 610 (direct_url.json). I’m not sure about how we should implement this. pip already has an implementation, but I don’t feel like copying it directly since we only need a small subset of it (to write the file, not read and make sense of it). Maybe we should put it somewhere instead, e.g. packaging or importlib-metadata? The installer can just accept an optional DirectURL instance and work with that.

And then we can start identifying features we can make sans-IO. I already pulled out a part of making sense of the wheel structure (where the .dist-info directory is, and format various files in it). Some other potential parts I can think of:

  • Metadata generation (other than RECORD). Especially if we have PEP 610 support, since that is more than writing a string to a file.
  • Keeping track of the installed files. Currently the example is using a dict to do this, but maybe we can have a Recorder (I’m terrible at naming) class to encapsulate the logic.

examples/whl.py Show resolved Hide resolved
examples/whl.py Outdated Show resolved Hide resolved
examples/whl.py Outdated Show resolved Hide resolved
examples/whl.py Outdated Show resolved Hide resolved
src/installer/layouts.py Outdated Show resolved Hide resolved
temp = path.with_name("{}.tmp.{}".format(path.name, self._name))
with temp.open(**kwargs) as f:
yield f
temp.replace(path)

Choose a reason for hiding this comment

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

given it also replaces I feel like just open is not adequate naming here

Choose a reason for hiding this comment

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

then again what's the point of this tmp file rather than just direct-write?

Copy link
Member Author

@uranusjr uranusjr May 2, 2020

Choose a reason for hiding this comment

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

I stole this pattern from pip and thought the original implementation must exist for a reason. Likely some kind of edge case about writing to an already-open file.

I’m not really in love with the naming of this either, but can’t think of a better one.

Choose a reason for hiding this comment

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

@pradyunsg care to enlighten us? for me at the moment seems just a needless complication 😊 At least let's document it why we need this awkward way.

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried to trace this, and… it takes me straight back to the initial implementation of wheel support! cc @dholth

pypa/pip@aa5b33d#diff-2695f32c4432acd141c3dbe7e7e3a6b0R152

Copy link
Member

Choose a reason for hiding this comment

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

It's likely to prevent concurrency issues, the rename operation being atomic.

Choose a reason for hiding this comment

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

If so I consider this a bad approach, it silently swallows an important error. Sure you will not throw a failure... but instead, you're getting an environment that might not be what you expect. I'd rather throw the failure to notify the user. E.g. imagine two processes install in parallel different versions; with this approach, we'll not throw an error, but the created version will be a combination of version A and B. I'd rather throw and let the user know that something bad is happening.

Choose a reason for hiding this comment

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

Not to mention that while you might not get failure on the .dist-info file, you can still get the same concurrency failure on .dist-info.tmp file.

installer.install(options.dest)


if __name__ == "__main__":

Choose a reason for hiding this comment

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

yeah this should go into the __main__ 👍

pyproject.toml Show resolved Hide resolved
pyproject.toml Show resolved Hide resolved


class InvalidWheel(Exception):
pass

Choose a reason for hiding this comment

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

instead of pass consider adding a docstring that explains when the error may be thrown

@brettcannon
Copy link
Member

Script generation.

What does this entail? Is this console_script entry points?

Maybe we should put [PEP 610] somewhere instead, e.g. packaging or importlib-metadata?

Either of those sounds reasonable to me.

@uranusjr
Copy link
Member Author

uranusjr commented May 2, 2020

What does this entail? Is this console_script entry points?

Yup.

@uranusjr uranusjr marked this pull request as ready for review May 2, 2020 22:49
@uranusjr
Copy link
Member Author

uranusjr commented May 4, 2020

I’m going to separate this and submit them as individual PRs instead. This contains at least two entirely different concerns.

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.

4 participants