Skip to content

MultihashSet missing Visit() and ForEach() methods #51

Description

@sumanjeet0012

Go's Set type has Visit(m Multihash) bool (add if not present, return whether added) and ForEach(f func(Multihash) error) error (iterate with error propagation). Python's MultihashSet doesn't have these methods.

Problem

Go's Set:

// Visit adds a multihash only if it is not in the set already.
// Returns true if the multihash was added (was not in the set before).
func (s *Set) Visit(m Multihash) bool {
    _, ok := s.set[string(m)]
    if !ok {
        s.set[string(m)] = struct{}{}
        return true
    }
    return false
}

// ForEach runs f(m) with each multihash in the set.
// Returns immediately if f(m) returns an error.
func (s *Set) ForEach(f func(m Multihash) error) error {
    for elem := range s.set {
        mh := Multihash(elem)
        if err := f(mh); err != nil {
            return err
        }
    }
    return nil
}

Python's MultihashSet has add(), remove(), Has(), All(), __contains__, __iter__, and set operations, but not Visit() or ForEach().

Proposed Solution

Add both methods:

class MultihashSet:
    def Visit(self, mh: Multihash) -> bool:
        """Add mh if not present. Return True if it was added."""
        if not isinstance(mh, Multihash):
            raise TypeError(f"MultihashSet can only contain Multihash objects, got {type(mh)}")
        if mh in self._set:
            return False
        self._set.add(mh)
        return True

    def visit(self, mh: Multihash) -> bool:
        """Python-style alias for Visit()."""
        return self.Visit(mh)

    def ForEach(self, func):
        """Call func(mh) for each Multihash. Stop and return error if func raises."""
        for mh in self._set:
            try:
                func(mh)
            except Exception as e:
                return e
        return None

    def for_each(self, func):
        """Python-style alias for ForEach()."""
        return self.ForEach(func)

Add tests:

def test_visit():
    mh_set = MultihashSet()
    mh1 = sum(b"file1", Func.sha2_256)
    assert mh_set.visit(mh1) is True   # Added
    assert mh_set.visit(mh1) is False  # Already present

def test_for_each():
    mh_set = MultihashSet([sum(b"a", Func.sha2_256), sum(b"b", Func.sha2_256)])
    collected = []
    mh_set.for_each(lambda mh: collected.append(mh))
    assert len(collected) == 2

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions