-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-41011: venv -- add more variables to pyvenv.cfg (GH-30382) #30382
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
bpo-41011: venv -- add more variables to pyvenv.cfg (GH-30382) #30382
Conversation
Lib/venv/__init__.py
Outdated
@@ -178,6 +178,8 @@ def create_configuration(self, context): | |||
f.write('version = %d.%d.%d\n' % sys.version_info[:3]) | |||
if self.prompt is not None: | |||
f.write(f'prompt = {self.prompt!r}\n') | |||
f.write('executable = %s\n' % context.env_exec_cmd) | |||
f.write('command = %s\n' % sys.executable) |
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.
That (sys.executable
) is not the command (-line) which was used to create the environment - it would be the python -m venv ...
or equivalent command line which need to be recorded.
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.
Would something like this work?
args = ' '.join(sys.argv[1:])
f.write(f'command = {sys.executable} -m {context.env_name} {args}\n')
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.
Would something like this work?
Not necessarily. The code to create a venv might be called programmatically through the EnvBuilder
API. The intention is to provide a command which, if run, produces a venv with the current settings. So the thing to do is:
- Run
python3 -m venv -h
to see what the command-line options are. - Look at the existing code to see how those options map to attributes of the
EnvBuilder
which are used in making the venv. - Looking at the
EnvBuilder
attributes of the current instance, work out what command-line would give those attributes, and synthesize the command line from there.
@@ -0,0 +1,3 @@ | |||
Added two new variables to *pyvenv.cfg* which is generated by :mod:`venv` | |||
module: *executable* for the executable within the environment and *command* | |||
for the command used to create the environment. |
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.
command -> command line
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 |
Lib/venv/__init__.py
Outdated
@@ -178,6 +178,8 @@ def create_configuration(self, context): | |||
f.write('version = %d.%d.%d\n' % sys.version_info[:3]) | |||
if self.prompt is not None: | |||
f.write(f'prompt = {self.prompt!r}\n') | |||
f.write('executable = %s\n' % context.env_exec_cmd) | |||
f.write('command = %s\n' % sys.executable) |
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.
Would something like this work?
Not necessarily. The code to create a venv might be called programmatically through the EnvBuilder
API. The intention is to provide a command which, if run, produces a venv with the current settings. So the thing to do is:
- Run
python3 -m venv -h
to see what the command-line options are. - Look at the existing code to see how those options map to attributes of the
EnvBuilder
which are used in making the venv. - Looking at the
EnvBuilder
attributes of the current instance, work out what command-line would give those attributes, and synthesize the command line from there.
Misc/NEWS.d/next/Library/2022-01-03-21-03-50.bpo-41011.uULmGi.rst
Outdated
Show resolved
Hide resolved
…sed on EnvBuilder attrs
…t flag; expand test to check that no invalid flags are present when no args are passed to EnvBuilder
Lib/venv/__init__.py
Outdated
if self.upgrade_deps: | ||
args.append('--upgrade-deps') | ||
if self.orig_prompt is not None: | ||
args.append(f'--prompt={self.orig_prompt}') |
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.
prompt = f'"{self.orig_prompt}"' if ' ' in self.orig_prompt else self.orig_prompt
args.append(f'--prompt={prompt}')
to handle the case where self.orig_prompt
has spaces?
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 think it's not enough to quote it on spaces, I quoted it unconditionally in case of chars like '*'.
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.
Ah, I just realized I did not commit that change.. pushing it now.
@vsajip I know the test got to be ugly and confusing, lmk if I can make it clearer... |
Do you mean |
Yes. It's also quite slow (creating new env for each flag), but checking all flags in one run would be less thorough, but it's an option we can consider. |
How about mocking the |
Yep it does! Much faster now.. |
@vsajip thanks for many rounds of quick reviews!! :) |
@@ -178,6 +179,29 @@ def create_configuration(self, context): | |||
f.write('version = %d.%d.%d\n' % sys.version_info[:3]) | |||
if self.prompt is not None: | |||
f.write(f'prompt = {self.prompt!r}\n') | |||
f.write('executable = %s\n' % os.path.realpath(sys.executable)) |
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 appreciate that this PR is long since merged, but just following-up on a surprising pyvenv.cfg
file that I saw recently, and git-blamed it back to here)
I'm not at all sure why realpath
is important here - the sys.executable
should be good enough when being called directly. When called through the EnvBuilder
, I don't see a reason for this either. 🤔
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.
You're right, it is a difference when you're not on Windows. But thinking about it, you could view the config as recording the actual interpreter used instead of the path that could change on you in the future (e.g., some symlink later gets changed to point to another interpreter).
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.
Thanks for this perspective (I hadn't considered it)! I'm not sure that using a config file to log information about how a venv was created is a good idea, but can appreciate the idea. Since this is a machine readable file, I would be concerned that it eventually gets used for non-log/audit purposes.
I've been digging into symlink issues with venv a lot recently, and think calling realpath
is quite problematic in other context (i.e. when determining home
). More details of that in #106045.
No follow-up needed here - just flagging it, and depending on the outcome of the linked issue, perhaps in the future I may request that this information become non realpath, or under a "history of how this venv was created" section of the config (perhaps in the form of a comment).
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'm not sure if these should be added to the docs -- there's no pyvenv.cfg section and two of the vars are currently documented in separate places and another two are not documented. It seems like someone needing them would look in pyvenv.cfg and find them; and their values are self-explanatory.
https://bugs.python.org/issue41011