cyclopts
cyclopts copied to clipboard
Interactive shell created according to docs also includes shell command
When creating the interactive shell, you probably don't really want to expose the command that, well, creates the shell. Currently, you can enter a shell from a shell etc., endlessly. There is no way to prevent that since all the commands get exposed in the shell.
Maybe the simplest solution would be to add an argument allowing you to exclude commands when creating the interactive shell? Backwards compatible and not expanding the API unnecessarily (my another idea was a special decorator for the command calling the shell, but that's probably not ideal).
If that sounds like a sensible solution, I could try to add that, and then we should probably document it too.
I had this partially implemented at one point, but ultimately decided:
- There are some niche situations where you may want to launch a shell from a shell, so I don't want to hardcode making it forbidden to launch a shell from a shell.
- This functionality can be shoehorned in by the user via the
dispatcherparameter if they desire that functionality.
The solution isn't perfect, but it's a fairly general solution that doesn't complicate the API further. A downside of this approach is that the commands are still available from the help page. We can refine this, but I was waiting for someone to actually ask for this :D .
As for 1., yes, I didn't actually want to exclude it by default, but rather allow to exclude it explicitly with an exclude argument like exclude=[command_name1, ...]
Of course for the time being you could just add a note to the dispatcher documentation showing this use case as an example, but I agree, the command still showing up in the help is still not ideal, so I think the explicit exclude makes sense.
Dunno what your approach to this library is, but especially given that there isn't yet a big adoption, I'd probably just add those kinds of things and if you come up with a better solution in the future, would not hesitate around changing that part of the API. It's not really a core feature or anything that would make many people mad if it changed in the future. I myself would understand that if I update the version of cyclopts, some more niche elements of the decorators, or stuff like interactive prompt etc could need an update.
Basically the thing I think you should most care about is making sure you stay true to the "keep function signatures (and generally, programs) simple if we can and reuse generic Python features as much as we can" principle which seems to be the major selling point. Implementation details may and will change I assume.
I'll try and updating the documentation.
In no particular order, some driving philosophies I've had:
-
Consistency is king. If something is slightly more convenient, but the behavior inconsistent, don't do it. If something is significantly more convenient, then consider it.
-
Try and leverage python builtins as much as possible (e.g.
Annotated). This helps natural compatibility with other libraries/tools. -
Behavior should be intuitive without reading every nook & cranny of the docs. This follows from (1). For example, the field
default_parametercan be supplied at nearly every location in the hierarchy, and the logic is the same every time. This also extends to things like "the function docstring should be parsed." -
If the configuration is more complicated than the implementation, don't implement it. It clutters the namespace and complicates the ruleset a user has to learn.