Metadata-Version: 2.4
Name: abstractsignature
Version: 0.1.0
Summary: Create abstract function signatures that enforce consistent implementation signatures.
Project-URL: Repository, https://github.com/d-c-gray/abstractsignature
Author-email: d-c-gray <cole.gray.writing@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: <4.0,>=3.11
Description-Content-Type: text/markdown

# abstractsignature

This package provides a method for enforcing consistent
function signatures between abstractmethod implementations. This hopes to make large libraries where many classes inherit a common interface from a single abstract definition easier to maintain.

Classes which inherit an ``@abstractmethod`` with an ``@abstractsignature`` will fail to instantiate if their signature does not equal the abstraction.

Two signatures are considered equal if all their parameters are
equal (excluding the implicit ``self``/``cls`` parameter for instance and class methods), their positional and positional only parameters are in the same order, and they have equal return annotations. Parameters are considered equal if they have the same name, kind, default value, and annotation.


# Install

Install from git:

```sh
uv add git+https://github.com/d-c-gray/abstractsignature.git
```

# Usage

Create a class that inherits from ABCSignature, and
define abstract methods. Add the ``@abstractsignature`` decorator above the ``@abstractmethod`` decorator. 

<!--pytest.mark.xfail-->
```python
from abstractsignature import abstractsignature, ABCSignature
from abc import abstractmethod

class MyInterface(ABCSignature):
    @abstractsignature
    @abstractmethod
    def my_method(self, a: int) -> int:
        return a + 1

class MyImplementation(MyInterface):
    def __init__(self):
        super().__init__()
    def my_method(self, number: int) -> int:
        return number + 1

MyImplementation()
```

If the implemented signature doesn't match the defined signature, you will
get an error:


```
abstractsignature.abstractsignature.IncorrectSignatureError: implementation <bound method MyImplementation.my_method of <__main__.MyImplementation object at 0x00000135A7E1EE40>> does not match abstract definition of <class '__main__.MyInterface'>:
Implemented signature:
 (number: int) -> int
Abstract signature:
 (a: int) -> int
```

This pattern also works with ``@classmethod`` and ``@staticmethod``

```python
from abstractsignature import abstractsignature, ABCSignature
from abc import abstractmethod

class MyInterface(ABCSignature):
    @classmethod
    @abstractsignature
    @abstractmethod
    def my_class_method(cls, a: int) -> int:
        return a + 1

    @staticmethod
    @abstractsignature
    @abstractmethod
    def my_static_method(cls, a: int) -> int:
        return a + 1
```


*This project was built from
[simple-modern-uv](https://github.com/jlevy/simple-modern-uv).*
