-
-
Notifications
You must be signed in to change notification settings - Fork 8
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
feat: Expand default functionality to enable fallback lookups. #180
Conversation
Trying it out locally. The classes (default, defaulttype, env, prompt, confirm, valuefrom) should probably implement cappa.Env("SOME_ENV_VAR") | cappa.ValueFrom(from_config, "some_config_value") ...to display as:
...and there's no way to get this result automatically, of course. But I don't see how the user could provide their own string to # If `ValueFrom` accepts `helptext`, the same name cannot be used in `some_callable`.
cappa.ValueFrom(some_callable, "some_config_value", helptext="configuration value `some.config_value`")
# Instead, maybe accept this?
cappa.ValueFrom(
some_callable,
args=["some_config_value"],
# These two don't clash anymore.
kwargs={"helptext": "whatever"},
helptext="configration value `some.config_value`",
) Or maybe you have another idea on how to customize the display of defaults class FromConfig(ValueFrom):
def __init__(self, attr_name: str, conf_name: str) -> None:
super().__init__(from_config, attr_name)
self.conf_name = conf_name
def __str__(self) -> str:
return f"configuration value `{self.conf_name}`" |
Actually it looks like such defaults are not displayed at all in the CLI help. And it turns out I'd need a |
Is there a reason why exceptions raised when evaluating a default are ignored? def __call__(self) -> tuple[bool, Any | None]:
for default in self.sequence:
try:
value = default()
except Exception: # noqa: S112
continue I got bit by this. My Personally I'd let exceptions bubble up to fail early 🙂 |
There seems to be an issue with recognizing defaults, because my default value obtained from assert isinstance(arg.default, Default), arg
is_parsed, value = arg.default() Or it simply comes from if value is not None:
return False, value in |
i have a bunch more changes pending, not yet passing all tests. but stuff like |
Yes that makes sense. We must make sure it's documented in the "defaults are not parsed" paragraph 🙂 |
946be14
to
10e67bb
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #180 +/- ##
===========================================
+ Coverage 99.35% 100.00% +0.64%
===========================================
Files 25 26 +1
Lines 2310 2422 +112
Branches 465 522 +57
===========================================
+ Hits 2295 2422 +127
+ Misses 12 0 -12
+ Partials 3 0 -3 ☔ View full report in Codecov by Sentry. |
`ValueFrom` objects.
10e67bb
to
c46749e
Compare
This ended up being a much larger diff than I'd originally thought it would be, but it also simplified a bunch of the default handling for Env/Prompt and made doing default_factory properly trivial (implemented it in literally 2 minutes). So I think it was clearly an overdue concept/refactor even if I trashed the whole State concept. I think State ends up being reasonably analagous to But it seems like it should have utility any time someone wants to pass data from the calling context into something inside cappa's handling anyways, so 🤷 |
Thank you so much! I'll try to test and report back, but do merge if you think it's ready (don't wait for me) 😄 |
I'll merge now just because it'll otherwise block other work, but i'd love if you were able to test before I cut a release |
I just read the docs, they are great! 🚀 It's a big PR indeed 😂 |
Default
object with associated fallback semantics for sequences of default handlers.ValueFrom
for handlingdefault_factory
lazily, as well as arbitrary function dispatchState
as object accessible toinvoke
,Arg.parse
, andValueFrom.callable
for sharing state amongst different stages of argument parsing.