Contract Ordering in POP

The Contract Ordering feature within the Plugin Oriented Programming (POP) architecture is a deterministic system to control the sequence of contract execution. This feature enhances the predictability of execution, providing developers with explicit control over the ordering and incorporating mechanisms to handle order collisions.

Overview

The Contract Ordering feature categorizes the execution sequence into three distinct categories:

  1. Positive Ordering: Contracts with a positive __order__ value are first in the list of contracts, starting with values like [1, 2, 3].
  2. Default Ordering: Contracts without an __order__ attribute are executed after positive ones, maintaining the order from __contracts__ lists.
  3. Negative Ordering: Contracts with a negative __order__ value are last in the list of contracts, ending with values like [-3, -2, -1].

Default Ordering

The “Default Ordering” category is a bit more complex, consisting of three stages:

  1. Implicit Contracts: These are executed first, including special contracts like “init” and those that share the same filename as the Python file they oversee.
  1. Explicit Contracts from the __contracts__ List: Following the implicit contracts, the contracts defined within the __contracts__ list of a mod are executed in the order they appear in that list.
  1. Recursive Contracts: Finally, the implicit recursive_contracts are executed, followed by the recursive contracts that match the names in the __contracts__ list, respecting the order they were defined in there.

This default ordering comes into play for contracts without an explicitly assigned __order__ attribute and is executed after the Positive Ordering but before Negative Ordering.

New Attributes and Functions

  • __order__ (Optional): An attribute with an int value with an value greater than or equal to 1 or less than or equal to -1
    added to the contract class to specify execution order.
  • __verify_order__ (Optional): Developers can implement this function within a contract mod to introduce custom order verification logic.

Ordering Collisions

A warning is issued if multiple contracts share the same __order__ value. This warning includes the shared order and the names of all contracts that share it.

# project_root/pop_code/mod/contracts/contract_1.py

__order__ = 1
# project_root/pop_code/mod/contracts/contract_2.py

__order__ = 1

These two files share the same order number, so a warning will be logged.

Example Usage

The contract ordering can be demonstrated through the contract_ordering module, available under tests/tpath/co1. Various contracts are defined, including recursive contracts and unordered contracts.

# project_root/pop_code/mod/contracts/contract_name.py

__order__ = (
    1  # Specifies that this contract falls under Positive Ordering and comes first
)

Verify Order Function

The optional __verify_order__ function is a synchronous method that enables verification of order the logic by any contract. It’s invoked post-sorting of contracts based on their __order__ values and prior to execution.

This function should have the following signature:

def __verify_order__(hub, contracts: tuple[str, ...]) -> tuple[bool, str]:
    ...
  • hub: The global namespace for accessing shared resources.
  • contracts: An immutable tuple of references to the contracts in their final order.

Here is an example of a contract that asserts that it is always first:

# project_root/pop_code/mod/contracts/contract_name.py


def __verify_order__(hub, contracts):
    return contracts[0] == __name__, f"{__name__} contract must always come first"

The function must return a boolean indicating the success of the verification. If verification fails, it should return a tuple containing “False” and a comment string explaining the reason for the failure. This customization empowers developers to implement additional validation layers for order integrity, enabling proactive issue detection in the execution sequence.

Modularity

Remember, in POP, contracts are also mods – which is another way to ensure contract order. This powerful feature means you can even have contracts on contracts, opening doors for more intricate ordering and execution scenarios. It’s a neat trick that provides additional flexibility in controlling how your contracts interact and execute. Feel free to explore this advanced concept as you get more comfortable with the system.

For example:

# project_root/pop_code/mod/contracts/contracts/init.py


def pre_pre(hub, ctx):
    # This contract would run before "pre" contracts in project_root/pop_code/mod/contracts/contract_name.py
    ...


def post_pre(hub, ctx):
    # This contract would run after "pre" contracts in project_root/pop_code/mod/contracts/contract_name.py
    ...


def sig_post(hub, ctx):
    # This contract ensures that a "post" contract exists in project_root/pop_code/mod/contracts/contract_name.py
    ...