CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-vine

Python promises library providing specialized promise-based asynchronous operations and lazy evaluation

Pending
Overview
Eval results
Files

abstract.mddocs/

Abstract Classes

Core abstract classes and proxy objects for creating thenable objects. These provide the foundation for vine's promise system and enable custom implementations of promise-like behavior.

Capabilities

Thenable Abstract Base Class

Abstract base class defining the interface for all promise-like objects in vine.

class Thenable:
    def then(self, on_success, on_error=None):
        """
        Chain callback to execute when thenable is fulfilled.
        
        Parameters:
        - on_success: callable, function to execute on successful completion
        - on_error: callable, optional error handler for exceptions
        
        Returns:
        Implementation-specific return value (typically a thenable)
        """

    def throw(self, exc=None, tb=None, propagate=True):
        """
        Throw exception through the thenable chain.
        
        Parameters:
        - exc: Exception, exception to throw (uses current if None)
        - tb: traceback, traceback object for exception
        - propagate: bool, whether to re-raise if no error handler
        """

    def cancel(self):
        """
        Cancel the thenable operation.
        
        Stops execution and cleans up resources.
        """

    @classmethod
    def register(cls, other):
        """
        Register a class as implementing Thenable interface.
        
        Parameters:
        - other: class to register as Thenable
        
        Returns:
        The registered class (enables use as decorator)
        """

    @classmethod  
    def __subclasshook__(cls, C):
        """
        Check if class C supports thenable interface.
        
        Returns True if class has 'then' method in its MRO.
        """

Usage Examples:

from vine import Thenable, promise

# Check if object is thenable
p = promise()
print(isinstance(p, Thenable))  # True

# Register custom class as thenable
@Thenable.register
class CustomThenable:
    def then(self, on_success, on_error=None):
        # Custom implementation
        pass
    
    def throw(self, exc=None, tb=None, propagate=True):
        # Custom implementation  
        pass
    
    def cancel(self):
        # Custom implementation
        pass

# Now CustomThenable instances are considered Thenable
custom = CustomThenable()
print(isinstance(custom, Thenable))  # True

Thenable Proxy

Proxy class that delegates thenable operations to a target promise.

class ThenableProxy:
    def _set_promise_target(self, p):
        """
        Set the target promise to proxy operations to.
        
        Parameters:
        - p: promise object to use as proxy target
        """

    def then(self, on_success, on_error=None):
        """
        Delegate then() call to target promise.
        
        Parameters:
        - on_success: callable, success callback
        - on_error: callable, error callback
        
        Returns:
        Result of target promise's then() method
        """

    def cancel(self):
        """
        Delegate cancel() call to target promise.
        
        Returns:
        Result of target promise's cancel() method
        """

    def throw(self, exc=None, tb=None, propagate=True):
        """
        Delegate throw() call to target promise.
        
        Parameters:
        - exc: Exception to throw
        - tb: traceback object
        - propagate: whether to re-raise
        
        Returns:
        Result of target promise's throw() method
        """

    def throw1(self, exc=None):
        """
        Delegate throw1() call to target promise.
        
        Parameters:
        - exc: Exception to throw
        
        Returns:
        Result of target promise's throw1() method
        """

    @property
    def cancelled(self) -> bool:
        """Proxy to target promise's cancelled property."""

    @property  
    def ready(self) -> bool:
        """Proxy to target promise's ready property."""

    @property
    def failed(self) -> bool:
        """Proxy to target promise's failed property."""

Usage Examples:

from vine import promise
from vine.abstract import ThenableProxy

# Create proxy for delayed promise creation
class DelayedPromiseProxy(ThenableProxy):
    def __init__(self, promise_factory):
        self.promise_factory = promise_factory
        self._p = None
    
    def _ensure_target(self):
        if self._p is None:
            self._p = self.promise_factory()
        return self._p
    
    def then(self, on_success, on_error=None):
        target = self._ensure_target()
        return target.then(on_success, on_error)

# Usage
def create_expensive_promise():
    print("Creating expensive promise...")
    return promise(lambda: expensive_computation())

# Proxy delays creation until actually needed  
proxy = DelayedPromiseProxy(create_expensive_promise)

# Promise only created when then() is called
proxy.then(lambda result: print(f"Got: {result}"))

Advanced Usage

Custom Thenable Implementation

from vine import Thenable
import asyncio

@Thenable.register  
class AsyncThenable:
    """Thenable that wraps asyncio coroutines."""
    
    def __init__(self, coro):
        self.coro = coro
        self.callbacks = []
        self.error_callbacks = []
        self._result = None
        self._error = None
        self._done = False
        
    def then(self, on_success, on_error=None):
        if self._done:
            if self._error:
                if on_error:
                    on_error(self._error)
            else:
                on_success(self._result)
        else:
            self.callbacks.append(on_success)
            if on_error:
                self.error_callbacks.append(on_error)
        return self
    
    def throw(self, exc=None, tb=None, propagate=True):
        self._error = exc or Exception("Thenable error")
        self._done = True
        for callback in self.error_callbacks:
            callback(self._error)
        if propagate and not self.error_callbacks:
            raise self._error
    
    def cancel(self):
        if hasattr(self.coro, 'cancel'):
            self.coro.cancel()
        self._done = True
    
    async def run(self):
        """Execute the wrapped coroutine."""
        try:
            self._result = await self.coro
            self._done = True
            for callback in self.callbacks:
                callback(self._result)
        except Exception as e:
            self.throw(e)

# Usage
async def async_operation():
    await asyncio.sleep(1)
    return "Async result"

# Wrap async operation in custom thenable
async_thenable = AsyncThenable(async_operation())
async_thenable.then(lambda result: print(f"Got: {result}"))

# Run the async operation
asyncio.run(async_thenable.run())

Thenable Duck Typing

# Vine automatically recognizes objects with then() method
class CustomPromiseLike:
    def __init__(self, value):
        self.value = value
        self.ready = False
    
    def then(self, callback, on_error=None):
        if self.ready:
            callback(self.value)
        return self
    
    def complete(self):
        self.ready = True

# Duck typing - automatically recognized as Thenable
custom = CustomPromiseLike("test")
print(isinstance(custom, Thenable))  # True (due to __subclasshook__)

# Can be used with vine utilities
from vine import maybe_promise
p = maybe_promise(custom)  # Returns custom object as-is

Proxy Patterns

class LoggingThenableProxy(ThenableProxy):
    """Proxy that logs all thenable operations."""
    
    def __init__(self, target):
        self._set_promise_target(target)
        self.operation_log = []
    
    def then(self, on_success, on_error=None):
        self.operation_log.append(f"then() called with {on_success}")
        return super().then(on_success, on_error)
    
    def cancel(self):
        self.operation_log.append("cancel() called")
        return super().cancel()
    
    def throw(self, exc=None, tb=None, propagate=True):
        self.operation_log.append(f"throw() called with {exc}")
        return super().throw(exc, tb, propagate)

# Usage
original_promise = promise(lambda: "result")
logged_promise = LoggingThenableProxy(original_promise)

logged_promise.then(lambda x: print(x))
logged_promise()

print(logged_promise.operation_log)  # Shows all operations

Install with Tessl CLI

npx tessl i tessl/pypi-vine

docs

abstract.md

index.md

promises.md

synchronization.md

utilities.md

tile.json