11from abc import ABC , abstractmethod
22from typing import TextIO , Union , Optional , Callable , Dict , Type , Any , List
33
4+ from pydantic import BaseModel
45from hbreader import FileInfo , hbread
56from jsonasobj2 import as_dict , JsonObj
67
@@ -36,9 +37,9 @@ def _is_empty(o) -> bool:
3637 def load_source (self ,
3738 source : Union [str , dict , TextIO ],
3839 loader : Callable [[Union [str , Dict ], FileInfo ], Optional [Union [Dict , List ]]],
39- target_class : Type [YAMLRoot ],
40+ target_class : Union [ Type [YAMLRoot ], Type [ BaseModel ] ],
4041 accept_header : Optional [str ] = "text/plain, application/yaml;q=0.9" ,
41- metadata : Optional [FileInfo ] = None ) -> Optional [Union [YAMLRoot , List [YAMLRoot ]]]:
42+ metadata : Optional [FileInfo ] = None ) -> Optional [Union [BaseModel , YAMLRoot , List [ BaseModel ] , List [YAMLRoot ]]]:
4243 """ Base loader - convert a file, url, string, open file handle or dictionary into an instance
4344 of target_class
4445
@@ -59,19 +60,28 @@ def load_source(self,
5960 else :
6061 data = source
6162 data_as_dict = loader (data , metadata )
63+
6264 if data_as_dict :
6365 if isinstance (data_as_dict , list ):
64- return [target_class (** as_dict (x )) for x in data_as_dict ]
66+ if issubclass (target_class , YAMLRoot ):
67+ return [target_class (** as_dict (x )) for x in data_as_dict ]
68+ elif issubclass (target_class , BaseModel ):
69+ return [target_class .parse_obj (** as_dict (x )) for x in data_as_dict ]
70+ else :
71+ raise ValueError (f'Cannot load list of { target_class } ' )
6572 elif isinstance (data_as_dict , dict ):
66- return target_class (** data_as_dict )
73+ if issubclass (target_class , BaseModel ):
74+ return target_class .parse_obj (data_as_dict )
75+ else :
76+ return target_class (** data_as_dict )
6777 elif isinstance (data_as_dict , JsonObj ):
6878 return [target_class (** as_dict (x )) for x in data_as_dict ]
6979 else :
7080 raise ValueError (f'Unexpected type { data_as_dict } ' )
7181 else :
7282 return None
7383
74- def load (self , * args , ** kwargs ) -> YAMLRoot :
84+ def load (self , * args , ** kwargs ) -> Union [ BaseModel , YAMLRoot ] :
7585 """
7686 Load source as an instance of target_class
7787
@@ -83,14 +93,14 @@ def load(self, *args, **kwargs) -> YAMLRoot:
8393 :return: instance of target_class
8494 """
8595 results = self .load_any (* args , ** kwargs )
86- if isinstance (results , YAMLRoot ):
96+ if isinstance (results , BaseModel ) or isinstance ( results , YAMLRoot ):
8797 return results
8898 else :
89- raise ValueError (f'Result is not an instance of YAMLRoot: { type (results )} ' )
99+ raise ValueError (f'Result is not an instance of BaseModel or YAMLRoot: { type (results )} ' )
90100
91101 @abstractmethod
92- def load_any (self , source : Union [str , dict , TextIO ], target_class : Type [YAMLRoot ], * , base_dir : Optional [str ] = None ,
93- metadata : Optional [FileInfo ] = None , ** _ ) -> Union [YAMLRoot , List [YAMLRoot ]]:
102+ def load_any (self , source : Union [str , dict , TextIO ], target_class : Type [Union [ BaseModel , YAMLRoot ] ], * , base_dir : Optional [str ] = None ,
103+ metadata : Optional [FileInfo ] = None , ** _ ) -> Union [BaseModel , YAMLRoot , List [ BaseModel ] , List [YAMLRoot ]]:
94104 """
95105 Load source as an instance of target_class, or list of instances of target_class
96106
@@ -103,7 +113,7 @@ def load_any(self, source: Union[str, dict, TextIO], target_class: Type[YAMLRoot
103113 """
104114 raise NotImplementedError ()
105115
106- def loads_any (self , source : str , target_class : Type [YAMLRoot ], * , metadata : Optional [FileInfo ] = None , ** _ ) -> Union [YAMLRoot , List [YAMLRoot ]]:
116+ def loads_any (self , source : str , target_class : Type [Union [ BaseModel , YAMLRoot ]] , * , metadata : Optional [FileInfo ] = None , ** _ ) -> Union [BaseModel , YAMLRoot , List [ BaseModel ] , List [YAMLRoot ]]:
107117 """
108118 Load source as a string as an instance of target_class, or list of instances of target_class
109119 @param source: source
@@ -114,7 +124,7 @@ def loads_any(self, source: str, target_class: Type[YAMLRoot], *, metadata: Opti
114124 """
115125 return self .load_any (source , target_class , metadata = metadata )
116126
117- def loads (self , source : str , target_class : Type [YAMLRoot ], * , metadata : Optional [FileInfo ] = None , ** _ ) -> YAMLRoot :
127+ def loads (self , source : str , target_class : Type [Union [ BaseModel , YAMLRoot ]] , * , metadata : Optional [FileInfo ] = None , ** _ ) -> Union [ BaseModel , YAMLRoot ] :
118128 """
119129 Load source as a string
120130 :param source: source
0 commit comments