Skip to content
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

Add type hinting #192

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open

Add type hinting #192

wants to merge 30 commits into from

Conversation

ggalloni
Copy link
Collaborator

This is the first attempt to add type hinting throughout the repo, mentioned in #189.

I was quite generic on many occasions as this is just supposed to give us a place to work on this and can be refined once we agree on some strategy.

@cmbant
Copy link
Collaborator

cmbant commented Aug 27, 2024

The most useful place to have type hints is annotations for variables that are only defined in the yaml (so consistency can then be checked just using standard editors like vs code/Pycharm). In many places types can be inferred accurately, and little to be gained by adding them explicitly unless useful for doc of public interface.

Note: want to make sure you don't statically import anything that's an optional dependence (e.g. ccl).

@ggalloni
Copy link
Collaborator Author

I added checks for the quantities from yaml files, which now must match the expected types. Let me know what you think of the current strategy.

For the explicit typing in the code, I am a fan of a bit of redundancy in this case, but it is just a matter of taste. I think it makes the code more readable as the user knows, at first sight, what type a certain quantity is. Still, I am planning to go through the modifications and clean the code, because some may be too obvious.

@cmbant
Copy link
Collaborator

cmbant commented Aug 30, 2024

There's a CobayaComponent-level method intended for parameter validation, validate_info (https://github.com/CobayaSampler/cobaya/blob/master/cobaya/component.py#L415). You could override this in one of SOLikeT's base classes to check that all assignments match the types in the annotations. (It shouldn't really be necessary to repeat the type once defined in the attribute's annotation).

But perhaps better would be to add a general "_enforces_types" class attribute to Cobaya, and add code to Cobaya's Component.validate_info to fully validate types for any descendant class that sets _enforce_types is True.
I'm not sure if there's a built-in python function to validate a variable against a type, but Sonnet suggests using typeguard (from typeguard import check_type) or something like this

def validate_attribute(cls, name, value):
    hints = get_type_hints(cls)
    if name in hints:
        expected_type = hints[name]
        if hasattr(expected_type, '__origin__'):
            if expected_type.__origin__ is Union:
                if not any(isinstance(value, t) for t in expected_type.__args__):
                    raise TypeError(f"Attribute '{name}' must be one of types {expected_type.__args__}, not {type(value)}")
            elif expected_type.__origin__ is Optional:
                if value is not None and not isinstance(value, expected_type.__args__[0]):
                    raise TypeError(f"Attribute '{name}' must be of type {expected_type.__args__[0]} or None, not {type(value)}")
        elif not isinstance(value, expected_type):
            raise TypeError(f"Attribute '{name}' must be of type {expected_type}, not {type(value)}")

[Note I am travelling most of the next two weeks, so likely not responding to any Cobaya issues]

@ggalloni
Copy link
Collaborator Author

ggalloni commented Sep 3, 2024

Starting from the code you suggested, I refactored the type-checking functions to avoid repeating the types. Also, now they accept essentially all types, including nested ones (e.g. List[str], Dict[str, float], Tuple[str, str, int], etc).

As a testing ground, I used the Bias class. Still, eventually, something similar can be moved within Cobaya and substitute validate_info (the method _validate_attribute in Bias is essentially equivalent, but allows for all types).

@ggalloni
Copy link
Collaborator Author

Hello @cmbant, now that CCL is working, all tests are OK with this.
Only Python 3.9 needed an adjustment as typing_extensions needs to be there.

@cmbant
Copy link
Collaborator

cmbant commented Nov 25, 2024

Sounds good, I guess could be merged once a new cobaya release.
Btw, I don't think you need provider: Provider, should be inherited.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants