-
Notifications
You must be signed in to change notification settings - Fork 129
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
Enhance type checking #382
Conversation
The new code is raising a Do you have an idea why this could be happening? |
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #382 +/- ##
==========================================
- Coverage 74.57% 74.25% -0.33%
==========================================
Files 147 147
Lines 11200 11247 +47
==========================================
- Hits 8352 8351 -1
- Misses 2848 2896 +48 ☔ View full report in Codecov by Sentry. |
I left the validation of bools as it was and added an In this way, one can force type checking by setting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting to see this. Bit mixed feeling though, a bit complicated than hoping (for something is just checking), not very clear how robust it is.
cobaya/model.py
Outdated
@@ -589,7 +589,7 @@ def logpost(self, | |||
return self.logposterior(params_values, make_finite=make_finite, | |||
return_derived=False, cached=cached).logpost | |||
|
|||
def get_valid_point(self, max_tries: int, ignore_fixed_ref: bool = False, | |||
def get_valid_point(self, max_tries: Union[int, str], ignore_fixed_ref: bool = False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has to be int as used in the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @cmbant, thanks for the feedback on this!
Indeed I think that, technically, that could be a float, as it is used just for evaluations like if tries<max_tries
. Still, I wouldn't feel comfortable with having a floating max_tries
, right?
Also, that number comes from the value
of a NumberWithUnits
, already parsed, so that should be either a float or an int. Thus, I would drop the Union
with str
(going back as it was before).
@@ -37,7 +37,7 @@ def cosmomc_root_to_cobaya_info_dict(root: str, derived_to_input=()) -> InputDic | |||
name = name.replace('chi2_', 'chi2__') | |||
if name.startswith('minuslogprior') or name == 'chi2': | |||
continue | |||
param_dict: ParamDict = {'latex': par.label} | |||
param_dict: 'ParamDict' = {'latex': par.label} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actual type should be better than deferred where possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed completely deferring 'ParamDict'. This comes at the cost of moving the definition of ParamsDict
in typing
a few lines below, after the definition of ParamDict
. Let me know what you think of this
cobaya/component.py
Outdated
@@ -331,6 +331,8 @@ class CobayaComponent(HasLogger, HasDefaults): | |||
_at_resume_prefer_new: List[str] = ["version"] | |||
_at_resume_prefer_old: List[str] = [] | |||
|
|||
enforce_types: bool = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should start with _ as not something we want changed by yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure about this. Indeed, adding the underscore we cannot enforce types neither through the yaml
nor through the info dict (as I do in the test for instance). So, I guess this becomes a question of what default behavior we want to use. If the default value of enforce_types
is False
, the user can only enforce types on components he/she defines with that flag to True
. But, for example, types of built-in samplers and such cannot be checked (except if we add in their definition the opposite flag). This may be a good choice since I guess that types of built-in stuff are checked anyway, in a way of the other. Vice versa, with enforce_types = True
by default, everything will be explicitly checked and there is no need for the user to access that.
Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would probably have to be False by default to keep people from hitting annoying errors and compatibility with existing external likelihoods. Was thinking of this more as an option for likelihood developers who support accurate type hint in their code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok great, then I'll make it private and default at False
👍
cobaya/component.py
Outdated
elif expected_type is int: # for numpy integers | ||
if value == float('inf'): # for infinite values parsed as floats | ||
return isinstance(value, float) | ||
return isinstance(value, int) or "numpy.int" in str(type(value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can simplify some of this using generic numbers.Number types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was thinking about using some more generic types, I will commit that soon.
cobaya/parameterization.py
Outdated
@@ -42,7 +42,7 @@ def is_derived_param(info_param: ParamInput) -> bool: | |||
return expand_info_param(info_param).get("derived", False) is not False | |||
|
|||
|
|||
def expand_info_param(info_param: ParamInput, default_derived=True) -> ParamDict: | |||
def expand_info_param(info_param: ParamInput, default_derived=True) -> 'ParamDict': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ops, probably a search and replace gone wrong...
cobaya/parameterization.py
Outdated
@@ -76,7 +76,7 @@ def expand_info_param(info_param: ParamInput, default_derived=True) -> ParamDict | |||
return info_param | |||
|
|||
|
|||
def reduce_info_param(info_param: ParamDict) -> ParamInput: | |||
def reduce_info_param(info_param: 'ParamDict') -> ParamInput: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed all of these, see above
cobaya/samplers/mcmc/mcmc.py
Outdated
@@ -56,11 +56,11 @@ class MCMC(CovmatSampler): | |||
|
|||
# instance variables from yaml | |||
burn_in: NumberWithUnits | |||
learn_every: NumberWithUnits | |||
output_every: NumberWithUnits | |||
learn_every: Union[NumberWithUnits, str] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why only some of these changed. In terms of usage, optional str is probably not very helpful since should be converted at read in, maybe NumberWithUnits and more flexible check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the only ones causing errors, but, following your suggestion, I moved the problem on the type-checking side as we know the NumberWithUnits
can come in as a string.
…nto checking_types
For assessing the robustness of this, I am not sure how to test it. An idea would be to switch the default of |
|
||
if hasattr(expected_type, "__origin__"): | ||
return self._validate_composite_type(expected_type, value) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are only the values general here, not also the expected_types?
e.g. any Mapping type could accept any Mapping value? (e.g. empty_dict is MappingProxyType)
Note also in numpy can also end up with "numbers" that are zero-rank arrays like np.array(1), which I suspect may not pass isinstance(Real), though not sure if that's ever an issue for setting parameters.
The best I can come up with that works with empty_dict, Sequence, Tuple[float] and TypedDicts, and allows numpy arrays for Sequence[float] and Tuple[float], is something like this:
However, is_typeddict is only in core typing from 3.10. |
Hello @cmbant, thanks for your help with this! |
OK great, let me know any probs. I also just pushed change to hopefully also make it work with deferred types. |
Currently, all non-WIndows builds are failing due to CCL not building correctly... |
Except that you don't have _enforce_types=True, only enforce_types... |
I fixed that (I thought I already did...) and am getting an error handling This seems to happen because that is dealt with only if
|
Can you give specific example? |
I made a fix, looks like running OK on windows |
I merged, thanks! |
The method
validate_info
ofCobayaComponent
, checks onlybool
.This PR is enhancing that to check every relevant type, including generic types (List[], Dict[], Tuple[], etc).