import copy class Example: def __init__(self, base=None, **kwargs): # Internal storage and other attributes self._store = {} self._demos = [] self._input_keys = None # Initialize from a base Example if provided if base and isinstance(base, type(self)): self._store = base._store.copy() # Initialize from a dict if provided elif base and isinstance(base, dict): self._store = base.copy() # Update with provided kwargs self._store.update(kwargs) def __getattr__(self, key): if key.startswith('__') and key.endswith('__'): raise AttributeError if key in self._store: return self._store[key] raise AttributeError(f"'{type(self).__name__}' object has no attribute '{key}'") def __setattr__(self, key, value): if key.startswith('_') or key in dir(self.__class__): super().__setattr__(key, value) else: self._store[key] = value def __getitem__(self, key): return self._store[key] def __setitem__(self, key, value): self._store[key] = value def __delitem__(self, key): del self._store[key] def __contains__(self, key): return key in self._store def __len__(self): return len([k for k in self._store if not k.startswith('dspy_')]) def __repr__(self): # return f"Example({self._store})" + f" (input_keys={self._input_keys}, demos={self._demos})" d = {k: v for k, v in self._store.items() if not k.startswith('dspy_')} return f"Example({d})" + f" (input_keys={self._input_keys})" def __str__(self): return self.__repr__() def __eq__(self, other): return self._store == other._store def __hash__(self): return hash(tuple(self._store.items())) def keys(self, include_dspy=False): return [k for k in self._store.keys() if not k.startswith('dspy_') or include_dspy] def values(self, include_dspy=False): return [v for k, v in self._store.items() if not k.startswith('dspy_') or include_dspy] def items(self, include_dspy=False): return [(k, v) for k, v in self._store.items() if not k.startswith('dspy_') or include_dspy] def get(self, key, default=None): return self._store.get(key, default) def with_inputs(self, *keys): copied = self.copy() copied._input_keys = set(keys) return copied def inputs(self): if self._input_keys is None: raise ValueError("Inputs have not been set for this example. Use `example.with_inputs()` to set them.") # return items that are in input_keys d = {key: self._store[key] for key in self._store if key in self._input_keys} return type(self)(d) def labels(self): # return items that are NOT in input_keys input_keys = self.inputs().keys() d = {key: self._store[key] for key in self._store if key not in input_keys} return type(self)(d) def __iter__(self): return iter(dict(self._store)) def copy(self, **kwargs): return type(self)(base=self, **kwargs) def without(self, *keys): copied = self.copy() for key in keys: del copied[key] return copied def toDict(self): return self._store.copy()