Skip to main content

A package to define interfaces 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.

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.3.6.tar.gz (3.2 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.3.6-py3-none-any.whl (3.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: interface_py-1.3.6.tar.gz
  • Upload date:
  • Size: 3.2 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.3.6.tar.gz
Algorithm Hash digest
SHA256 995930e366d2745c1e4aed8a27d461ae9fba2d01d846bfee5a241f889a330777
MD5 c672f55457b6d8dc90257e06c824d188
BLAKE2b-256 b5a46dd62111b0ef5270ad2d3dd7990dcde19662d7b8072eb5d272927280e0c8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: interface_py-1.3.6-py3-none-any.whl
  • Upload date:
  • Size: 3.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.3.6-py3-none-any.whl
Algorithm Hash digest
SHA256 f08c4fffc7542e762354695d555e711cf5527cafb471b46bb8d21481979b05b6
MD5 79d0a39fdfd844fccacc3794d34f4afa
BLAKE2b-256 21a02079ed0276e19fdc533a0257584dc98fd2a76d4fe55eb120885c616493da

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