Skip to content

install-wheel: add support for specifying python startup flags#13

Open
eli-schwartz wants to merge 1 commit into
gentoo:masterfrom
eli-schwartz:script-flags
Open

install-wheel: add support for specifying python startup flags#13
eli-schwartz wants to merge 1 commit into
gentoo:masterfrom
eli-schwartz:script-flags

Conversation

@eli-schwartz
Copy link
Copy Markdown
Member

gpep517 install-wheel --shebang-flags='-s'

will cause all /usr/bin scripts to pass -s to the interpreter in its shebang. Useful for ensuring that system commands do not import mismatched modules from pip install --user.

Also useful in theory to produce programs that run via -OO, something the python ecosystem rarely remembers is possible because scripts cannot be easily fine-tuned and short of changing the entrypoint script you cannot activate -O. Perhaps we could change that.

Copy link
Copy Markdown
Member

@mgorny mgorny left a comment

Choose a reason for hiding this comment

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

Please don't forget to handle updates to your "prerequirement" upstream PR and finally file this as a PR for upstream.

Comment thread gpep517/__main__.py
from installer.sources import WheelFile
from installer.utils import get_launcher_kind

from .scheme import Gpep517WheelDestination
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't use relative imports. Be consistent.

Comment thread gpep517/__main__.py Outdated
Comment thread gpep517/scheme.py Outdated
Comment thread gpep517/scheme.py Outdated
Comment thread gpep517/scheme.py
from __future__ import annotations

import contextlib, io, os, shlex, zipfile
import typing as T
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Inconsistent.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Again, all this does is make files longer and more annoying to read, since most type annotations suddenly gain an additional 5 characters of overhead towards the max line length.

Either that or you spend more time managing individual from typing import Foo, Bar, Baz imports than you spend coding.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In preparation for rebasing... I'd still like an answer about this.

I've found when reading and contributing to many python codebases that usage of symbols from the typing module tend to shift around a lot.

Importing typing and referencing typing.Iterable leads to overly long lines that are cramped and hard to read, especially if a line has more than one typing symbol on a single line (multiple parameters to a function definition, use of Union, container types such as Dict and List and Mapping that have other symbols inside). Tonaid in readability, I was introduced to, and gratefully started using myself, the convention to import typing as T which saves a lot of space. "T" is very recognizable and there aren't a lot of use cases for a one-character symbol other than that. The main other use case is for loop iteration, but that is usually "i" or "k, v". And anyways, the use of upper case is a well established convention for global constants, and the typing module is global and contains constants, so... :)

I think it's a good convention and it aids in readability, so if possible I'd like to be able to come to an agreement that this "as" import can stay and perhaps be used in other files as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I've never done it in this project, or any of the other of my projects, and I never had a real need to. Hence, I don't see the point of suddenly changing this now.

Comment thread gpep517/scheme.py
# with minor tweaks where classes don't have hooks to control their
# internals.

from __future__ import annotations
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this really needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It is required to make if T.TYPE_CHECKING imports not be runtime errors. It is also a small performance improvement for all code that has type annotations, period.

Type annotations are not needed at runtime unless you're using something like beartype or pydantic. Building them into code objects and discarding them is a bit wasteful.

The import is equivalent to surrounding all type annotations with quotes. I find the future import to be more ergonomic, and could add it to other files if you like... ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, feel free to add them everywhere.

Comment thread gpep517/scheme.py Outdated
@eli-schwartz eli-schwartz force-pushed the script-flags branch 2 times, most recently from 3e79825 to 2b65308 Compare December 13, 2023 01:28
```
gpep517 install-wheel --shebang-flags='-s'
```

will cause all /usr/bin scripts to pass `-s` to the interpreter in its
shebang. Useful for ensuring that system commands do not import
mismatched modules from `pip install --user`.

Also useful in theory to produce programs that run via -OO, something
the python ecosystem rarely remembers is possible because scripts cannot
be easily fine-tuned and short of changing the entrypoint script you
cannot activate -O. Perhaps we could change that.
@eli-schwartz
Copy link
Copy Markdown
Member Author

Updated.

@thesamesam thesamesam requested a review from mgorny December 26, 2023 20:21
@eli-schwartz
Copy link
Copy Markdown
Member Author

Any update on what I should do here? Upstream PyPA/installer hasn't merged any PRs in months other than pre-commit.ci spam and isn't responsive to requests for review.

Are we still waiting on them or is it fine to reimplement functionality locally?

Are there any responses to the answers I gave on review comments where I disagreed with the review?

@mgorny mgorny closed this Apr 29, 2025
@arthurzam
Copy link
Copy Markdown
Member

@mgorny mind explaining why this PR was closed?

I see a request for further comments from the author, with no replies. A little bit of more explanation would be nice.

@arthurzam arthurzam reopened this Apr 29, 2025
@mgorny
Copy link
Copy Markdown
Member

mgorny commented Apr 29, 2025

OP was requested to submit the pull request upstream. Nothing new has happened.

@thesamesam
Copy link
Copy Markdown
Member

It took ages for pypa/installer#200 to be merged and no answer was given to the questions directed to you above, including whether there's a need to wait for installer to merge every single change (which may take years) or not. Nor the other parts.

@mgorny
Copy link
Copy Markdown
Member

mgorny commented Apr 29, 2025

The PR was merged eventually.

@thesamesam
Copy link
Copy Markdown
Member

Yes, eventually. pypa/installer#276 seems stuck now too.

Let's please not wait on installer (where we've had various issues before, like with --prefix). Can you review this again?

@arthurzam
Copy link
Copy Markdown
Member

I'm also in support for not waiting for upstream, I suspect it would be easier to drop support when they do accept it (in some years).

I would recommend to mention in the script docs, and the special argument passed, that they are temporary until upstream merges, so non-Gentoo projects that use gpep517 know this might break in the future.

Copy link
Copy Markdown
Member

@mgorny mgorny left a comment

Choose a reason for hiding this comment

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

Sure, I can live with it. Still, it needs to be rebased and the new code needs to follow the same coding style as the existing code.

Comment thread gpep517/scheme.py

if forlauncher or simple:
shebang = '#!' + executable + post_interp_
else:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we actually need this? I don't think we really expect Gentoo Python executables that long, or support spaces in EPREFIX. I get that it's upstream code, but since we're duplicating it, better duplicate less of it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think so. There are people outside of Gentoo that use gpep517, e.g. on the distro side Alpine. But also I've mentioned it a few times to people in #python and similar when the topic of installing wheels without pip has come up, and they have found it interesting and useful.

Comment thread gpep517/scheme.py
# gpep517: use build_shebang
new_stream.write(build_shebang(interpreter, False, flags) + b'\n')
# copy the rest of the stream
stream.seek(0)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this really necessary? Logically saying, we've just read #!python without the newline, so readline() without seeking should yield the same result.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Indeed, I think you're correct. It's a small saving but correct to avoid. I suppose the installer sources copied it from the else branch (where it is necessary to rewind to the beginning) but I'm still not sure why. :D

Comment thread gpep517/scheme.py
Comment on lines +94 to +98
while True:
buf = stream.read(_COPY_BUFSIZE)
if not buf:
break
new_stream.write(buf)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks like reinventing shutil.copyfileobj().

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes... I quite agree. It appears to be blindly copied from copyfileobj_with_hashing, another function from the installer codebase which at least had a good reason to exist.

@eli-schwartz
Copy link
Copy Markdown
Member Author

Still, it needs to be rebased

Yup, I see that since 4d9f6e9 the code I modified has made other changes that lead to merge conflicts. (Same basic idea though -- applying our own scheme handler.)

After the weekend I will see about finding time to sort that out, and update the PR to base itself off of that.

I would recommend to mention in the script docs, and the special argument passed, that they are temporary until upstream merges, so non-Gentoo projects that use gpep517 know this might break in the future.

@arthurzam,

I'm not sure what you mean by that. We don't -- never have and probably never will -- import upstream's __main__, all we do is use the library APIs to build out our own CLI. We already add other optional features that upstream isn't interested in for their CLI, and we also rename the option for enabling optimized bytecode (which upstream insists on using two separate arguments for).

I don't see any reason to mark a gpep517 CLI argument as temporary. Upstream changes will only affect our ability to reuse new library APIs instead of designing them ourselves.

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.

5 participants