Skip to main content

DEPRECATED - Use 'globalfactory' instead. SpecRec ObjectFactory dependency injection for Python

Project description

SpecRec for Python


⚠️ DEPRECATION NOTICE ⚠️

This package has been renamed to global-object-factory

The specrec package is deprecated and will no longer receive updates. Please migrate to the new package:

pip uninstall specrec
pip install global-object-factory

Update your imports:

# Old
from specrec import ObjectFactory, create

# New
from global_object_factory import ObjectFactory, create

For more information and documentation, visit: https://github.com/ivettordog/global-object-factory


Make legacy Python code testable with minimal changes

Installation (Deprecated)

pip install specrec-python

ObjectFactory: Breaking Hard Dependencies

Turn untestable legacy code into testable code by replacing direct instantiation with factory calls.

The Problem

Legacy code with hard dependencies:

class UserService:
    def process_user(self, user_id):
        # Hard to test - always hits real database
        repo = SqlRepository("server=prod;database=users")
        user = repo.get_user(user_id)
        return user

The Solution

Replace new with create():

from specrec import create

class UserService:
    def process_user(self, user_id):
        # Now testable - can inject test doubles
        repo = create(SqlRepository)("server=prod;database=users")
        user = repo.get_user(user_id)
        return user

Writing Tests

Basic Test Setup

from specrec import create, set_one, context

def test_user_service():
    # Create test double
    mock_repo = MockSqlRepository()
    mock_repo.users = {"123": User("John", "john@example.com")}

    with context():
        # Next create() call returns our mock
        set_one(SqlRepository, mock_repo)

        # Test the code
        service = UserService()
        user = service.process_user("123")

        assert user.name == "John"

Persistent Test Doubles

from specrec import set_always, clear_one

def test_multiple_calls():
    mock_repo = MockSqlRepository()

    with context():
        # All create() calls return our mock
        set_always(SqlRepository, mock_repo)

        service = UserService()
        user1 = service.process_user("123")  # Uses mock
        user2 = service.process_user("456")  # Uses mock too

API Reference

Core Functions

  • create(cls) - Returns a factory function for the class
  • create_direct(cls, *args, **kwargs) - Create instance directly
  • set_one(cls, instance) - Return test double once, then normal instances
  • set_always(cls, instance) - Always return test double
  • clear_one(cls) - Clear test doubles for specific type
  • clear_all() - Clear all test doubles
  • context() - Context manager for automatic cleanup

Advanced Usage

Custom Factory Instance

from specrec import ObjectFactory

# Create dedicated factory
api_factory = ObjectFactory()
create_api_service = api_factory.create(ApiService)
service = create_api_service("https://api.example.com")

Constructor Parameter Tracking

from specrec.interfaces import IConstructorCalledWith, ConstructorParameterInfo
from typing import List

class TrackedService(IConstructorCalledWith):
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.constructor_params: List[ConstructorParameterInfo] = []

    def constructor_called_with(self, params: List[ConstructorParameterInfo]) -> None:
        self.constructor_params = params

# Usage
service = create(TrackedService)("localhost", 8080)
print(service.constructor_params[0].name)   # "host"
print(service.constructor_params[0].value)  # "localhost"

Object Registration

from specrec import register_object, get_registered_object

config = DatabaseConfig()
object_id = register_object(config, "db-config")

# Later retrieve it
retrieved = get_registered_object("db-config")

Requirements

  • Python 3.8+
  • typing-extensions (for Python < 3.10)

License

PolyForm Noncommercial License 1.0.0

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

specrec-2.0.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

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

specrec-2.0.0-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file specrec-2.0.0.tar.gz.

File metadata

  • Download URL: specrec-2.0.0.tar.gz
  • Upload date:
  • Size: 13.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for specrec-2.0.0.tar.gz
Algorithm Hash digest
SHA256 057f7168d5322b776238aa00903cdec3a01b2c3cdba00f280663d57c77d26a7a
MD5 e7272033d8bfb48a31e25fc4fcc65523
BLAKE2b-256 ee2aec1112ea3f384eab87872cee7114a918fad60bad6bfc0b79e252c78f2809

See more details on using hashes here.

File details

Details for the file specrec-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: specrec-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for specrec-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36a5ab950b616bfc62c2c415b5d4aca4ccd8831b02192f45b306380cc9107cce
MD5 f30f7e69262a8f5cd732eb97db4ddda5
BLAKE2b-256 6f8da244a3faddc3f72c4022f5c0825daadf79e623867c1d1977a80909c1bff9

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