Skip to content

Iteration strategies

_iter_instances controls which instances take part in a merge and in what order. pleroma ships four ready-made strategies in pleroma.iteration so you rarely need to write that override from scratch.

Available strategies

Function Yields
iter_all Every instance in original order (default behaviour)
iter_reversed Every instance in reverse order
iter_first The first two instances only
iter_last The first and last instances only

All four accept any Collection and return an Iterator, making them safe to use with lists, tuples, and other sequences. An empty collection always produces an empty iterator without raising.

Using a strategy

Import the function and call it from your _iter_instances override:

import dataclasses
from pleroma import MergeableMixin, iter_reversed

@dataclasses.dataclass
class Config(MergeableMixin):
    host: str | None = None
    port: int | None = None

    @classmethod
    def _iter_instances(cls, instances):
        return iter_reversed(instances)

a = Config(host="a", port=8080)
b = Config(host="b", port=None)
c = Config(host="c", port=9090)

Config.merge([a, b, c])
# Traversal order: c → b → a
# host: 'a' (last non-None going c→b→a is 'a')
# port: 9090 (last non-None going c→b→a is 9090)
# Config(host='a', port=9090)

iter_first — merge only the first two

Use iter_first when only the earliest entries in a collection should be considered and the rest discarded:

import dataclasses
from pleroma import MergeableMixin, iter_first

@dataclasses.dataclass
class Event(MergeableMixin):
    source: str | None = None
    value: int | None = None

    @classmethod
    def _iter_instances(cls, instances):
        return iter_first(instances)

a = Event(source="a", value=1)
b = Event(source="b", value=2)
c = Event(source="c", value=100)

Event.merge([a, b, c])
# Only a and b are merged; c is ignored.
# Event(source='b', value=2)

iter_last — merge base with tail

Use iter_last when only the first and last entries matter:

import dataclasses
from pleroma import MergeableMixin, iter_last

@dataclasses.dataclass
class Snapshot(MergeableMixin):
    label: str | None = None
    value: int | None = None

    @classmethod
    def _iter_instances(cls, instances):
        return iter_last(instances)

first  = Snapshot(label="init",    value=0)
middle = Snapshot(label="ignored", value=50)
last   = Snapshot(label="final",   value=99)

Snapshot.merge([first, middle, last])
# Only first and last are merged; middle is skipped.
# Snapshot(label='final', value=99)

Works with MergeableModel too

All strategies work identically with MergeableModel:

from pleroma import iter_last
from pleroma.contrib.pydantic import MergeableModel

class Setting(MergeableModel):
    value: int | None = None

    @classmethod
    def _iter_instances(cls, instances):
        return iter_last(instances)