-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Can we have a Arg::validate_with(self, Box<Validator>) -> Self
function?
#572
Comments
Apologies for how long it's taken me to get to this, I've been travelling. I might be misunderstanding what you're trying to do, but the current implementation should allow for that already unless you're talking about not knowing the function beforehand. i.e. the difference in what you're proposing, is using dynamic dispatch of a trait object instead of statically dispatching to a particular function. If it's something other than this, please elaborate. If using dynamic dispatch is truly what you're wanting to do, I'm not opposed to adding that, but I'd want to name it something less...overlapping? Or we'd have to really document well what the difference is and when to use each. |
The point is simply to be able to pass context to the validator function. For example, if I have an argument which gets a path, I might want to check whether this path exists. But I also might want to check whether this is a file, is readable, is not longer than 100kloc, etc. This could all be done by one validator function, yes. But if my App runs in different states, I might not mind if the file is above 100kloc or even readable (for example if I have a One way how to solve the problem from above is using several validator functions, each function for one of the requirements. Another one would be to be able to pass state to the validator function. I thought the latter would be a bit nicer, so I started to implement it in #573. I hope I did not overlook an already existing functionality with this! 😄 |
I was actually about to open an issue with a similar goal. In my case, I have some validators which could be generic (things like "path is readable") but they're not because I need my error messages to indicate which argument is failing validation. (And I don't care how it's achieved, as long as the result is acceptably easy for users to understand.) |
Related to #1471 |
FWIW, I'm quite keen on this feature as well. Not so much dynamic dispatch per se, but more simply the ability to be able to pass in a parameter of my own choosing to the validator in addition to the what clap itself passes. |
I see that we've got two different questions on the table here:
Maybe we could add @ssokolow @bradwood @matthiasbeyer To avoid haunting ghosts, can somebody supply a code snippet that is of an issue? Something that you'd like to do, but it's either currently impossible or possible but too cumbersome? The snippet should also reveal how trait objects could have solved the issue. |
It's been over three years and I can't remember what situation I specifically needed this for, given that the simple case is adequately satisfied by how Clap prefixes the validator-returned message with Heck, given that I've moved to StructOpt (and am about to test out Clap 3.x's derive API), it'd probably be a good idea to think up a more declarative-API-friendly solution to custom messages for generic validators anyway if such a feature comes to pass. |
I suppose your understanding of what "generic validators" being is different from mine. Could you elaborate? Preferably with (pseudo) code examples. Why and in what do you see validators being not flexible or friendly enough for the derive? |
By "generic validators", I mean things like (Once I've got things cleaned up, I want to flesh that out into a collection of them and split it out into a crate for others to use independent of my project boilerplate.) For example, I might have a script which takes two or three positional arguments and want more than just the In that context, I envision defining a wrapper for each validator assignment, just to alter the error message, will result in both a cluttered (Also, please excuse the mess in |
And that's a third question on the table, and I think it's quite irrelevant to trait objects - clap would use it's own prefix indefinitely. I suggest you to open a separate issue for that. From what I've picked from OK, let's wait a bit for the other participants supply their input. Otherwise I'll proceed to closing this issue as "maintainers don't get what the request is". |
I wasn't specifically talking about trait objects. I was explaining a use case which, ideally, shouldn't require that a second feature be implemented, given the overlap. (Both involve the desire to specify a custom error message for a specific use of a general-purpose validator.) If anything, it was an argument to not settle on the idea of using trait objects too quickly. |
@ssokolow Here's your problem as I perceive it: Clap validators don't have the full control over the error message displayed. The message consists of two parts: the Your desire is to modify (or just omit) the prefix. Is my understanding correct? If so, this is unrelated to the issue (which is totally about trait objects that can't possibly help you with it), and I urge you to open a separate issue for that if you want it to be addressed. |
No, my desire is to minimize the boilerplate involved in per-field customization of failure messages on fields that share the same stock validator. I mentioned it here because the initial poster's rationale is:
...and that's how I'd have accomplished it in Python. |
And then we're back to the question of why you can't just capture the "custom data" in the closure. I took a closer look and found that the validator fns have |
@ssokolow Do you need the ability to mutate the context? Is |
Ugh, I'm struggling to come up with a meaningful example. @ssokolow Could use your help here. |
Assuming you want something minimal enough that a working example could be presented in compact form, you could do a generic "positive, non-zero integer" validator where the failure message is overridden to something specific like "Number of archive volumes must be a positive integer". It's most useful when the placeholder from |
I mean something that would demonstrate usefulness of the context, I can't come up with an example that doesn't look made up. Since you were asking for the context passing ability, I assume you have a good idea of what the example might be. It doesn't have to be too concise, 50 (or maybe even 100) LOC will do. And what about the mutability problem? Right now, you can only have an immutable (shared) reference to the captured context, and it doesn't allow you to mutate anything. Interior mutability won't help you too, because the validator has to be |
I'll see what I can do, but life has been busy the last few days and I haven't even been able to get to things I specifically chose to take on in as timely a fashion as I expected. |
Sorry for going silent. One of my hard drives started to give signs that it may fail soon, and I'm due for a bunch of hardware replacement anyway (eg. can you believe I still don't have an SSD?), so, I've been busy double-checking my backups and preparing for an all-at-once large-scale system upgrade when the new hardware arrives. I'll let you know once I'm ready to give you something. |
Mate, I found you. We should unite and start a new brand movement "weirdos who don't upgrade hardware while it works fine". Affiliate it with bitcoin and bigdata and the world will succumb! |
*chuckle* I wouldn't say "works fine". It's quite annoying when my nightly backups push everything out of the disk cache and the system then chugs as I have to deal with the consequences of having so many of my applications depending on a forest of small files that need to be seek-time'd back into the cache from all around the platter. That, and I have another drive from the same production run in one of my machines that started to get bad sectors, so no need to play chicken with it and risk losing data added since the last nightly incremental. (They've both been running more or less 24/7 since 2007.) |
Well, I think the " be able to pass context to the validator function." is solved now. |
I have a use-case where it would be nice to be able to pass custom data to the validator (mainly for passing the error message).
My use-case is: I want to write a validator which checks an argument for whether it is a path and whether this path exists. If the path does not exist, is not readable ... etc, I want to return an appropriate error message.
I want to implement this functionality in a sub-crate of my project and I want to do it generically, so one has only to construct an object and tell it "if the validation fails, use this error message: 'someerrorhappened'". I could then use this type to tell clap "Hey, use this as validator". I would have the benefit that I would write the validation function once, but still have a bit of dynamic in creating my error messages.
I propose a trait
and a function on
Arg
:The text was updated successfully, but these errors were encountered: