Skip to main content

A package to define interface in Python

Project description

interface-py

interface-py is a lightweight Python package for defining interfaces and concrete implementations with enforced contracts.
It ensures that concrete classes implement all required methods, properties, and fields, including validation for empty or invalid property getters.


Features

  • Define interfaces using the @interface decorator.
  • Enforce that concrete classes implement all interface methods, fields, and properties.
  • Detects and enforces rules for empty, explicit, and invalid getters/setters.
  • Support for fields with four declaration styles:
    1. With annotation only → x: int
    2. With annotation + ...y: float = ...
    3. Without annotation + ...z = ...
    4. With direct type assignment → DataModel = dict or any other type/class
  • Ensures that property getters defined explicitly in interfaces always raise an error.
  • Allows defining properties in interfaces with empty bodies (..., pass, or docstring-only`).
  • Enforce getter, setter, and deleter implementation rules for properties.
  • Supports multi-level interface hierarchies with automatic contract aggregation.
  • Prevents runtime errors from missing implementations.
  • Works alongside Python's built-in ABCs.

Installation

pip install interface-py

Usage

Defining an Interface

from interface_py import interface

@interface
class HumanInterface:
    # field definitions
    name: str
    age: int = ...
    nickname = ...
    DataModel = dict  # direct type assignment
    
    def speak(self): ...
    
    @property
    def rank(self): ...
    
    @rank.setter
    def rank(self, value): ...
  • Property definitions in interfaces may have an empty body (..., pass, or docstring-only`).
  • However, explicit getters (e.g. @rank.getter) are not allowed in interfaces, even if their body is empty.

🦆 Duck Typing (Structural Compatibility Checks)

interface-py provides structural compatibility checks via a separate submodule:
interface_py.duck_typing

This module lets you check whether a class or instance matches an interface contract structurally,
even if it doesn’t explicitly inherit from it.


Example

from interface_py import interface
from interface_py.duck_typing import is_duck_subclass, is_duck_instance

@interface
class FlyableInterface:
    def fly(self): ...

class Bird:
    def fly(self):
        print("Flying high!")

class Plane:
    def fly(self):
        print("Taking off!")

# Structural (duck) compatibility check
assert is_duck_subclass(Bird, FlyableInterface)
assert is_duck_instance(Plane(), FlyableInterface)

✅ In this example:

  • Neither Bird nor Plane explicitly inherit from FlyableInterface.
  • However, both provide the required fly() method.
  • Therefore, they are structurally compatible with the interface.
    (“If it flies like a bird, it’s a bird.”)

Notes

  • These checks are opt-in and non-intrusive
    They don’t affect Python’s built-in issubclass() or isinstance() behavior.
    Instead, you explicitly call is_duck_subclass() or is_duck_instance().
  • Works with:
    • Methods
    • Properties
    • Fields
    • Static methods
    • Class methods
  • This design avoids modifying the MRO or inheritance hierarchy.
  • Future versions may extract this logic into a standalone package for broader reuse.

Import Path

from interface_py.duck_typing import (
    is_duck_subclass,
    is_duck_instance,
)

Multi-level Interface Example

from interface_py import interface, concrete

@interface
class MilitaryHumanInterface(HumanInterface):
    def march(self): ...

@concrete
class Soldier(MilitaryHumanInterface):
    name: str = "John"
    age: int = 25
    nickname = "Eagle"
    
    def speak(self):
        print("Reporting for duty!")

    def march(self):
        print("Marching!")

    @property
    def rank(self):
        return self._rank
    
    @rank.setter
    def rank(self, value):
        self._rank = value
  • MilitaryHumanInterface extends HumanInterface.
  • Soldier implements all required methods, fields, and properties from both interfaces automatically.
  • Multi-level inheritance automatically merges all parent interface contracts.

Field Enforcement Examples

from interface_py import interface, concrete

@interface
class ExampleInterface:
    x: int              # only annotation
    y: float = ...      # annotation with ellipsis
    z = ...             # plain ellipsis
    DataModel = dict    # direct type assignment


# ✅ Correct implementation
@concrete
class GoodImpl(ExampleInterface):
    x: int = 10
    y: float = 3.14
    z = "hello"
    DataModel = dict


# ❌ Incorrect implementation
@concrete
class BadImpl(ExampleInterface):
    x: str = "oops"   # wrong type (expected int)
    # y missing → TypeError
    z = ...           # not allowed to keep ellipsis
    DataModel = list   # wrong type assignment

Method Enforcement Rules

In interfaces, all methods must have an empty body.
Empty bodies are recognized as:

  • pass
  • ...
  • docstring-only functions (for example, a function that only contains a string literal as its body)

In concrete classes, all methods must have a non-empty body.
Methods defined with only pass, ..., or docstring-only are considered unimplemented and raise a TypeError.


Property Enforcement Rules

  • A property can be declared in an interface as:

    @property
    def data(self): ...
    
  • The above is valid and treated as a contract placeholder.

  • However, the following is invalid and raises an error:

    @property
    def data(self):
        pass
    
    @data.getter
    def data(self):
        ...
    
  • Concrete classes must implement the getter, and if defined in the interface, also the setter and deleter.


Validation

  • Instantiating a concrete class that does not implement all interface methods/fields/properties raises a TypeError.
  • Ensures consistent interface contracts across your project.
  • The decorator @interface automatically enforces the interface behavior without requiring any base class.
  • The decorator @concrete ensures that at least one parent of the concrete class is an interface.

Why Use interface-py?

  • Provides contract enforcement in dynamically typed Python.
  • Detects incomplete or empty implementations early.
  • Helps structure large codebases with clear interface and implementation separation.
  • Avoids runtime errors from missing or placeholder methods.
  • Enforces correctness while remaining Pythonic.

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

interface_py-1.5.0.tar.gz (10.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

interface_py-1.5.0-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file interface_py-1.5.0.tar.gz.

File metadata

  • Download URL: interface_py-1.5.0.tar.gz
  • Upload date:
  • Size: 10.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for interface_py-1.5.0.tar.gz
Algorithm Hash digest
SHA256 7e882043a54f38ae1ef6a812d5654492b8962ad9cdb33cd7f89d43d19f0d6289
MD5 016164e4cfe558bfd978c97fb64e9b3f
BLAKE2b-256 2b810a268d9fefacb0e9766fe25b9e47730dc21ac9f6ef7b6e9692535c0c2cb6

See more details on using hashes here.

File details

Details for the file interface_py-1.5.0-py3-none-any.whl.

File metadata

  • Download URL: interface_py-1.5.0-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for interface_py-1.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ca1ad8935d903fcb5b250fd63b83a10a3c35951fca3507bb1074ed48afd29f24
MD5 4d79f7c728373950e1008df893b1fbd4
BLAKE2b-256 e7bfa371faab32665f81814fcbe89800433cdc7954dbcf54221d05b87d0a7108

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page