22# Based on NetworkManager-1.39.2/tools/generate-docs-nm-settings-docs-merge.py
33# SPDX-License-Identifier: LGPL-2.1-or-later
44import collections
5+ import io
6+ import os
57import textwrap
68import xml .etree .ElementTree as ElementTree
79from argparse import ArgumentParser
@@ -216,34 +218,46 @@ def find_first_not_none(itr: List[Any]) -> Optional[Any]:
216218 return next ((i for i in itr if i is not None ), None )
217219
218220
221+ # Generate docs/options.rst, see:
222+ # https://github.com/python-sdbus/python-sdbus-networkmanager/pull/39#issuecomment-1186522147
223+ def open_options_rst () -> io .TextIOWrapper :
224+ options_rst = open ("docs/options.rst" , "w" )
225+ options_rst .write ("Network Manager settings\n ========================\n " )
226+ return options_rst
227+
228+
229+ def append_sphinx_autoclass (options_rst : io .TextIOWrapper , classname : str ) -> None :
230+ classpath = f"sdbus_async.networkmanager.settings.{ classname } "
231+ options_rst .write (f"\n .. autoclass:: { classpath } \n :members:\n " )
232+
233+
219234# The code quality of this function is poor(Sourcery says 5%), needs refactoring,
220235# also see the rework in tools/generate-settings-dataclasses-jinja.py
221236def main (settings_xml_path : Path ) -> None :
237+ options_rst = open_options_rst ()
222238 gl_input_files = [settings_xml_path ]
223239
224240 xml_roots = [ElementTree .parse (f ).getroot () for f in gl_input_files ]
225241 assert all (root .tag == "nm-setting-docs" for root in xml_roots )
226242 settings_roots = [node_to_dict (root , "setting" , "name" )
227243 for root in xml_roots ]
228244
229- root_node = ElementTree .Element ("nm-setting-docs" )
230-
231245 # Generate the file header
232246 license = "SPDX-License-Identifier: LGPL-2.1-or-later"
233- script = ("This file was generated by "
234- "tools/generate-settings-dataclasses.py" )
247+ script = "This file was generated by tools/generate-settings-dataclasses.py"
235248 header = f"""# { license } \n # { script } ,
236249# if possible, please make changes by also updating the script.\n """
237250 i = open ("sdbus_async/networkmanager/settings/__init__.py" , mode = "w" )
238- p = open ( "sdbus_async/networkmanager/settings/profile.py" , mode = "r" )
239- profile_py = open ("sdbus_async/networkmanager/settings/profile.py" ).read ()
251+ profile_path = "sdbus_async/networkmanager/settings/profile.py"
252+ profile_py = open (profile_path ).read ()
240253
241254 # define start and end markers for generating part of settings/profile.py:
242255 start_string = "# start of the generated list of settings classes\n "
243256 start_index = profile_py .index (start_string ) + len (start_string )
244257 end_string = " # end of the generated list of settings classes\n "
245258 end_index = profile_py .index (end_string )
246- p = open ("sdbus_async/networkmanager/settings/profile.py" , mode = "w" )
259+ profile_path_new = f"{ profile_path } .new"
260+ p = open (profile_path_new , mode = "w" )
247261
248262 # write the file headers
249263 i .write (header )
@@ -296,7 +310,6 @@ def main(settings_xml_path: Path) -> None:
296310 f .write ("\n \n " )
297311
298312 # Generate the settings_class and it's entry in profile.py:
299- setting_node = ElementTree .SubElement (root_node , "setting" )
300313 if module != "connection" :
301314 p .write (f" { module } : Optional[{ classname } ] = field(\n " )
302315 p .write (f" metadata={{'dbus_name': '{ settingname } ',\n " )
@@ -305,7 +318,7 @@ def main(settings_xml_path: Path) -> None:
305318 p .write (" )\n " )
306319 f .write ("@dataclass\n " )
307320 f .write (f"class { classname } (NetworkManagerSettingsMixin):\n " )
308- setting_node . set ( "name" , settingname )
321+ append_sphinx_autoclass ( options_rst , classname )
309322
310323 # generate the docstring of the new settings_class
311324 desc = node_get_attr (settings , "description" )
@@ -316,8 +329,6 @@ def main(settings_xml_path: Path) -> None:
316329 for property in iter_keys_of_dicts (properties , key_fcn_property_name , f'{ settingname } .' ):
317330 property_name = property [len (settingname )+ 1 :]
318331 properties_attrs = [p .get (property_name ) for p in properties ]
319- property_node = ElementTree .SubElement (setting_node , "property" )
320- property_node .set ("name" , property_name )
321332 t = node_get_attr (properties_attrs , "type" )
322333 attribute = property_name .replace ('-' , '_' )
323334 for builtin in ["id" , "type" ]:
@@ -371,9 +382,13 @@ def main(settings_xml_path: Path) -> None:
371382 f .write (line .replace (":@" , ": " ) + '\n ' )
372383 default = node_get_attr (properties_attrs , "default" )
373384 if default in ["{}" , "0" , "-1" ]:
374- default = " None"
385+ default = None
375386 if optional :
376- f .write (f" default={ str (default ).title ()} ,\n " )
387+ if dbustype == "a{ss}" and default :
388+ default = f"field(default_factory = lambda: { default } )"
389+ else :
390+ default = str (default ).title () # FALSE -> False
391+ f .write (f" default={ default } ,\n " )
377392 f .write (" )\n " )
378393
379394 # Generate docstrings for attributes: Not stored by python,
@@ -401,6 +416,7 @@ def main(settings_xml_path: Path) -> None:
401416 i .write (f" '{ cls } ',\n " )
402417 i .write (")\n " )
403418 p .write (profile_py [end_index :])
419+ os .rename (profile_path_new , profile_path )
404420
405421
406422if __name__ == '__main__' :
0 commit comments