Skip to content

The AnnotationProtocol class extends the isinstance check of python to be more strict and assess the following in addition to whether the `object` is an instance of the `classinfo` argument.

License

Notifications You must be signed in to change notification settings

RoyalHaskoningDHV/annotation-protocol

Repository files navigation

annotation-protocol

The AnnotationProtocol allows for more thorough isinstance checks in python. Specifically, it adds the following functionality beyond typing.Protocol.

  1. Check that all attributes from the class other that should adhere to the protocol are present in it.
  2. Attributes, input arguments and return arguments need ot have the same type annotations between protocol and other.

Author: Royal HaskoningDHV

Email: [email protected], [email protected], [email protected], [email protected], [email protected]

Installation

Use the package manager pip to install annotation-protocol.

pip install annotation-protocol

Background

The Protocol class from the typing package can be used to create templates of classes with specific attributes and methods. We can check if a class adheres to a given Protocol by doing an isinstance check of the form isinstance(MyClass(), MyProtocol). The AnnotationProtocol extends this functionality by also checking if all type-hints are the same for each attribute, method argument and method output.

Usage

For clarity, in the examples below we compare the standard Protocol from the typing package against the AnnotationProtocol. Note that only the AnnotationProtocol returns False when there is a mismatch in type-hints.

from typing import Protocol, runtime_checkable

from annotation_protocol import AnnotationProtocol


@runtime_checkable
class MyProtocol(Protocol):
    def testfun(my_arg: str | list) -> set:
        ...

class MyAnnotationProtocol(AnnotationProtocol):
    def testfun(my_arg: str | list) -> set:
        ...

class ClassShouldPass:
    def testfun(my_arg: str) -> set:
        return set()

class ClassShouldFail:
    def testfun(my_arg: dict) -> set:
        return set()

print(f"Protocol: {isinstance(ClassShouldPass(), MyProtocol)}")  # returns True
print(f"Protocol: {isinstance(ClassShouldFail(), MyProtocol)}")  # returns True

print(f"AnnotationProtocol: {isinstance(ClassShouldPass(), MyAnnotationProtocol)}")  # returns True
print(f"AnnotationProtocol: {isinstance(ClassShouldFail(), MyAnnotationProtocol)}")  # returns False

Note that it is possible to have a subset of type annotations in the ClassShouldPass class compared to the MyAnnotationProtocol. In other words it is not necessary to have all types of a UnionType group of types from the protocol in the class that should adhere to the protocol.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT

About

The AnnotationProtocol class extends the isinstance check of python to be more strict and assess the following in addition to whether the `object` is an instance of the `classinfo` argument.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages