Skip to content

Isolate environment variable substitutions #521

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

Merged
merged 3 commits into from
Aug 11, 2017
Merged

Isolate environment variable substitutions #521

merged 3 commits into from
Aug 11, 2017

Conversation

AndreLouisCaron
Copy link

Perform {env:X} replacement only in environments where X is used. This
enables different environments to use different subsets of the environment
(e.g. don't require union of all passenv sections in all environments).

Fixes #515.

Note to reviewers: this is a tentative fix. I'm definitely not sure how to best proceed with this fix. Feel free to recommend an alternate approach!

Perform `{env:X}` replacement only in environments where `X` is used.  This
enables different environments to use different subsets of the environment
(e.g. don't require union of all passenv sections in all environments).
@The-Compiler
Copy link
Member

Can't speak for the code, but I've had this problem before too.

@AndreLouisCaron
Copy link
Author

Ping?

@obestwalter
Copy link
Member

Hi @AndreLouisCaron thanks for the fix. Can you quickly tell me why you are not confident that the fix is the best way to go forward? I did not check the code yet, just wanted to get more insight, before I review it.

@AndreLouisCaron
Copy link
Author

@obestwalter Some methods already had a replace argument, but not all of them. Also, it seemed (to me, without context) to be inconsistently applied. I couldn't figure out why it was applied in some places and not others, but maybe it was written like that for a good reason that is unknown to me :-)

@obestwalter
Copy link
Member

o.k. thanks - I will take that into account and dig a bit through history to check whether there is some background to it.

@@ -818,7 +819,7 @@ def make_envconfig(self, name, section, subs, config):
atype = env_attr.type
if atype in ("bool", "path", "string", "dict", "dict_setenv", "argv", "argvlist"):
meth = getattr(reader, "get" + atype)
res = meth(env_attr.name, env_attr.default)
res = meth(env_attr.name, env_attr.default, replace=replace)
Copy link
Author

Choose a reason for hiding this comment

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

Note to reviewers: adding this here is why I needed to add a replace argument all over the place.

@@ -787,7 +787,8 @@ def __init__(self, config, inipath):
factors = set(name.split('-'))
if section in self._cfg or factors <= known_factors:
config.envconfigs[name] = \
self.make_envconfig(name, section, reader._subs, config)
self.make_envconfig(name, section, reader._subs, config,
replace=name in config.envlist)
Copy link
Author

Choose a reason for hiding this comment

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

Note to reviewers: this is the core of the change I wanted to make. Don't replace environment substitutions unless the environment is in envlist.

Copy link
Author

Choose a reason for hiding this comment

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

Actually, my intent is to use replace=False when the environment is not scheduled in the current run. I'm not 100% sure config.envlist is what I want here.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, my intent is to use replace=False when the environment is not scheduled in the current run.

Do you mean: all the runs scheduled in this invocation? e.g. tox -e py27,py34 would then only do substitutions for these two environments when parsing the ini?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, that's what I meant.

new_arg += new_word
newcommand += new_arg
else:
newcommand = command
Copy link
Author

Choose a reason for hiding this comment

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

Note to reviewers: the new else clause here is essential to the change. When replace=False, we should leave the command uninterpreted (we can't evaluate it since we're potentially missing some of the variables).

Copy link
Member

Choose a reason for hiding this comment

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

In combination with the current way of determining if replacements should happen that would mean though that it is possible that an environment that should run does not get any replacements if one of the variables is not set instead of rightfully crashing because there is a variable missing. Correct? I think I have create some example tox.ini and play this through to get my head around it though ...

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure I understand your question. IMO, if you request to run an environment and we can't perform substitutions because something is missing, I would keep the existing behaviour (e.g. faily loudly) for the moment.

I agree that as a user, I would expect something else (e.g. run other envs, skip/fail the one(s) with the missing vars), but I would do that in a separate PR.

Copy link
Member

Choose a reason for hiding this comment

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

oh .. I was not notified that you answered here :)

Actually I also prefer failing, but I am not sure if this is happening. I have to look closer at the test and do some exploring myself. Thanks.

@AndreLouisCaron
Copy link
Author

@obestwalter I added a few notes in the review to cue in on my reasoning. I hope it helps without skewing your independent review :-)

@obestwalter
Copy link
Member

Thanks, very appreciated :)

@@ -953,12 +954,12 @@ def getlist(self, name, sep="\n"):
return []
return [x.strip() for x in s.split(sep) if x.strip()]

def getdict(self, name, default=None, sep="\n"):
def getdict(self, name, default=None, sep="\n", replace=True):
value = self.getstring(name, None)
Copy link
Author

Choose a reason for hiding this comment

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

Note to self: may have forgotten the replace=replace here.

Copy link
Member

Choose a reason for hiding this comment

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

I think so as well, should also be passed through to getstring.

@obestwalter
Copy link
Member

I'll review and test this at the EuroPython tox sprint weekend and then it will likely be in 2.8.

@AndreLouisCaron
Copy link
Author

Thanks a bunch!

Copy link
Member

@obestwalter obestwalter left a comment

Choose a reason for hiding this comment

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

A few questions are open - see comments

@@ -787,7 +787,8 @@ def __init__(self, config, inipath):
factors = set(name.split('-'))
if section in self._cfg or factors <= known_factors:
config.envconfigs[name] = \
self.make_envconfig(name, section, reader._subs, config)
self.make_envconfig(name, section, reader._subs, config,
replace=name in config.envlist)
Copy link
Member

Choose a reason for hiding this comment

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

Actually, my intent is to use replace=False when the environment is not scheduled in the current run.

Do you mean: all the runs scheduled in this invocation? e.g. tox -e py27,py34 would then only do substitutions for these two environments when parsing the ini?

@@ -953,12 +954,12 @@ def getlist(self, name, sep="\n"):
return []
return [x.strip() for x in s.split(sep) if x.strip()]

def getdict(self, name, default=None, sep="\n"):
def getdict(self, name, default=None, sep="\n", replace=True):
value = self.getstring(name, None)
Copy link
Member

Choose a reason for hiding this comment

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

I think so as well, should also be passed through to getstring.

new_arg += new_word
newcommand += new_arg
else:
newcommand = command
Copy link
Member

Choose a reason for hiding this comment

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

In combination with the current way of determining if replacements should happen that would mean though that it is possible that an environment that should run does not get any replacements if one of the variables is not set instead of rightfully crashing because there is a variable missing. Correct? I think I have create some example tox.ini and play this through to get my head around it though ...

elif word.startswith("{posargs:") and word.endswith("}"):
if posargs:
if replace:
newcommand = ""
Copy link
Member

Choose a reason for hiding this comment

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

this should be new_command to be consistent with other variable names used around it

@AndreLouisCaron
Copy link
Author

@obestwalter Can't reply directly to your comment.

Actually, my intent is to use replace=False when the environment is not scheduled in the current run.

Do you mean: all the runs scheduled in this invocation? e.g. tox -e py27,py34 would then only do substitutions for these two environments when parsing the ini?

Yes.

@AndreLouisCaron
Copy link
Author

In combination with the current way of determining if replacements should happen that would mean though that it is possible that an environment that should run does not get any replacements if one of the variables is not set instead of rightfully crashing because there is a variable missing. Correct? I think I have create some example tox.ini and play this through to get my head around it though ...

Like I said, I'd like to answer, but I'm not sure I understand what your question is.

@obestwalter
Copy link
Member

o.k. - I'll merge this now and fix up anything that is not quite there yet (e.g. one missing passing of replace). Will test this today and cut a release candidate from it at some point at the weekend. @AndreLouisCaron it would be great if you test the rc then yourself a bit and check if everything is as it should be.

@obestwalter obestwalter merged commit 67e88f6 into tox-dev:master Aug 11, 2017
@AndreLouisCaron
Copy link
Author

Sorry, was on vacation the past 2 weeks and did not follow up. Thanks for proceeding with this! Let me know when the RC is up, I will gladly try it out :-)

obestwalter added a commit that referenced this pull request Aug 13, 2017
fix up #521: add missing pass of arg to underlying function.
@obestwalter
Copy link
Member

@AndreLouisCaron - hope you had a nice holiday :) rc1 with your changes is out already.

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.

Environment variables required across unrelated environments
4 participants