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

Change Variables() such that you can disable subst()'ing before running converter or validator #4241

Closed
bdbaddog opened this issue Oct 11, 2022 · 9 comments · Fixed by #4550
Assignees
Labels
mongodb Variables Variables() subsystem

Comments

@bdbaddog
Copy link
Contributor

bdbaddog commented Oct 11, 2022

Currently, the logic for Variables will subst the passed value for a variable before running the converter and validator (per each if specified). This isn't always desirable. Suggest add a flag or other way to disable one or both of those substs

Required information

  • Version of SCons
    4.4.0
  • Version of Python
    N/A

Discord discussion:
https://discord.com/channels/571796279483564041/1029498487156527114

@bdbaddog bdbaddog added Variables Variables() subsystem mongodb labels Oct 11, 2022
@bdbaddog bdbaddog self-assigned this Oct 11, 2022
@mwichmann
Copy link
Collaborator

RFI: I can't follow that link (get lost in the morass of trying to vector through the web browser to authenticate before being allowed to see, which no longer works for me), could we add a detail for

This isn't always desirable

@bdbaddog
Copy link
Contributor Author

bdbaddog commented Apr 8, 2024

Here's the discord thread content:

acm — 10/11/2022 1:59 PM
Does python come with something builtin to do "array literal in a string to array"?

bdbaddog — 10/11/2022 2:18 PM
str.split() ?

bdbaddog — 10/11/2022 2:35 PM
so I'd be if it hadn't initially been named Options() ListVariable would have been named OptionsVariable() which is actually a better name, then ListVariable() could be used for this.. but is your query only about passing a variable on command line which would have file paths?

acm — 10/11/2022 2:44 PM
Not just file paths
The problem is any "list-y" thing
Not all lists are paths
Probably many are, but I wouldn't want to require that
I think the naming stuff is not really relevant

bdbaddog — 10/11/2022 2:49 PM
the naming? you mean OptionsVariable(),etc.. (just thinking out loud there, not meant to address your query)
I think we want variable evaluation to have an option to not subst if there is a converter.

acm — 10/11/2022 2:51 PM
There are some other oddities in validator and converter
Like if you have:
Variable(validator=validate, converter=int())
The validator gets called with a string
It is a little puzzling
So if you have a flag that can only take the integers 4 or 5, your validator has to validate '4' and '5'
And I agree it is weird that having a converter implies an unavoidable subst
I got stuck on RPATH when I tried this in a variables file:
RPATH=[SCons.Subst.Literal('$ORIGIN/../lib')]

That would have worked, except that RPATH has a converter
So it gets substed.

bdbaddog — 10/11/2022 3:02 PM
Do you think you'd always want to either subst for both converter and validator, or for neither? or selectively for each?

acm — 10/11/2022 3:04 PM
Yeah I really don't know
I can see reasons for doing it both ways
I'll think about it
I will probably need to end this bit of yak shaving and go find a solution that does not involve setting an $ORIGIN -y RPATH on the command line.

bdbaddog — 10/11/2022 3:06 PM
that for linux linker? mac's different right?
for your usage you'd either want RPATH or not right? if so the value would be always $ORIGIN/../lib ?

bdbaddog — 10/11/2022 3:25 PM
Added this to add details and not drop this. #4241

@mwichmann
Copy link
Collaborator

that's useful, thanks. Somehow I'm not surprised the always beloved \\\\\\\\\$ORIGIN is involved here.... that one always causes trouble, it seems :-)

@mwichmann
Copy link
Collaborator

mwichmann commented Apr 21, 2024

Okay, to pick this bit:

Like if you have Variable(validator=validate, converter=int()), the validator gets called with a string. It is a little puzzling. So if you have a flag that can only take the integers 4 or 5, your validator has to validate '4' and '5'

The design overall is a little awkward. Despite what the manpage says, the rough order is:

  • make sure the input sources are in a dict
  • copy the k:v pairs from the dict to env
  • call the converter on each option that was added. May cause env[key] to be updated. For ListVariable in particular, it changes from a string to an instance of a private class; for the cited example, it changed to an int.
  • call the validator on each option that was added, giving a chance to bail if something doesn't mesh.

Calling subst before passing to the validator is how it fetches the updated value saved by calling the converter, but you could just get the raw value via env[key] without doing the subst. I, too, find it a little odd that you let the converter change things, and then you force the result back into a string, but I guess it saves each individual validator from doing its own subst and so is a little more concise?

Is there something actionable in this issue?

@bdbaddog
Copy link
Contributor Author

Sure. I think a subst=True/False on Variable, with default of True would work?

@mwichmann
Copy link
Collaborator

Yeah, probably. After "sleeping on it", I don't get the value of subst'ing a second time, before calling the validator. You've done substitution before calling the converter, which then converts to the right form. Turning it back into a string for the validator just doesn't seem right, unless you believe everything should be a string (if it's not a bool). The docs don't say that is the case, but I'm suspecting that was the thinking during development. For example, the unit test for EnumVariable (and the e2e test as well) test only string values, never, for example, ints.

subst'ing before the converter makes a little more sense: variables coming from the command line are always strings, but the input source can also be python expressions in a file and/or an arbritrary dict, where the values could be almost anything. subst'ing makes the converters simple: get a string, do whatever transformations you need on that; you don't have to first stop and check what kind of data you got. But then you get the case of this issue: the subst was perhaps only intended to cover getting the value from the env, but subst recurses, so if the value accidentally looked like a $VAR, that will be replaced, too. Not sure how much sense that makes.

@mwichmann
Copy link
Collaborator

mwichmann commented Apr 22, 2024

And... a quick check shows that the tests do expect the value to be subst'd, specifically for PathVariable, it even has cascading variables in one case,

    PathVariable('qtdir', 'where the root of Qt is installed', qtdir),         
    PathVariable('qt_libraries', 'where the Qt library is installed', os.path.join('$qtdir', 'lib'))

But it's not hard for validators that need substitution to do it themselves, if one wanted to go that way.

Edit: incomplete info. PathVariable has this specific issue because there's no converter for PathVariable. So it never gets the benfit of the "first subst".

@mwichmann
Copy link
Collaborator

Going back to an earlier comment:

Sure. I think a subst=True/False on Variable, with default of True would work?

This is easy to do - I have a prototype - but after reading an article entitled roughly "The Boolean Trap", one wonders if a string value is better, to allow for possible future flexibility. One could imagine, without having use cases in hand, that controlling whether both converter and validator subst or not might be interesting; or the type of subst (the subst module intself defines those three styles - SUBST_SIG, SUBST_CMD and SUBST_RAW). Maybe that's all just YAGNI, but is a bool unnecessarily restrictive?

More importantly: is this actually worth doing?

@bdbaddog
Copy link
Contributor Author

I think bool is sufficient. If we really found we needed more flexibility then we could complicate the solution more..
I think it's worth doing, it could remove some fairly obnoxious hacks needed to avoid the subst'ing when it's not desired.

mwichmann added a commit to mwichmann/scons that referenced this issue Jun 3, 2024
New parameter do_subst added to the variables Add method,
if false indicates the variable value should not be substituted
by the Variables logic. The default is True.

Fixes SCons#4241.

Signed-off-by: Mats Wichmann <mats@linux.com>
mwichmann added a commit to mwichmann/scons that referenced this issue Jun 3, 2024
New parameter do_subst added to the variables Add method,
if false indicates the variable value should not be substituted
by the Variables logic. The default is True.

Fixes SCons#4241.

Signed-off-by: Mats Wichmann <mats@linux.com>
mwichmann added a commit to mwichmann/scons that referenced this issue Aug 16, 2024
Fix ListVariable handling of a quoted variable value containing spaces.
As a side effect of splitting the former monolithic converter/validator
for ListVariable into separate callbacks, it became possible for
subst to be called twice. The ListVariable converter produces an
instance of a _ListVariable container, and running subst on that
result ends up losing information, so avoid doing so.

While developing a test for this, it turned out the test framework
also didn't handle a quoted argument containing a space, so that
a test case passing arguments to scons via "run(arguments='...')"
could end up with scons seeing a different (broken) command line
than scons invoked with the same arguments typing to a shell prompt.
A regex is now used to more accurately split the "arguments" parameter,
and a unit test was added to the framework tests to validate.

The framework fix had a side effect - it was possible that when run
as part of the test suite, the Variables package could receive a value
still wrapped in quotes, leading to string mismatches ('"with space"'
is not equal to 'with space'), so ListVariable now strips wrapping
quote marks.

Also during testing it turned out that the earlier fix for SCons#4241,
allowing a Variable to declare the value should not be subst'd,
introduced problems for two types which assumed they would always
be passed a string. With subst=False, they could be passed a default
value that had been specified as a bool. Fixed to not fail on that.

Fixes SCons#4585

Signed-off-by: Mats Wichmann <mats@linux.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mongodb Variables Variables() subsystem
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants