11import csv
2+ import os
23from collections import defaultdict
4+ from inspect import Parameter , Signature , cleandoc , signature
5+ from typing import Literal
6+
7+ from numpydoc .docscrape import Parameter as numpydoc_Parameter
8+ from numpydoc .docscrape_sphinx import SphinxDocString
9+
10+ from dpdata .bond_order_system import BondOrderSystem
311
412# ensure all plugins are loaded!
513from dpdata .driver import Driver , Minimizer
614from dpdata .format import Format
15+ from dpdata .system import LabeledSystem , MultiSystems , System
716
817
918def get_formats () -> dict :
@@ -64,7 +73,7 @@ def get_cls_link(cls: object) -> str:
6473
6574
6675def check_supported (fmt : Format ):
67- methods = set ()
76+ methods = {}
6877 for mtd in [
6978 "from_system" ,
7079 "to_system" ,
@@ -76,44 +85,267 @@ def check_supported(fmt: Format):
7685 "to_multi_systems" ,
7786 ]:
7887 if detect_overridden (fmt , mtd ):
79- methods . add ( mtd )
88+ methods [ mtd ] = None
8089 if mtd == "to_system" :
81- methods . add ( "to_labeled_system" )
90+ methods [ "to_labeled_system" ] = None
8291 if fmt .MultiMode != fmt .MultiModes .NotImplemented :
83- methods . add ( "from_multi_systems" )
84- methods . add ( "to_multi_systems" )
85- return methods
92+ methods [ "from_multi_systems" ] = None
93+ methods [ "to_multi_systems" ] = None
94+ return list ( methods . keys ())
8695
8796
8897method_links = {
89- "from_system" : ":func:`System() <dpdata.system.System>`" ,
90- "to_system" : ":func:`System.to() <dpdata.system.System.to>`" ,
91- "from_labeled_system" : ":func:`LabeledSystem() <dpdata.system.LabeledSystem>`" ,
92- "to_labeled_system" : ":func:`LabeledSystem.to() <dpdata.system.System.to>`" ,
93- "from_bond_order_system" : ":func:`BondOrderSystem() <dpdata.bond_order_system.BondOrderSystem>`" ,
94- "to_bond_order_system" : ":func:`BondOrderSystem.to() <dpdata.system.System.to>`" ,
95- "from_multi_systems" : ":func:`MultiSystems.load_systems_from_file() <dpdata.system.MultiSystems.load_systems_from_file>`" ,
96- "to_multi_systems" : ":func:`MultiSystems.to() <dpdata.system.MultiSystems.to>`" ,
98+ "from_system" : ":ref:`System() <{}_{}>`" ,
99+ "to_system" : ":ref:`System.to() <{}_{}>`" ,
100+ "from_labeled_system" : ":ref:`LabeledSystem() <{}_{}>`" ,
101+ "to_labeled_system" : ":ref:`LabeledSystem.to() <{}_{}>`" ,
102+ "from_bond_order_system" : ":ref:`BondOrderSystem() <{}_{}>`" ,
103+ "to_bond_order_system" : ":ref:`BondOrderSystem.to() <{}_{}>`" ,
104+ "from_multi_systems" : ":ref:`MultiSystems.load_systems_from_file() <{}_{}>`" ,
105+ "to_multi_systems" : ":ref:`MultiSystems.to() <{}_{}>`" ,
106+ }
107+
108+ method_classes = {
109+ "from_system" : "System" ,
110+ "to_system" : "System" ,
111+ "from_labeled_system" : "LabeledSystem" ,
112+ "to_labeled_system" : "LabeledSystem" ,
113+ "from_bond_order_system" : "BondOrderSystem" ,
114+ "to_bond_order_system" : "BondOrderSystem" ,
115+ "from_multi_systems" : "MultiSystems" ,
116+ "to_multi_systems" : "MultiSystems" ,
97117}
98118
119+ method_cls_obj = {
120+ "from_system" : System ,
121+ "to_system" : System ,
122+ "from_labeled_system" : LabeledSystem ,
123+ "to_labeled_system" : LabeledSystem ,
124+ "from_bond_order_system" : BondOrderSystem ,
125+ "to_bond_order_system" : BondOrderSystem ,
126+ "from_multi_systems" : MultiSystems ,
127+ "to_multi_systems" : MultiSystems ,
128+ }
129+
130+
131+ def generate_sub_format_pages (formats : dict ):
132+ """Generate sub format pages."""
133+ os .makedirs ("formats" , exist_ok = True )
134+ for format , alias in formats .items ():
135+ # format: Format, alias: list[str]
136+ buff = []
137+ buff .append (".. _%s:" % format .__name__ )
138+ buff .append ("" )
139+ for aa in alias :
140+ buff .append ("%s format" % aa )
141+ buff .append ("=" * len (buff [- 1 ]))
142+ buff .append ("" )
143+ buff .append ("Class: %s" % get_cls_link (format ))
144+ buff .append ("" )
145+
146+ docstring = format .__doc__
147+ if docstring is not None :
148+ docstring = cleandoc (docstring )
149+ rst = str (SphinxDocString (docstring ))
150+ buff .append (rst )
151+ buff .append ("" )
152+
153+ buff .append ("Conversions" )
154+ buff .append ("-----------" )
155+ methods = check_supported (format )
156+ for method in methods :
157+ buff .append ("" )
158+ buff .append (f".. _{ format .__name__ } _{ method } :" )
159+ buff .append ("" )
160+ if method .startswith ("from_" ):
161+ buff .append ("Convert from this format to %s" % method_classes [method ])
162+ buff .append ("`" * len (buff [- 1 ]))
163+ elif method .startswith ("to_" ):
164+ buff .append ("Convert from %s to this format" % method_classes [method ])
165+ buff .append ("`" * len (buff [- 1 ]))
166+ buff .append ("" )
167+ method_obj = getattr (format , method )
168+ if (
169+ method == "to_labeled_system"
170+ and method not in format .__dict__
171+ and "to_system" in format .__dict__
172+ ):
173+ method_obj = getattr (format , "to_system" )
174+ docstring = method_obj .__doc__
175+ if docstring is not None :
176+ docstring = cleandoc (docstring )
177+ sig = signature (method_obj )
178+ parameters = dict (sig .parameters )
179+ return_annotation = sig .return_annotation
180+ # del self
181+ del parameters [list (parameters )[0 ]]
182+ # del data
183+ if method .startswith ("to_" ):
184+ del parameters [list (parameters )[0 ]]
185+ if "args" in parameters :
186+ del parameters ["args" ]
187+ if "kwargs" in parameters :
188+ del parameters ["kwargs" ]
189+ if method == "to_multi_systems" or method .startswith ("from_" ):
190+ sig = Signature (
191+ list (parameters .values ()), return_annotation = method_cls_obj [method ]
192+ )
193+ else :
194+ sig = Signature (
195+ list (parameters .values ()), return_annotation = return_annotation
196+ )
197+ sig = str (sig )
198+ if method .startswith ("from_" ):
199+ if method != "from_multi_systems" :
200+ for aa in alias :
201+ parameters ["fmt" ] = Parameter (
202+ "fmt" ,
203+ Parameter .POSITIONAL_OR_KEYWORD ,
204+ default = None ,
205+ annotation = Literal [aa ],
206+ )
207+ sig_fmt = Signature (
208+ list (parameters .values ()),
209+ return_annotation = method_cls_obj [method ],
210+ )
211+ sig_fmt = str (sig_fmt )
212+ buff .append (
213+ f""".. py:function:: dpdata.{ method_classes [method ]} { sig_fmt } """
214+ )
215+ buff .append (""" :noindex:""" )
216+ for aa in alias :
217+ buff .append (
218+ """.. py:function:: dpdata.{}.from_{}{}""" .format (
219+ method_classes [method ],
220+ aa .replace ("/" , "_" ).replace ("." , "" ),
221+ sig ,
222+ )
223+ )
224+ buff .append (""" :noindex:""" )
225+ buff .append ("" )
226+ if docstring is None or method not in format .__dict__ :
227+ docstring = """ Convert this format to :class:`%s`.""" % (
228+ method_classes [method ]
229+ )
230+ doc_obj = SphinxDocString (docstring )
231+ if len (doc_obj ["Parameters" ]) > 0 :
232+ doc_obj ["Parameters" ] = [
233+ xx
234+ for xx in doc_obj ["Parameters" ]
235+ if xx .name not in ("*args" , "**kwargs" )
236+ ]
237+ else :
238+ if method == "from_multi_systems" :
239+ doc_obj ["Parameters" ] = [
240+ numpydoc_Parameter (
241+ "directory" ,
242+ "str" ,
243+ ["directory of systems" ],
244+ )
245+ ]
246+ doc_obj ["Yields" ] = []
247+ doc_obj ["Returns" ] = [
248+ numpydoc_Parameter ("" , method_classes [method ], ["converted system" ])
249+ ]
250+ rst = " " + str (doc_obj )
251+ buff .append (rst )
252+ buff .append ("" )
253+ elif method .startswith ("to_" ):
254+ for aa in alias :
255+ parameters = {
256+ "fmt" : Parameter (
257+ "fmt" ,
258+ Parameter .POSITIONAL_OR_KEYWORD ,
259+ annotation = Literal [aa ],
260+ ),
261+ ** parameters ,
262+ }
263+ if method == "to_multi_systems" :
264+ sig_fmt = Signature (
265+ list (parameters .values ()),
266+ return_annotation = method_cls_obj [method ],
267+ )
268+ else :
269+ sig_fmt = Signature (
270+ list (parameters .values ()),
271+ return_annotation = return_annotation ,
272+ )
273+ sig_fmt = str (sig_fmt )
274+ buff .append (
275+ f""".. py:function:: dpdata.{ method_classes [method ]} .to{ sig_fmt } """
276+ )
277+ buff .append (""" :noindex:""" )
278+ for aa in alias :
279+ buff .append (
280+ """.. py:function:: dpdata.{}.to_{}{}""" .format (
281+ method_classes [method ],
282+ aa .replace ("/" , "_" ).replace ("." , "" ),
283+ sig ,
284+ )
285+ )
286+ buff .append (""" :noindex:""" )
287+ buff .append ("" )
288+ if docstring is None or (
289+ method not in format .__dict__
290+ and not (
291+ method == "to_labeled_system"
292+ and method not in format .__dict__
293+ and "to_system" in format .__dict__
294+ )
295+ ):
296+ docstring = "Convert :class:`%s` to this format." % (
297+ method_classes [method ]
298+ )
299+ doc_obj = SphinxDocString (docstring )
300+ if len (doc_obj ["Parameters" ]) > 0 :
301+ doc_obj ["Parameters" ] = [
302+ xx
303+ for xx in doc_obj ["Parameters" ][1 :]
304+ if xx .name not in ("*args" , "**kwargs" )
305+ ]
306+ else :
307+ if method == "to_multi_systems" :
308+ doc_obj ["Parameters" ] = [
309+ numpydoc_Parameter (
310+ "directory" ,
311+ "str" ,
312+ ["directory to save systems" ],
313+ )
314+ ]
315+ if method == "to_multi_systems" :
316+ doc_obj ["Yields" ] = []
317+ doc_obj ["Returns" ] = [
318+ numpydoc_Parameter ("" , method_classes [method ], ["this system" ])
319+ ]
320+ rst = " " + str (doc_obj )
321+ buff .append (rst )
322+ buff .append ("" )
323+ buff .append ("" )
324+ buff .append ("" )
325+
326+ with open ("formats/%s.rst" % format .__name__ , "w" ) as rstfile :
327+ rstfile .write ("\n " .join (buff ))
328+
329+
99330if __name__ == "__main__" :
100331 formats = get_formats ()
101332 with open ("formats.csv" , "w" , newline = "" ) as csvfile :
102333 fieldnames = [
103- "Class " ,
334+ "Format " ,
104335 "Alias" ,
105- "Supported Functions " ,
336+ "Supported Conversions " ,
106337 ]
107338 writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
108339
109340 writer .writeheader ()
110341 for kk , vv in formats .items ():
111342 writer .writerow (
112343 {
113- "Class " : get_cls_link ( kk ) ,
344+ "Format " : ":ref:`%s`" % kk . __name__ ,
114345 "Alias" : "\n " .join ("``%s``" % vvv for vvv in vv ),
115- "Supported Functions" : "\n " .join (
116- method_links [mtd ] for mtd in check_supported (kk )
346+ "Supported Conversions" : "\n " .join (
347+ method_links [mtd ].format (kk .__name__ , mtd )
348+ for mtd in check_supported (kk )
117349 ),
118350 }
119351 )
@@ -151,3 +383,4 @@ def check_supported(fmt: Format):
151383 "Alias" : "\n " .join ("``%s``" % vvv for vvv in vv ),
152384 }
153385 )
386+ generate_sub_format_pages (formats )
0 commit comments