<commit_before>from collections import deque


class Observable(object):
    _call_stack = []
    
    def __init__(self, name=None):
        self.name = name
        self._subscribers = set()
        self._dependants = set()
    
    def subscribe(self, f):
        self._subscribers.add(f)
    
    on_change = subscribe
    
    def unsubscribe(self, f):
        self._subscribers.remove(f)
    
    def add_dependant(self, d):
        self._dependants.add(d)
    
    def remove_dependant(self, d):
        self._dependants.remove(d)
        
    @property
    def dependants(self):
        return self._dependants
    
    def all_dependants(self):
        """
        Generate all the observables that depend on self (transitive closure)
        """
        return self._traverse(set([self]))

    def invalidate_dependants(self):
        dependants = list(self.all_dependants())

        for d in dependants:
            d.valid = False

        for d in dependants:
            d._notify()

    def _traverse(self, visited):
        for d in self._dependants:
            if d in visited:
                continue

            visited.add(d)
            yield d

            for rd in d._traverse(visited):
                yield rd

    def _notify(self):
        for f in self._subscribers:
            f(self)
    
        
class InputValue(Observable):
    
    def __init__(self, value, name=None):
        super(InputValue, self).__init__(name)
        self._value = value<commit_msg>Added cleaning the dependencies after invalidating the nodes<commit_after>from collections import deque


class Observable(object):
    _call_stack = []
    
    def __init__(self, name=None):
        self.name = name
        self._subscribers = set()
        self._dependants = set()
    
    def subscribe(self, f):
        self._subscribers.add(f)
    
    on_change = subscribe
    
    def unsubscribe(self, f):
        self._subscribers.remove(f)
    
    def add_dependant(self, d):
        self._dependants.add(d)
    
    def remove_dependant(self, d):
        self._dependants.remove(d)

    def clear_dependants(self):
        self._dependants.clear()

    @property
    def dependants(self):
        return self._dependants
    
    def all_dependants(self):
        """
        Generate all the observables that depend on self (transitive closure)
        """
        return list(self._traverse(set([self])))

    def invalidate_dependants(self):
        dependants = self.all_dependants()

        for d in dependants:
            d.valid = False
            d.clear_dependants()

        for d in dependants:
            d._notify()

    def _traverse(self, visited):
        for d in self._dependants:
            if d in visited:
                continue

            visited.add(d)
            yield d

            for rd in d._traverse(visited):
                yield rd

    def _notify(self):
        for f in self._subscribers:
            f(self)
    
        
class InputValue(Observable):
    
    def __init__(self, value, name=None):
        super(InputValue, self).__init__(name)
        self._value = value
{'fraction_non_alphanumeric': 0.08876117496807152, 'fraction_numerical': 0.0, 'mean_word_length': 1.8481818181818181, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2816362', 'n_tokens_mistral': 924, 'n_tokens_neox': 893, 'n_words': 222}