-
Notifications
You must be signed in to change notification settings - Fork 10
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
Should positionals
be opt-in when strict: true
?
#85
Comments
That seems pretty reasonable - maybe a “positionalArgs” option, that can be true, or an integer? |
Would the integer be a minimum, a maximum, or a precise number of positional arguments to expect? None of those are very satisfying answers, I think. I suppose you could allow specifying both a minimum and a maximum, at the cost of even more config knobs. |
I’d expect a maximum, but yes, it could instead be true, or an object with min/max integer properties. |
Quick comment. Good description! However, I don't like adding configuration to use basic features of the parser, so still thinking about it. |
Well, the other half of that is that absent this config options, scripts which don't want positionals but still want to be well-behaved will need to add extra logic to use the parser at all: So one of the two groups (expecting-positionals and not-expecting-positionals) is inevitably going to have to add something, to get the behavior they want and be well-behaved. Not being able to configure this amounts to deciding that the not-expecting-positionals group is the one which will need to add something. Which is fine, in general, but my concern is that in this particular case that group is not even going to notice they needed to add something to be well-behaved, and consequently ship a poorly-behaved script, which is (I think) a bad outcome. (And, separately, having this bit would allow better error messages, which I think is valuable.) |
This is a thinking-out-loud comment, not fully formed. I like the concept, but I am concerned it is a slippery slope of diminishing returns. At what point do we say no? A deliberately over-stated description of "well-behaved", but where do we draw the line?
The extreme end-point is a safe "well-behaved" subset of functionality that requires extensive configuration and does not behave like other programs. And tutorials will say "use strict:false to simplify setup"! Ok, please resume normal levels of cynicism and scepticism. |
Why must there be a point where we say no? Zero config strict mode means that any time there’s something we discover is a footgun, we’d want to make the default behavior safe, even if that means common cases would require more configuration. |
Some common use cases are:
|
I don't think "zero config" belongs in that sentence. 😉 |
Ok, I'll bite. Because there isn't agreement there is demand or a need for a bullet-proof argument parser built into node. That wasn't in the previous proposal, or the initial spec here, or the current spec. Because each additional piece of safety configuration offers the potential to detect one more footgun, but makes the library harder to get started with, or less convenient for the end user. As the starting configuration gets more intimidating, the chances people start from a boiler-plate starting configuration which bypasses the protections increase. Or people use I care about the cost-benefit ratio. I think there is often a trade-off between safety and usability and some protections are not worth the penalties. To be clear, I opened the issue about whether there is going to be a strict mode at all, and I would prefer to include a strict mode in the first implementation. But not bullet-proof. |
Yeah, I agree this slope is pretty slippery. I think the heuristic I would use for
The third thing, in particular, means that there are always going to be scripts which are not well-behaved by my definition without the author performing additional validation. That's OK, as long as it's reasonably obvious to authors that they are going to need to do that validation themselves. I think having a boolean for I could see an argument [heh] for having This of course hinges on author expectations, and in particular how many people we think are going to run into a given sharp edge. I think it's going to be pretty common to write applications which aren't expecting any positional arguments, so I think that's a scenario we should weight pretty highly. There's always going to be someone out there who is surprised by, say, the fact that |
Nice heuristic. Thanks for taking the time to lay it out! I am up for an opt-in boolean for positionals.
If |
What is this opt-in property named? Trying a couple of other variations: const { values, positionals } = parseArgs({ strict: true, positionals: true, options: knownOptions });
const { values, positionals } = parseArgs({ strict: true, allowPositionals: true, options: knownOptions });
const { values, positionals } = parseArgs({ strict: true, expectPositionals: true, options: knownOptions }); |
I would call it |
I still prefer a longer name. A few reasons:
|
I think I've been nudged towards the argument that options should default to I'm supportive of the My preference would be |
+1 for |
It's not very useful to have the option if the default is to allow positionals. After all, if a script author remembers that they need to explicitly disallow positional arguments for their particular application, they can write That is, I think that making positionals opt-in is in keeping with the "you will need to provide config for each option that you want to accept" design. I regard positionals as being a kind of option that you want to accept. If we don't accept this point of view, I don't think there's much benefit to have a config option to disallow them at all, since a script author can do that themselves trivially. |
I also think either And I am ok either way. |
Shall we just take this feature to a vote with 👍 (allowPositionals defaulting to false), 👎 (launching without allowPositionals). |
@shadowspawn, @iansu, anyone else want to chime in ☝️, otherwise I'd say we go the route @bakkot is suggesting by a narrow margin (2 👍, to 1 👎 ). |
@bakkot @shadowspawn, looks like we might not quite make If there's a chance it addresses our last open point of discussion, I'm pro Worst case scenario, we land in an early minor release of Node 18, and people can start to rely on |
I think it would be a rush for tomorrow. We have not landed any of strict yet. I suggest we do not attempt this now, rather than rush a decision. Reasoning:
Of historical interest, it used to be very hard to check for excess positionals in Commander including by client. It irritated me but not many issues touched on it. I added support for detecting excess with the intention of turning it on by default, but broke a number of my own unit tests and decided to make it opt-in to ship with less churn for existing users. I know that is an argument each way, but my point is that the lack of checks did come up much as a reported issue. |
To be clear, I suggest this issue misses out on MVP. Not that we delay MVP. |
@bakkot are you okay with the compromise of landing this post MVP, the advantage of trying to get in for Node v18.0.0 (_not to overpromise, as we might already be too late for this.) is we don't need to spend the next year addressing bugs where we explain to people that |
That doesn’t seem like that big a deal to me - it’ll just be listed in the docs. |
I think you'd know better than I would the costs and benefits of introducing an additional restriction like this after shipping. If you think a restriction like this can be reasonably added in a post-MVP version, that's fine with me. If not - if you think people are going to depend on getting positionals, such that node wouldn't want to break those people by making positionals opt-in - well, I don't know how serious a cost it is to miss 18.0.0, so that's hard for me to weigh that against never having this restriction. Certainly it's not the end of the world if this gets left out forever, though. It'll be another thing many consumers need to always remember to validate lest their application silently drop input, to the annoyance of their users. But we can't eliminate all of those cases, so having another big one, while in my view it would be quite unfortunate, isn't fatal. |
I think there's a tradeoff, my experience with adding code coverage to Node.js, which landed in a minor release, was that the feature didn't see significant adoption until the next major releases -- I think people are hesitant to deliver an application that will only work with a certain version range of runtimes. However, I do want to be careful not to force My concerns about landing in a |
In my experience, pre-LTS minors of node 18 just won't matter; it's only the first LTS minor that people are likely to be "stuck" on. I think as long as we land in node 18 prior to LTS, we're perfectly fine, and I'd prefer to land with as full a featureset as we think is warranted (including this issue). |
I'll defer to y'all's judgement on this. |
I'd rather we not rush, let's take our hat out of the running for And this frees us up to work on this feature as well. Thoughts @shadowspawn? |
I think the timezone difference means this is a done deal with parseArgs landing after 18.0.0!? [edit: I added the "after", missing in the first draft and sorry for any confusion if you saw that!] I abstained from the vote, as I am ok either way. To be clear:
[edit: sorry if that was a bit blunt!] |
A common approach for ideation is to go wide, then come narrow down again with consensus, and can focus on what is left. So for narrowing, are we agreed that:
Please vote to gauge consensus. |
This one
Edit: 1 and 3 conflict a bit. Retracting this suggestion. Perhaps better the configuration is just ignored completely in |
Naming: shall the opt-in configuration be named (Note: I am against Please vote to gauge consensus. |
I also prefer the more descriptive
I'm also okay either way at this point, it seemed like we had one more vote for adding this feature than not. @bakkot it sounded like you'd be willing to implement this feature? why don't you create a PR, and we can reference it in the PR to merge parseArgs into Node.js. If no one makes a strong argument against We're calling |
@bcoe Happy to make a PR, but it might be a day or two. |
Is there a desired timeframe @bcoe ? (I am guessing perhaps no fixed deadline, just as soon as convenient?) |
No set deadline, but it can get annoying keeping an upstream PR in sync for too long, mid next week might be a good goal for MVP into Node.js? We'll have an opportunity to do some follow up PRS before 18.1.0. |
Elsewhere I've mentioned I think the goal of
strict: true
should be that you can write a well-behaved script just by callingparseArgs
with your options configured, with no further validation required (except validation of the values of value-taking options, which is out of scope). Here by "well-behaved" I mean it will surface an error to the user if they try to use the script in a way the author did not intend.Right now, if I'm writing a script which does not expect positional arguments, and I do the obvious thing of
but the user passes a positional argument, I'm never going to notice, and the user's input is going to be silently dropped. And it's very likely that I'll end up shipping this, because it's probably not going to occur to me to try passing a positional argument and so I will never notice this problem.
That seems contrary to the goal above. So I'd like to suggest having a
positionals
configuration option, which must be explicitly opted into (whenstrict: true
). For people who want positionals, this ought to be a small hiccup: they'll notice right away that passing a positional argument doesn't work. And for people who don't, they'll get the right behavior. So neither group is at risk of shipping a script which is not well-behaved.(Good errors help here: e.g., "this script has not been configured to take positional arguments" is clear to users that they're misusing the script, and to authors who want to take positional arguments that they need to configure it to take positional arguments.)
Another advantage of having this piece of information is that it lets you improve error messages. If the parser encounters an unknown flag
--foo
, and the script author has explicitly opted in to positionals, the error message can suggest that if the user intended to pass--foo
as a positional argument they can do so by putting-- --foo
at the end of the command invocation. But you wouldn't want to suggest this in a script which isn't using positionals.The text was updated successfully, but these errors were encountered: