@@ -86,10 +86,37 @@ def is_yaml_tag_supported(cls, yaml_tag: str) -> bool:
8686def yaml_info (yaml_tag : str = None , yaml_tag_ns : str = None ) \
8787 -> Callable [['Type[YA]' , Optional [str ], Optional [str ]], 'Type[YA]' ]:
8888 """
89- A simple class decorator to tag a class with a global yaml tag - that way no need to call YamlAble super constructor
89+ A simple class decorator to tag a class with a global yaml tag - that way you do not have to call `YamlAble` super
90+ constructor.
9091
91- :param yaml_tag:
92- :param yaml_tag_ns:
92+ You can either provide a full yaml tag suffix:
93+
94+ ```python
95+ @yaml_info("com.example.MyFoo")
96+ class Foo(YamlAble):
97+ pass
98+
99+ print(Foo.__yaml_tag_suffix__) # yields "com.example.MyFoo"
100+ ```
101+
102+ or simply provide a namespace, that will be appended with '.<class name>' :
103+
104+ ```python
105+ @yaml_info(yaml_tag_ns="com.example")
106+ class Foo(YamlAble):
107+ pass
108+
109+ print(MyFoo.__yaml_tag_suffix__) # yields "com.example.Foo"
110+ ```
111+
112+ In both cases, the suffix is appended at the end of the common yamlable prefix:
113+
114+ ```python
115+ print(Foo().dumps_yaml()) # yields "!yamlable/com.example.Foo {}"
116+ ```
117+
118+ :param yaml_tag: the complete yaml suffix.
119+ :param yaml_tag_ns: the yaml namespace. It will be appended with '.<cls.__name__>'
93120 :return:
94121 """
95122 def f (cls ):
@@ -99,11 +126,38 @@ def f(cls):
99126
100127def yaml_info_decorate (cls : 'Type[YA]' , yaml_tag : str = None , yaml_tag_ns : str = None ) -> 'Type[YA]' :
101128 """
102- A simple class decorator to tag a class with yaml tag - that way no need to call YamlAble super constructor
129+ A simple class decorator to tag a class with a global yaml tag - that way you do not have to call `YamlAble` super
130+ constructor.
131+
132+ You can either provide a full yaml tag suffix:
133+
134+ ```python
135+ @yaml_info("com.example.MyFoo")
136+ class Foo(YamlAble):
137+ pass
138+
139+ print(Foo.__yaml_tag_suffix__) # yields "com.example.MyFoo"
140+ ```
141+
142+ or simply provide a namespace, that will be appended with '.<class name>' :
143+
144+ ```python
145+ @yaml_info(yaml_tag_ns="com.example")
146+ class Foo(YamlAble):
147+ pass
148+
149+ print(MyFoo.__yaml_tag_suffix__) # yields "com.example.Foo"
150+ ```
151+
152+ In both cases, the suffix is appended at the end of the common yamlable prefix:
153+
154+ ```python
155+ print(Foo().dumps_yaml()) # yields "!yamlable/com.example.Foo {}"
156+ ```
103157
104158 :param cls:
105- :param yaml_tag:
106- :param yaml_tag_ns:
159+ :param yaml_tag: the complete yaml suffix.
160+ :param yaml_tag_ns: the yaml namespace. It will be appended with '.<cls.__name__>'
107161 :return:
108162 """
109163 if yaml_tag_ns is not None :
@@ -141,13 +195,19 @@ def decode_yamlable(loader, yaml_tag, node, **kwargs):
141195 :return:
142196 """
143197 candidates = _get_all_subclasses (YamlAble )
198+ errors = dict ()
144199 for clazz in candidates :
145- if clazz .is_yaml_tag_supported (yaml_tag ):
146- constructor_args = read_yaml_node_as_dict (loader , node )
147- return clazz .from_yaml_dict (constructor_args , yaml_tag = yaml_tag )
200+ try :
201+ if clazz .is_yaml_tag_supported (yaml_tag ):
202+ constructor_args = read_yaml_node_as_dict (loader , node )
203+ return clazz .from_yaml_dict (constructor_args , yaml_tag = yaml_tag )
204+ except Exception as e :
205+ errors [clazz .__name__ ] = e
148206
149207 raise TypeError ("No YamlAble subclass found able to decode object !yamlable/" + yaml_tag + ". Tried classes: "
150- + str (candidates ))
208+ + str (candidates ) + ". Caught errors: " + str (errors ) + ". "
209+ "Please check the value of <cls>.__yaml_tag_suffix__ on these classes. Note that this value may be "
210+ "set using @yaml_info() so help(yaml_info) might help too." )
151211
152212
153213def encode_yamlable (dumper , obj , without_custom_tag : bool = False , ** kwargs ):
0 commit comments