def with_classes_timeline(obj):
    """Add `ClassesTimeline` attributes.

    `obj` must be a scenario or a stream.
    """

    def _decorate_benchmark(obj: CLScenario):
        new_streams = []
        for s in obj.streams.values():
            new_streams.append(_decorate_stream(s))
        return CLScenario(new_streams)

    def _decorate_stream(obj: CLStream):
        # TODO: support stream generators. Should return a new generators which applies
        #  foo_decorate_exp every time a new experience is generated.
        new_stream = []
        if not isinstance(obj, EagerCLStream):
            warnings.warn("stream generator will be converted to a list.")

        # compute set of all classes in the stream
        all_cls: set[int] = set()
        for exp in obj:
            all_cls = all_cls.union(exp.dataset.targets.uniques)

        prev_cls: set[int] = set()
        for exp in obj:
            new_exp = copy(exp)
            curr_cls = exp.dataset.targets.uniques

            new_exp.classes_in_this_experience = curr_cls
            new_exp.previous_classes = set(prev_cls)
            new_exp.classes_seen_so_far = curr_cls.union(prev_cls)
            # TODO: future_classes ignores repetitions right now...
            #  implement and test scenario with repetitions
            new_exp.future_classes = all_cls.difference(new_exp.classes_seen_so_far)
            new_stream.append(new_exp)

            prev_cls = prev_cls.union(curr_cls)
        return EagerCLStream(obj.name, new_stream)

    if isinstance(obj, CLScenario):
        return _decorate_benchmark(obj)
    elif isinstance(obj, CLStream):
        return _decorate_stream(obj)
    else:
        raise ValueError(
            "Unsupported object type: must be one of {CLScenario, CLStream}"
        )
Add `ClassesTimeline` attributes.

    `obj` must be a scenario or a stream.
    
avalanche/benchmarks/scenarios/supervised.py