11import abc
22import dataclasses
33import os
4- from typing import Any , ClassVar , Dict , Generator , Generic , List , Optional , Protocol , Self , TypeVar , runtime_checkable
4+ from typing import (
5+ Any ,
6+ ClassVar ,
7+ Dict ,
8+ Generator ,
9+ Generic ,
10+ List ,
11+ Optional ,
12+ Protocol ,
13+ Self ,
14+ TypeVar ,
15+ cast ,
16+ runtime_checkable ,
17+ )
518
619from semver import Version
720from typing_extensions import override
@@ -201,7 +214,16 @@ def has_data(self) -> bool:
201214 Returns:
202215 bool: True if data has been loaded, False otherwise.
203216 """
204- return not _typing .is_unset (self ._data )
217+ return not (_typing .is_unset (self ._data ) or self .has_error )
218+
219+ @property
220+ def has_error (self ) -> bool :
221+ """Check if the data stream encountered an error during loading.
222+
223+ Returns:
224+ bool: True if an error occurred, False otherwise.
225+ """
226+ return isinstance (self ._data , _typing .ErrorOnLoad )
205227
206228 @property
207229 def data (self ) -> _typing .TData :
@@ -213,9 +235,22 @@ def data(self) -> _typing.TData:
213235 Raises:
214236 ValueError: If data has not been loaded yet.
215237 """
238+ if self .has_error :
239+ cast (_typing .ErrorOnLoad , self ._data ).raise_from_error ()
216240 if not self .has_data :
217241 raise ValueError ("Data has not been loaded yet." )
218- return self ._data
242+ return cast (_typing .TData , self ._data )
243+
244+ def clear (self ) -> Self :
245+ """Clear the loaded data from the data stream.
246+
247+ Resets the data to an unset state, allowing for reloading.
248+
249+ Returns:
250+ Self: The data stream instance for method chaining.
251+ """
252+ self ._data = _typing .UnsetData
253+ return self
219254
220255 def load (self ) -> Self :
221256 """Load data into the data stream.
@@ -239,7 +274,10 @@ def load(self) -> Self:
239274 print(f"Loaded {len(df)} rows")
240275 ```
241276 """
242- self ._data = self .read ()
277+ try :
278+ self ._data = self .read ()
279+ except Exception as e : # pylint: disable=broad-except
280+ self ._data = _typing .ErrorOnLoad (self , exception = e )
243281 return self
244282
245283 def __str__ (self ):
@@ -266,9 +304,27 @@ def __iter__(self) -> Generator["DataStream", None, None]:
266304 Yields:
267305 DataStream: Child data streams (none for base DataStream).
268306 """
269- yield
307+ return
308+ yield # This line is unreachable but needed for the generator type
309+
310+ def collect_errors (self ) -> List [_typing .ErrorOnLoad ]:
311+ """Collect all errors from this stream and its children.
270312
271- def load_all (self , strict : bool = False ) -> list [tuple ["DataStream" , Exception ], None , None ]:
313+ Performs a depth-first traversal to gather all ErrorOnLoad instances.
314+
315+ Returns:
316+ List[ErrorOnLoad]: List of all errors raised on load encountered in the hierarchy.
317+ """
318+ errors = []
319+ if self .has_error :
320+ errors .append (cast (_typing .ErrorOnLoad , self ._data ))
321+ for stream in self :
322+ if stream is None :
323+ continue
324+ errors .extend (stream .collect_errors ())
325+ return errors
326+
327+ def load_all (self , strict : bool = False ) -> Self :
272328 """Recursively load this data stream and all child streams.
273329
274330 Performs depth-first traversal to load all streams in the hierarchy.
@@ -293,17 +349,13 @@ def load_all(self, strict: bool = False) -> list[tuple["DataStream", Exception],
293349 ```
294350 """
295351 self .load ()
296- exceptions = []
297352 for stream in self :
298353 if stream is None :
299354 continue
300- try :
301- exceptions += stream .load_all (strict = strict )
302- except Exception as e :
303- if strict :
304- raise e
305- exceptions .append ((stream , e ))
306- return exceptions
355+ stream .load_all (strict = strict )
356+ if stream .has_error and strict :
357+ cast (_typing .ErrorOnLoad , stream .data ).raise_from_error ()
358+ return self
307359
308360
309361TDataStream = TypeVar ("TDataStream" , bound = DataStream [Any , Any ])
@@ -411,7 +463,7 @@ def at(self) -> _At[TDataStream]:
411463 return self ._at
412464
413465 @override
414- def load (self ):
466+ def load (self ) -> Self :
415467 """Load data for this collection.
416468
417469 Overrides the base method to add validation that loaded data is a list of DataStreams.
0 commit comments