connor-makowski / type_enforced

A pure python type enforcer for annotations. Enforce types in python functions and methods.
MIT License
45 stars 2 forks source link

Provide ability to enforce with Constraints #36

Closed kakaday22 closed 7 months ago

kakaday22 commented 7 months ago

Hi!

First of all great library and thank you for your support.

I been using the library and I noticed that it would be very useful if the library can support type hint with constraints. Similar to 'Literal' but constrain based on other comparators (gt, lt, ge, le, eq, pattern, other)

Use case I have:

from type_enforced import Enforcer
from typing import Annotated

PositiveInt = Annotated[int, Constrain(gt=0)] # constraints int to > 0
CustomInt= Annotated[int, Constrain(ge=0, le=100)]  # constraints int from [0-100]
CustomString= Annotated[str, Constrain(pattern=r".*running.*")]  # constraints strings to match regex pattern

@Enforcer
def myfunc(value: PositiveInt):
    # logic here with value
    pass

myfunc("a") -> throws TypeError due to not been an int
myfunc(-1) -> throws TypeError due to int lt 0
myfunc(10) -> valid response

In annotated portion the signature can be Annotated[, ], where callable returns True/False is passed argument satisfy Constraint and from there proceed to throw error or not

Is this a possible feature to have in the near future?

connor-makowski commented 7 months ago

This is a great feature request and the way I see it now quite possible. One thing I would need to take into consideration is time impact for existing uses. If near future means a few weeks, I would say this is possible depending on my free time.

kakaday22 commented 7 months ago

Thanks for the quick response!

I am happy to collaborate with you. I actually just finished a PoC for this feature to see the feasibility

from type_enforced import Enforcer
from type_enforced.constraint import Constrain

PositiveInt = Constrain(int, gt=0)

@Enforcer
def myfunc(value: PositiveInt):
    print(f"{value=}")

def main():
    myfunc(-1) # -> throws ConstraintError exception as  constraint was violated
   myfunc("some_string") # -> throws TypeError as  the type hint was constraint to int

if __name__ == '__main__':
    main()
connor-makowski commented 7 months ago

I'm always happy to collaborate. Im taking this week off, but I would be happy to check this out next week. PRs are always welcome. I'll need to set up a collaborator agreement for this repo too.

kakaday22 commented 7 months ago

I took the liberty and implemented the feature, created a PR. Feel free to review or modify as convenient 😄

connor-makowski commented 7 months ago

Nice job here. I ended up merging in the changes and making a number of modifications based on coding style preferences, but all in all, nice job with the PR. Thanks a ton.