Skip to content

Decorator

Polyforce is quite versatile and for different tastes. You can use the PolyModel for you own objects or you can simply use the polycheck decorator for everything else.

polycheck

This is the decorator that helps you with everything you need without the need of using an inherited object.

The same parameters of the PolyModel are also allowed within the polycheck.

How to use it

When using the polycheck you must import it first.

from polyforce import polycheck

Once it is imported you can simply subclass it in your objects. Something like this:

from typing import List, Union

from typing_extensions import Self

from polyforce import polycheck


class Movie:
    def __init__(
        self,
        name: str,
        year: int,
        tags: Union[List[str], None] = None,
    ) -> None:
        self.name = name
        self.year = year
        self.tags = tags

    @polycheck()
    def get_movie(self, name: str) -> Self:
        """
        Returns a movie
        """
        ...

    @polycheck()
    def _set_name(self, name: str) -> None:
        """
        Sets the name of the movie.
        """

    @polycheck()
    @classmethod
    def create_movie(cls, name: str, year: int) -> Self:
        """
        Creates a movie object
        """
        return cls(name=name, year=year)

    @polycheck()
    @staticmethod
    def evaluate_movie(name: str, tags: List[str]) -> bool:
        """
        Evaluates a movie in good (true) or bad (false)
        """
        ...

When adding the polycheck object, will enable the static type checking to happen all over the functions declared.

Ignore the checks

Well, there is not too much benefit of using polycheck if you want to ignore the checks, correct? Well, yes but you still can do it if you want.

There might be some scenarios where you want to override some checks and ignore the checks.

For this, Polyforce uses the Config dictionary.

You simply need to pass ignore=True and the static type checking will be disabled for the class.

It will look like this:

from typing import List, Union

from typing_extensions import Self

from polyforce import polycheck


class Movie:
    def __init__(
        self,
        name: str,
        year: int,
        tags: Union[List[str], None] = None,
    ) -> None:
        self.name = name
        self.year = year
        self.tags = tags

    @polycheck(ignore=True)
    def get_movie(self, name: str) -> Self:
        """
        Returns a movie
        """
        ...

    @polycheck(ignore=True)
    def _set_name(self, name: str) -> None:
        """
        Sets the name of the movie.
        """

    @classmethod
    def create_movie(cls, name: str, year: int) -> Self:
        """
        Creates a movie object
        """
        return cls(name=name, year=year)

    @staticmethod
    def evaluate_movie(name: str, tags: List[str]) -> bool:
        """
        Evaluates a movie in good (true) or bad (false)
        """
        ...

Tip

The decorator has the same fields as the PolyModel but since polycheck is done on a function basis, applying ignore+True is the same as not adding the decorator at all. This serves as example for documentation purposes only.

Ignore specific types

What if you want to simply ignore some types? Meaning, you might want to pass arbitrary values that you don't want them to be static checked.

from typing import List, Union

from polyforce import polycheck


class Actor:
    ...


class Movie:
    def __init__(
        self,
        name: str,
        year: int,
        tags: Union[List[str], None] = None,
    ) -> None:
        self.name = name
        self.year = year
        self.tags = tags
        self.actors: List[Actor] = []

    @polycheck(ignored_types=(Actor,))
    def add_actor(self, actor: Actor) -> None:
        """
        Returns a movie
        """
        self.actors.append(actor)

This will make sure that the type Actor is actually ignore and assumed as type Any which also means you can pass whatever value you desire since the type Actor is no longer checked.

Integrations

Polyforce works also really well with integrations, for instance with Pydantic.

The only thing you need to do is to import the decorator and use it inside the functions you want to enforce.

This example is exactly the same as the one for PolyModel.

from typing import List, Union

from pydantic import BaseModel, ConfigDict

from polyforce import polycheck


class Actor:
    ...


class Movie(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True)
    name: str
    year: int
    actors: Union[List[Actor], None] = None

    @polycheck()
    def add_actor(self, actor: Actor) -> None:
        self.actors.append(actor)

    @polycheck()
    def set_actor(self, actor: Actor) -> None:
        ...

This way you can use your favourite libraries with Polyforce.