Skip to content

Conversation

@JeffersGlass
Copy link
Contributor

@JeffersGlass JeffersGlass commented Mar 29, 2023

This improves the previous validate() function in pyterminal.ts to be more flexible in how it handles potential values and default values. Previously, configuration options could only be booleans or strings, and the default had to be a string.

Now, the options can be any of the non-array types (string, boolean, number or Object) that could be present in the TOML/JSON from py-config, any of them can be the default, and the type system will catch whether the listed default value is indeed part of the array.

I've moved validate() - now renamed to validateConfigParameter() - from pyterminal.ts to plugin.ts, but only used it to improve pyterminal.ts for now to make it easier to see what's changed. We can use it to validate parameters for the other plugins in follow-up PRs. I've also added validateConfigParameterFromArray(), which handles the (currently) common situation where the valid values are drawn from a small list known ahead of time.

This could probably now use a test or two, hence the WIP. Tests written; this is ready for review. Following Antonio's thoughts about broadening what this could do, I'm reverting this to draft for now. This is ready for review again.

I also want to use this functionality in #1317 (xterm.js), so I'm prioritizing this at this moment.

@JeffersGlass JeffersGlass added the status: WIP PR that is not yet ready for review label Mar 29, 2023
@JeffersGlass JeffersGlass marked this pull request as draft March 29, 2023 02:20
@JeffersGlass JeffersGlass changed the title Improve validate() function for plugin options WIP: Improve validate() function for plugin options Mar 29, 2023
@JeffersGlass JeffersGlass added status: ready PR that is ready for review and removed status: WIP PR that is not yet ready for review labels Mar 29, 2023
@JeffersGlass JeffersGlass changed the title WIP: Improve validate() function for plugin options Improve validate() function for plugin options Mar 29, 2023
@JeffersGlass JeffersGlass marked this pull request as ready for review March 29, 2023 13:28
@JeffersGlass JeffersGlass requested a review from antocuni March 29, 2023 13:28
Copy link
Contributor

@antocuni antocuni left a comment

Choose a reason for hiding this comment

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

+1 for moving the validation logic to plugin.ts and have a robust function which all the plugins can use.

-0 for making it overly complicated w.r.t. types.
If I understand correctly, a good chunk of the logic is needed to make the typescript compiler happy. My question is: is this extra complexity worth it?

Also, I can see how this works if you have a fixed set of options: you just pass all the possible values. But what if I want to specify a generic string?
Or a number?
An integer?
An integer between -4 and 102?

Note that I'm not saying that you should implement all the logic in this PR, but it's probably a good idea to plan ahead and think what are the functionalities that we want to support, because it might change the way we design the validation logic.

@JeffersGlass
Copy link
Contributor Author

JeffersGlass commented Mar 29, 2023

If I understand correctly, a good chunk of the logic is needed to make the typescript compiler happy. My question is: is this extra complexity worth it?

It also reduces complexity in unit tests - once the type system guarantees that default will be a member of possible_values for every configuration option, we can test checkConfigOption essentially once. Otherwise, I think we'd need a test to ensure that the default for terminal_options is valid, another that the default for docked_settings is valid, etc, because there'd be nothing preventing someone down the road from writing:

checkedConfigOption({ possible_values: [true, false, 'auto'], default: 'BANANAS' });

other than the integration tests that involve those individual attributes, which may or may not consistently handle 'invalid' options themselves.

Also, I can see how this works if you have a fixed set of options: you just pass all the possible values. But what if I want to specify a generic string? Or a number? An integer? An integer between -4 and 102?

This is a great thought, and not something I'd considered... let me muse on it and see if there's a straightforward line to something that would allow that.

@JeffersGlass JeffersGlass added status: WIP PR that is not yet ready for review and removed status: ready PR that is ready for review labels Mar 29, 2023
@JeffersGlass JeffersGlass marked this pull request as draft March 29, 2023 20:03
@JeffersGlass
Copy link
Contributor Author

I've got a promising start an a change where a user could pass their own validation function. Needs some more API thoughts but the bones are there. Reverting this to draft for now until it's ready... probably will want a re-review when that's complete.

@JeffersGlass JeffersGlass mentioned this pull request Mar 30, 2023
14 tasks
@JeffersGlass JeffersGlass marked this pull request as ready for review April 3, 2023 15:57
@JeffersGlass JeffersGlass requested a review from antocuni April 3, 2023 15:57
@JeffersGlass
Copy link
Contributor Author

JeffersGlass commented Apr 3, 2023

@antocuni this is ready for a re-review, when you have a chance.

validateConfigParameter is now much more general - it accepts a validator function which it uses to determine whether the user-supplied value is valid, which should allow for a lot of flexibility down the road, like the cases you listed.

validateConfigParameterFromArray is a helper method which will be broadly applicable to the parameters we use at the moment, for situations where the valid values are drawn from a small list we know ahead of time.

One can imagine adding more helper methods down the road - validateConfigParameterIsString, validateConfigParameterIsPositiveNumber, etc, , but for now I've just written the one needed for pyterminal.


~~test_pyrepl_exec_hooks is failing intermittently, but that's unrelated. Still sad though. ~~ #1363 fixed the issue! Huzzah!

@JeffersGlass JeffersGlass added status: ready PR that is ready for review and removed status: WIP PR that is not yet ready for review labels Apr 6, 2023
* if not, throw an error explaining the bad value.
* This is the most generic validation function; other validation functions for common situations follow
* @param options.config - The (extended) AppConfig object from py-config
* @param {string} options.name - The name of the key in py-config to be checked
Copy link
Member

Choose a reason for hiding this comment

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

Is @param {string} options.name the correct way of specifying params in the docs?

I ask since -- in other places, for example: @param filePath is written i.e. without the type. And name of the variable is written first. The above example I gave is present in fetchJSPlugin function in main.ts

Not sure what the best standards are, but wanted to highlight regardless...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for calling it out - I think the syntax here is correct? I'm not a JSDoc expert - I'm following the @param documentation, specifically the Documenting a parameter's properties section about adding types and a parameter's properties.

}

// Members of py-config in plug that we want to validate must be one of these types
type BaseConfigObject = string | boolean | number;
Copy link
Member

Choose a reason for hiding this comment

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

Do you want to allow undefined here perhaps?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we want to - an undefined value coming from py-config is how we signal that the plugin should supply a default value:

https://github.com/JeffersGlass/pyscript/blob/3fa082df26f1a1d702779e1ac93a875426e71313/pyscriptjs/src/plugin.ts#L299-L308

So if a plugin wants to identify whether the value was left undefined in the config, they should set a sentinel value as the default and look for that at runtime.

Copy link
Member

Choose a reason for hiding this comment

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

I only ask since you typecast it explicitly here: https://github.com/JeffersGlass/pyscript/blob/3fa082df26f1a1d702779e1ac93a875426e71313/pyscriptjs/src/plugin.ts#L298

and check for undefined in the very next line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahhh I see now - sorry was writing the merge as you posted this.

Copy link
Member

@madhur-tandon madhur-tandon left a comment

Choose a reason for hiding this comment

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

Tests are Great! Thanks @JeffersGlass

@JeffersGlass JeffersGlass merged commit dfa116e into pyscript:main Apr 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: ready PR that is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants