HydPy 6.2.dev1__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hydpy/__init__.py +275 -0
- hydpy/aliases.py +2554 -0
- hydpy/auxs/__init__.py +0 -0
- hydpy/auxs/anntools.py +1305 -0
- hydpy/auxs/armatools.py +883 -0
- hydpy/auxs/calibtools.py +3337 -0
- hydpy/auxs/interptools.py +1094 -0
- hydpy/auxs/iuhtools.py +543 -0
- hydpy/auxs/networktools.py +597 -0
- hydpy/auxs/ppolytools.py +809 -0
- hydpy/auxs/quadtools.py +61 -0
- hydpy/auxs/roottools.py +228 -0
- hydpy/auxs/smoothtools.py +273 -0
- hydpy/auxs/statstools.py +2125 -0
- hydpy/auxs/validtools.py +81 -0
- hydpy/conf/HydPyConfigBase.xsd +68637 -0
- hydpy/conf/HydPyConfigBase.xsdt +358 -0
- hydpy/conf/HydPyConfigMultipleRuns.xsd +25 -0
- hydpy/conf/HydPyConfigSingleRun.xsd +24 -0
- hydpy/conf/__init__.py +0 -0
- hydpy/conf/a_coefficients_explicit_lobatto_sequence.npy +0 -0
- hydpy/conf/support_points_for_smoothpar_logistic2.npy +0 -0
- hydpy/config.py +42 -0
- hydpy/core/__init__.py +0 -0
- hydpy/core/aliastools.py +214 -0
- hydpy/core/autodoctools.py +1947 -0
- hydpy/core/auxfiletools.py +1169 -0
- hydpy/core/devicetools.py +3810 -0
- hydpy/core/exceptiontools.py +269 -0
- hydpy/core/filetools.py +1985 -0
- hydpy/core/hydpytools.py +3089 -0
- hydpy/core/importtools.py +1398 -0
- hydpy/core/indextools.py +345 -0
- hydpy/core/itemtools.py +1849 -0
- hydpy/core/masktools.py +460 -0
- hydpy/core/modeltools.py +4868 -0
- hydpy/core/netcdftools.py +2683 -0
- hydpy/core/objecttools.py +2023 -0
- hydpy/core/optiontools.py +1045 -0
- hydpy/core/parametertools.py +4674 -0
- hydpy/core/printtools.py +222 -0
- hydpy/core/propertytools.py +643 -0
- hydpy/core/pubtools.py +254 -0
- hydpy/core/selectiontools.py +1571 -0
- hydpy/core/sequencetools.py +4476 -0
- hydpy/core/seriestools.py +339 -0
- hydpy/core/testtools.py +2483 -0
- hydpy/core/timetools.py +3567 -0
- hydpy/core/typingtools.py +333 -0
- hydpy/core/variabletools.py +2615 -0
- hydpy/cythons/__init__.py +24 -0
- hydpy/cythons/annutils.pxd +33 -0
- hydpy/cythons/annutils.pyi +25 -0
- hydpy/cythons/annutils.pyx +120 -0
- hydpy/cythons/autogen/__init__.py +0 -0
- hydpy/cythons/autogen/annutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/annutils.pxd +42 -0
- hydpy/cythons/autogen/annutils.pyx +129 -0
- hydpy/cythons/autogen/c_arma.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_arma.pxd +179 -0
- hydpy/cythons/autogen/c_arma.pyx +356 -0
- hydpy/cythons/autogen/c_arma_rimorido.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_arma_rimorido.pxd +179 -0
- hydpy/cythons/autogen/c_arma_rimorido.pyx +356 -0
- hydpy/cythons/autogen/c_conv.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv.pxd +198 -0
- hydpy/cythons/autogen/c_conv.pyx +491 -0
- hydpy/cythons/autogen/c_conv_idw.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_idw.pxd +124 -0
- hydpy/cythons/autogen/c_conv_idw.pyx +264 -0
- hydpy/cythons/autogen/c_conv_idw_ed.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_idw_ed.pxd +197 -0
- hydpy/cythons/autogen/c_conv_idw_ed.pyx +481 -0
- hydpy/cythons/autogen/c_conv_nn.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_nn.pxd +120 -0
- hydpy/cythons/autogen/c_conv_nn.pyx +224 -0
- hydpy/cythons/autogen/c_dam.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam.pxd +805 -0
- hydpy/cythons/autogen/c_dam.pyx +1477 -0
- hydpy/cythons/autogen/c_dam_llake.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_llake.pxd +364 -0
- hydpy/cythons/autogen/c_dam_llake.pyx +705 -0
- hydpy/cythons/autogen/c_dam_lreservoir.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_lreservoir.pxd +365 -0
- hydpy/cythons/autogen/c_dam_lreservoir.pyx +708 -0
- hydpy/cythons/autogen/c_dam_lretention.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_lretention.pxd +340 -0
- hydpy/cythons/autogen/c_dam_lretention.pyx +625 -0
- hydpy/cythons/autogen/c_dam_pump.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_pump.pxd +402 -0
- hydpy/cythons/autogen/c_dam_pump.pyx +724 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.pxd +452 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.pyx +829 -0
- hydpy/cythons/autogen/c_dam_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_sluice.pxd +404 -0
- hydpy/cythons/autogen/c_dam_sluice.pyx +726 -0
- hydpy/cythons/autogen/c_dam_v001.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v001.pxd +452 -0
- hydpy/cythons/autogen/c_dam_v001.pyx +816 -0
- hydpy/cythons/autogen/c_dam_v002.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v002.pxd +394 -0
- hydpy/cythons/autogen/c_dam_v002.pyx +703 -0
- hydpy/cythons/autogen/c_dam_v003.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v003.pxd +417 -0
- hydpy/cythons/autogen/c_dam_v003.pyx +744 -0
- hydpy/cythons/autogen/c_dam_v004.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v004.pxd +486 -0
- hydpy/cythons/autogen/c_dam_v004.pyx +891 -0
- hydpy/cythons/autogen/c_dam_v005.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v005.pxd +524 -0
- hydpy/cythons/autogen/c_dam_v005.pyx +928 -0
- hydpy/cythons/autogen/c_dummy.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy.pxd +151 -0
- hydpy/cythons/autogen/c_dummy.pyx +263 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_node2node.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_node2node.pxd +89 -0
- hydpy/cythons/autogen/c_dummy_node2node.pyx +148 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_snowcover.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowcover.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowcover.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_soilwater.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_soilwater.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_soilwater.pyx +104 -0
- hydpy/cythons/autogen/c_evap.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap.pxd +1029 -0
- hydpy/cythons/autogen/c_evap.pyx +2601 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.pxd +227 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.pyx +584 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.pxd +193 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.pyx +478 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.pxd +681 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.pyx +1642 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.pxd +532 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.pyx +1296 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.pxd +179 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.pyx +328 -0
- hydpy/cythons/autogen/c_evap_pet_m.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_m.pxd +124 -0
- hydpy/cythons/autogen/c_evap_pet_m.pyx +214 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.pxd +126 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.pyx +214 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.pxd +305 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.pyx +624 -0
- hydpy/cythons/autogen/c_evap_ret_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_io.pxd +112 -0
- hydpy/cythons/autogen/c_evap_ret_io.pyx +176 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.pxd +139 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.pyx +273 -0
- hydpy/cythons/autogen/c_exch.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch.pxd +230 -0
- hydpy/cythons/autogen/c_exch.pyx +462 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.pxd +134 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.pyx +255 -0
- hydpy/cythons/autogen/c_exch_waterlevel.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_waterlevel.pxd +54 -0
- hydpy/cythons/autogen/c_exch_waterlevel.pyx +78 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.pxd +156 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.pyx +282 -0
- hydpy/cythons/autogen/c_ga.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga.pxd +353 -0
- hydpy/cythons/autogen/c_ga.pyx +1204 -0
- hydpy/cythons/autogen/c_ga_garto.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga_garto.pxd +330 -0
- hydpy/cythons/autogen/c_ga_garto.pyx +1105 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.pxd +236 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.pyx +944 -0
- hydpy/cythons/autogen/c_gland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland.pxd +437 -0
- hydpy/cythons/autogen/c_gland.pyx +726 -0
- hydpy/cythons/autogen/c_gland_gr4.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr4.pxd +382 -0
- hydpy/cythons/autogen/c_gland_gr4.pyx +605 -0
- hydpy/cythons/autogen/c_gland_gr5.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr5.pxd +368 -0
- hydpy/cythons/autogen/c_gland_gr5.pyx +568 -0
- hydpy/cythons/autogen/c_gland_gr6.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr6.pxd +420 -0
- hydpy/cythons/autogen/c_gland_gr6.pyx +673 -0
- hydpy/cythons/autogen/c_hland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland.pxd +855 -0
- hydpy/cythons/autogen/c_hland.pyx +2486 -0
- hydpy/cythons/autogen/c_hland_96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96.pxd +631 -0
- hydpy/cythons/autogen/c_hland_96.pyx +1724 -0
- hydpy/cythons/autogen/c_hland_96c.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96c.pxd +621 -0
- hydpy/cythons/autogen/c_hland_96c.pyx +1822 -0
- hydpy/cythons/autogen/c_hland_96p.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96p.pxd +683 -0
- hydpy/cythons/autogen/c_hland_96p.pyx +1911 -0
- hydpy/cythons/autogen/c_kinw.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw.pxd +509 -0
- hydpy/cythons/autogen/c_kinw.pyx +965 -0
- hydpy/cythons/autogen/c_kinw_williams.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw_williams.pxd +409 -0
- hydpy/cythons/autogen/c_kinw_williams.pyx +763 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.pxd +220 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.pyx +440 -0
- hydpy/cythons/autogen/c_lland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland.pxd +1386 -0
- hydpy/cythons/autogen/c_lland.pyx +3679 -0
- hydpy/cythons/autogen/c_lland_dd.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_dd.pxd +679 -0
- hydpy/cythons/autogen/c_lland_dd.pyx +1719 -0
- hydpy/cythons/autogen/c_lland_knauf.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_knauf.pxd +1096 -0
- hydpy/cythons/autogen/c_lland_knauf.pyx +2784 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.pxd +1369 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.pyx +3625 -0
- hydpy/cythons/autogen/c_meteo.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo.pxd +469 -0
- hydpy/cythons/autogen/c_meteo.pyx +879 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.pxd +75 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.pyx +107 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.pxd +209 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.pyx +339 -0
- hydpy/cythons/autogen/c_meteo_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_io.pxd +63 -0
- hydpy/cythons/autogen/c_meteo_glob_io.pyx +91 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.pxd +289 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.pyx +527 -0
- hydpy/cythons/autogen/c_meteo_precip_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_precip_io.pxd +112 -0
- hydpy/cythons/autogen/c_meteo_precip_io.pyx +176 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pxd +87 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pyx +123 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.pxd +209 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.pyx +343 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.pxd +286 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.pyx +519 -0
- hydpy/cythons/autogen/c_meteo_temp_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_temp_io.pxd +112 -0
- hydpy/cythons/autogen/c_meteo_temp_io.pyx +176 -0
- hydpy/cythons/autogen/c_musk.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk.pxd +282 -0
- hydpy/cythons/autogen/c_musk.pyx +605 -0
- hydpy/cythons/autogen/c_musk_classic.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk_classic.pxd +138 -0
- hydpy/cythons/autogen/c_musk_classic.pyx +226 -0
- hydpy/cythons/autogen/c_musk_mct.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk_mct.pxd +282 -0
- hydpy/cythons/autogen/c_musk_mct.pyx +609 -0
- hydpy/cythons/autogen/c_rconc.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc.pxd +119 -0
- hydpy/cythons/autogen/c_rconc.pyx +174 -0
- hydpy/cythons/autogen/c_rconc_nash.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc_nash.pxd +111 -0
- hydpy/cythons/autogen/c_rconc_nash.pyx +185 -0
- hydpy/cythons/autogen/c_rconc_uh.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc_uh.pxd +92 -0
- hydpy/cythons/autogen/c_rconc_uh.pyx +125 -0
- hydpy/cythons/autogen/c_sw1d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d.pxd +511 -0
- hydpy/cythons/autogen/c_sw1d.pyx +1263 -0
- hydpy/cythons/autogen/c_sw1d_channel.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_channel.pxd +119 -0
- hydpy/cythons/autogen/c_sw1d_channel.pyx +300 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.pxd +240 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.pyx +476 -0
- hydpy/cythons/autogen/c_sw1d_lias.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_lias.pxd +320 -0
- hydpy/cythons/autogen/c_sw1d_lias.pyx +619 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.pxd +325 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.pyx +644 -0
- hydpy/cythons/autogen/c_sw1d_network.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_network.pxd +90 -0
- hydpy/cythons/autogen/c_sw1d_network.pyx +246 -0
- hydpy/cythons/autogen/c_sw1d_pump.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_pump.pxd +256 -0
- hydpy/cythons/autogen/c_sw1d_pump.pyx +502 -0
- hydpy/cythons/autogen/c_sw1d_q_in.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_q_in.pxd +224 -0
- hydpy/cythons/autogen/c_sw1d_q_in.pyx +383 -0
- hydpy/cythons/autogen/c_sw1d_q_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_q_out.pxd +224 -0
- hydpy/cythons/autogen/c_sw1d_q_out.pyx +383 -0
- hydpy/cythons/autogen/c_sw1d_storage.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_storage.pxd +193 -0
- hydpy/cythons/autogen/c_sw1d_storage.pyx +349 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.pxd +212 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.pyx +404 -0
- hydpy/cythons/autogen/c_test.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test.pxd +175 -0
- hydpy/cythons/autogen/c_test.pyx +348 -0
- hydpy/cythons/autogen/c_test_discontinous.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_discontinous.pxd +146 -0
- hydpy/cythons/autogen/c_test_discontinous.pyx +256 -0
- hydpy/cythons/autogen/c_test_stiff0d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_stiff0d.pxd +146 -0
- hydpy/cythons/autogen/c_test_stiff0d.pyx +250 -0
- hydpy/cythons/autogen/c_test_stiff1d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_stiff1d.pxd +145 -0
- hydpy/cythons/autogen/c_test_stiff1d.pyx +294 -0
- hydpy/cythons/autogen/c_whmod.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod.pxd +482 -0
- hydpy/cythons/autogen/c_whmod.pyx +1156 -0
- hydpy/cythons/autogen/c_whmod_rural.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod_rural.pxd +411 -0
- hydpy/cythons/autogen/c_whmod_rural.pyx +982 -0
- hydpy/cythons/autogen/c_whmod_urban.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod_urban.pxd +482 -0
- hydpy/cythons/autogen/c_whmod_urban.pyx +1155 -0
- hydpy/cythons/autogen/c_wland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland.pxd +842 -0
- hydpy/cythons/autogen/c_wland.pyx +1890 -0
- hydpy/cythons/autogen/c_wland_gd.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland_gd.pxd +829 -0
- hydpy/cythons/autogen/c_wland_gd.pyx +1847 -0
- hydpy/cythons/autogen/c_wland_wag.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland_wag.pxd +810 -0
- hydpy/cythons/autogen/c_wland_wag.pyx +1780 -0
- hydpy/cythons/autogen/c_wq.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq.pxd +275 -0
- hydpy/cythons/autogen/c_wq.pyx +652 -0
- hydpy/cythons/autogen/c_wq_trapeze.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_trapeze.pxd +170 -0
- hydpy/cythons/autogen/c_wq_trapeze.pyx +400 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.pxd +243 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.pyx +578 -0
- hydpy/cythons/autogen/c_wq_walrus.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_walrus.pxd +61 -0
- hydpy/cythons/autogen/c_wq_walrus.pyx +82 -0
- hydpy/cythons/autogen/configutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/configutils.pxd +17 -0
- hydpy/cythons/autogen/configutils.pyx +119 -0
- hydpy/cythons/autogen/interfaceutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/interfaceutils.pxd +31 -0
- hydpy/cythons/autogen/interfaceutils.pyx +82 -0
- hydpy/cythons/autogen/interputils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/interputils.pxd +42 -0
- hydpy/cythons/autogen/interputils.pyx +118 -0
- hydpy/cythons/autogen/masterinterface.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/masterinterface.pxd +153 -0
- hydpy/cythons/autogen/masterinterface.pyx +222 -0
- hydpy/cythons/autogen/pointerutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/pointerutils.pxd +31 -0
- hydpy/cythons/autogen/pointerutils.pyx +650 -0
- hydpy/cythons/autogen/ppolyutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/ppolyutils.pxd +35 -0
- hydpy/cythons/autogen/ppolyutils.pyx +59 -0
- hydpy/cythons/autogen/quadutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/quadutils.pxd +26 -0
- hydpy/cythons/autogen/quadutils.pyx +973 -0
- hydpy/cythons/autogen/rootutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/rootutils.pxd +28 -0
- hydpy/cythons/autogen/rootutils.pyx +109 -0
- hydpy/cythons/autogen/sequenceutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/sequenceutils.pxd +45 -0
- hydpy/cythons/autogen/sequenceutils.pyx +101 -0
- hydpy/cythons/autogen/smoothutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/smoothutils.pxd +29 -0
- hydpy/cythons/autogen/smoothutils.pyx +833 -0
- hydpy/cythons/configutils.pxd +8 -0
- hydpy/cythons/configutils.pyi +5 -0
- hydpy/cythons/configutils.pyx +110 -0
- hydpy/cythons/interfaceutils.pxd +22 -0
- hydpy/cythons/interfaceutils.pyi +15 -0
- hydpy/cythons/interfaceutils.pyx +73 -0
- hydpy/cythons/interputils.pxd +33 -0
- hydpy/cythons/interputils.pyi +32 -0
- hydpy/cythons/interputils.pyx +109 -0
- hydpy/cythons/modelutils.py +2990 -0
- hydpy/cythons/pointerutils.pxd +22 -0
- hydpy/cythons/pointerutils.pyi +89 -0
- hydpy/cythons/pointerutils.pyx +641 -0
- hydpy/cythons/ppolyutils.pxd +26 -0
- hydpy/cythons/ppolyutils.pyi +21 -0
- hydpy/cythons/ppolyutils.pyx +50 -0
- hydpy/cythons/quadutils.pxd +17 -0
- hydpy/cythons/quadutils.pyi +13 -0
- hydpy/cythons/quadutils.pyx +964 -0
- hydpy/cythons/rootutils.pxd +19 -0
- hydpy/cythons/rootutils.pyi +21 -0
- hydpy/cythons/rootutils.pyx +100 -0
- hydpy/cythons/sequenceutils.pxd +36 -0
- hydpy/cythons/sequenceutils.pyi +7 -0
- hydpy/cythons/sequenceutils.pyx +92 -0
- hydpy/cythons/smoothutils.pxd +20 -0
- hydpy/cythons/smoothutils.pyi +15 -0
- hydpy/cythons/smoothutils.pyx +824 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_dill_assl.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_kalk.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_leun.py +14 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_marb.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_dill_assl_lahn_leun.py +5 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_leun_lahn_kalk.py +5 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_marb_lahn_leun.py +5 -0
- hydpy/data/HydPy-H-Lahn/control/default/land.py +9 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_dill_assl.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_kalk.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_leun.py +56 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_marb.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_dill_assl_lahn_leun.py +7 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_leun_lahn_kalk.py +7 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_marb_lahn_leun.py +7 -0
- hydpy/data/HydPy-H-Lahn/multiple_runs.xml +309 -0
- hydpy/data/HydPy-H-Lahn/multiple_runs_alpha.xml +71 -0
- hydpy/data/HydPy-H-Lahn/network/default/headwaters.py +11 -0
- hydpy/data/HydPy-H-Lahn/network/default/nonheadwaters.py +11 -0
- hydpy/data/HydPy-H-Lahn/network/default/streams.py +8 -0
- hydpy/data/HydPy-H-Lahn/series/default/dill_assl_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalairtemperature.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalevapotranspiration.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_p.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_t.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_kalk_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_leun_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_marb_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/obs_q.nc +0 -0
- hydpy/data/HydPy-H-Lahn/single_run.xml +152 -0
- hydpy/data/HydPy-H-Lahn/single_run.xmlt +143 -0
- hydpy/data/__init__.py +17 -0
- hydpy/docs/__init__.py +0 -0
- hydpy/docs/autofigs/__init__.py +0 -0
- hydpy/docs/bib/__init__.py +0 -0
- hydpy/docs/bib/refs.bib +566 -0
- hydpy/docs/combine_docversions.py +133 -0
- hydpy/docs/draw_model_sketches.py +1301 -0
- hydpy/docs/enable_autodoc.py +7 -0
- hydpy/docs/figs/HydPy-G-GR4.png +0 -0
- hydpy/docs/figs/HydPy-G-GR5.png +0 -0
- hydpy/docs/figs/HydPy-G-GR6.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96-COSERO.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96-PREVAH.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96.png +0 -0
- hydpy/docs/figs/HydPy-H-Lahn.png +0 -0
- hydpy/docs/figs/HydPy-KinW-Williams.png +0 -0
- hydpy/docs/figs/HydPy-L-DD.png +0 -0
- hydpy/docs/figs/HydPy-W-Wag.png +0 -0
- hydpy/docs/figs/HydPy_Logo.png +0 -0
- hydpy/docs/figs/HydPy_Logo_Text.png +0 -0
- hydpy/docs/figs/IDLE-editor.png +0 -0
- hydpy/docs/figs/IDLE-shell.png +0 -0
- hydpy/docs/figs/LAWA_river-basin-bumbers.png +0 -0
- hydpy/docs/figs/__init__.py +0 -0
- hydpy/docs/html_/__init__.py +0 -0
- hydpy/docs/polish_html.py +57 -0
- hydpy/docs/prepare.py +224 -0
- hydpy/docs/publish_docs.py +53 -0
- hydpy/docs/rst/HydPy-ARMA.rst +27 -0
- hydpy/docs/rst/HydPy-Conv.rst +22 -0
- hydpy/docs/rst/HydPy-Dam.rst +79 -0
- hydpy/docs/rst/HydPy-Dummy.rst +21 -0
- hydpy/docs/rst/HydPy-Evap.rst +26 -0
- hydpy/docs/rst/HydPy-Exch.rst +36 -0
- hydpy/docs/rst/HydPy-G.rst +40 -0
- hydpy/docs/rst/HydPy-GA.rst +34 -0
- hydpy/docs/rst/HydPy-H.rst +24 -0
- hydpy/docs/rst/HydPy-KinW.rst +32 -0
- hydpy/docs/rst/HydPy-L.rst +42 -0
- hydpy/docs/rst/HydPy-Meteo.rst +28 -0
- hydpy/docs/rst/HydPy-Musk.rst +21 -0
- hydpy/docs/rst/HydPy-Rconc.rst +17 -0
- hydpy/docs/rst/HydPy-SW1D.rst +49 -0
- hydpy/docs/rst/HydPy-Test.rst +19 -0
- hydpy/docs/rst/HydPy-W.rst +20 -0
- hydpy/docs/rst/HydPy-WHMod.rst +19 -0
- hydpy/docs/rst/HydPy-WQ.rst +20 -0
- hydpy/docs/rst/__init__.py +0 -0
- hydpy/docs/rst/additional_repositories.rst +40 -0
- hydpy/docs/rst/auxiliaries.rst +31 -0
- hydpy/docs/rst/continuous_integration.rst +75 -0
- hydpy/docs/rst/core.rst +75 -0
- hydpy/docs/rst/cythons.rst +47 -0
- hydpy/docs/rst/definitions.rst +506 -0
- hydpy/docs/rst/developer_guide.rst +54 -0
- hydpy/docs/rst/example_projects.rst +40 -0
- hydpy/docs/rst/execution.rst +22 -0
- hydpy/docs/rst/framework_tools.rst +56 -0
- hydpy/docs/rst/how_to_read_the_reference_manual.rst +156 -0
- hydpy/docs/rst/hydpydependencies.rst +55 -0
- hydpy/docs/rst/index.rst +125 -0
- hydpy/docs/rst/installation.rst +155 -0
- hydpy/docs/rst/model_families.rst +79 -0
- hydpy/docs/rst/model_overview.rst +291 -0
- hydpy/docs/rst/modelimports.rst +10 -0
- hydpy/docs/rst/options.rst +119 -0
- hydpy/docs/rst/programming_style.rst +572 -0
- hydpy/docs/rst/project_structure.rst +520 -0
- hydpy/docs/rst/quickstart.rst +304 -0
- hydpy/docs/rst/reference_manual.rst +29 -0
- hydpy/docs/rst/required_tools.rst +50 -0
- hydpy/docs/rst/simulation.rst +514 -0
- hydpy/docs/rst/submodel_interfaces.rst +32 -0
- hydpy/docs/rst/tests_and_documentation.rst +85 -0
- hydpy/docs/rst/user_guide.rst +38 -0
- hydpy/docs/rst/version_control.rst +116 -0
- hydpy/docs/rst/zbibliography.rst +8 -0
- hydpy/docs/sphinx/__init__.py +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/frameset.html +11 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/rstsource.html +15 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/versionchanges.html +33 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/defindex.html +35 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/domainindex.html +56 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex-single.html +63 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex-split.html +41 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex.html +76 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/globaltoc.html +11 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/layout.html +221 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/localtoc.html +15 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/opensearch.xml +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/page.html +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/relations.html +23 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/search.html +65 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/searchbox.html +21 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/searchfield.html +23 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/sourcelink.html +18 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/basic.css_t +925 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/doctools.js +156 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/documentation_options.js_t +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/file.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/language_data.js_t +26 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/minus.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/plus.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/searchtools.js +574 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/sphinx_highlight.js +154 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/theme.conf +16 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/layout.html +23 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/static/classic.css_t +358 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/static/sidebar.js_t +72 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/theme.conf +32 -0
- hydpy/docs/sphinx/conf.py +398 -0
- hydpy/docs/sphinx/defaultlinks_extension.py +36 -0
- hydpy/docs/sphinx/integrationtest_extension.py +104 -0
- hydpy/docs/sphinx/projectstructure_extension.py +58 -0
- hydpy/docs/sphinx/submodelgraph_extension.py +53 -0
- hydpy/exe/__init__.py +0 -0
- hydpy/exe/commandtools.py +651 -0
- hydpy/exe/hyd.py +277 -0
- hydpy/exe/modelimports.py +41 -0
- hydpy/exe/replacetools.py +216 -0
- hydpy/exe/servertools.py +2348 -0
- hydpy/exe/xmltools.py +3280 -0
- hydpy/interfaces/__init__.py +0 -0
- hydpy/interfaces/aetinterfaces.py +94 -0
- hydpy/interfaces/dischargeinterfaces.py +45 -0
- hydpy/interfaces/petinterfaces.py +117 -0
- hydpy/interfaces/precipinterfaces.py +42 -0
- hydpy/interfaces/radiationinterfaces.py +79 -0
- hydpy/interfaces/rconcinterfaces.py +30 -0
- hydpy/interfaces/routinginterfaces.py +324 -0
- hydpy/interfaces/soilinterfaces.py +96 -0
- hydpy/interfaces/stateinterfaces.py +98 -0
- hydpy/interfaces/tempinterfaces.py +46 -0
- hydpy/models/__init__.py +0 -0
- hydpy/models/arma/__init__.py +14 -0
- hydpy/models/arma/arma_control.py +383 -0
- hydpy/models/arma/arma_derived.py +204 -0
- hydpy/models/arma/arma_fluxes.py +41 -0
- hydpy/models/arma/arma_inlets.py +11 -0
- hydpy/models/arma/arma_logs.py +19 -0
- hydpy/models/arma/arma_model.py +461 -0
- hydpy/models/arma/arma_outlets.py +11 -0
- hydpy/models/arma_rimorido.py +381 -0
- hydpy/models/conv/__init__.py +12 -0
- hydpy/models/conv/conv_control.py +303 -0
- hydpy/models/conv/conv_derived.py +271 -0
- hydpy/models/conv/conv_fluxes.py +54 -0
- hydpy/models/conv/conv_inlets.py +11 -0
- hydpy/models/conv/conv_model.py +687 -0
- hydpy/models/conv/conv_outlets.py +11 -0
- hydpy/models/conv_idw.py +120 -0
- hydpy/models/conv_idw_ed.py +184 -0
- hydpy/models/conv_nn.py +112 -0
- hydpy/models/dam/__init__.py +16 -0
- hydpy/models/dam/dam_aides.py +17 -0
- hydpy/models/dam/dam_control.py +346 -0
- hydpy/models/dam/dam_derived.py +559 -0
- hydpy/models/dam/dam_factors.py +46 -0
- hydpy/models/dam/dam_fluxes.py +179 -0
- hydpy/models/dam/dam_inlets.py +29 -0
- hydpy/models/dam/dam_logs.py +52 -0
- hydpy/models/dam/dam_model.py +5011 -0
- hydpy/models/dam/dam_outlets.py +23 -0
- hydpy/models/dam/dam_receivers.py +41 -0
- hydpy/models/dam/dam_senders.py +23 -0
- hydpy/models/dam/dam_solver.py +75 -0
- hydpy/models/dam/dam_states.py +11 -0
- hydpy/models/dam_llake.py +499 -0
- hydpy/models/dam_lreservoir.py +548 -0
- hydpy/models/dam_lretention.py +343 -0
- hydpy/models/dam_pump.py +278 -0
- hydpy/models/dam_pump_sluice.py +339 -0
- hydpy/models/dam_sluice.py +319 -0
- hydpy/models/dam_v001.py +1127 -0
- hydpy/models/dam_v002.py +381 -0
- hydpy/models/dam_v003.py +422 -0
- hydpy/models/dam_v004.py +665 -0
- hydpy/models/dam_v005.py +479 -0
- hydpy/models/dummy/__init__.py +15 -0
- hydpy/models/dummy/dummy_control.py +22 -0
- hydpy/models/dummy/dummy_fluxes.py +11 -0
- hydpy/models/dummy/dummy_inlets.py +11 -0
- hydpy/models/dummy/dummy_inputs.py +41 -0
- hydpy/models/dummy/dummy_model.py +196 -0
- hydpy/models/dummy/dummy_outlets.py +11 -0
- hydpy/models/dummy_interceptedwater.py +85 -0
- hydpy/models/dummy_node2node.py +83 -0
- hydpy/models/dummy_snowalbedo.py +84 -0
- hydpy/models/dummy_snowcover.py +84 -0
- hydpy/models/dummy_snowycanopy.py +86 -0
- hydpy/models/dummy_soilwater.py +85 -0
- hydpy/models/evap/__init__.py +13 -0
- hydpy/models/evap/evap_control.py +354 -0
- hydpy/models/evap/evap_derived.py +236 -0
- hydpy/models/evap/evap_factors.py +188 -0
- hydpy/models/evap/evap_fixed.py +68 -0
- hydpy/models/evap/evap_fluxes.py +150 -0
- hydpy/models/evap/evap_inputs.py +54 -0
- hydpy/models/evap/evap_logs.py +91 -0
- hydpy/models/evap/evap_masks.py +48 -0
- hydpy/models/evap/evap_model.py +9170 -0
- hydpy/models/evap/evap_parameters.py +149 -0
- hydpy/models/evap/evap_sequences.py +32 -0
- hydpy/models/evap/evap_states.py +18 -0
- hydpy/models/evap_aet_hbv96.py +372 -0
- hydpy/models/evap_aet_minhas.py +331 -0
- hydpy/models/evap_aet_morsim.py +627 -0
- hydpy/models/evap_pet_ambav1.py +483 -0
- hydpy/models/evap_pet_hbv96.py +147 -0
- hydpy/models/evap_pet_m.py +94 -0
- hydpy/models/evap_pet_mlc.py +107 -0
- hydpy/models/evap_ret_fao56.py +265 -0
- hydpy/models/evap_ret_io.py +74 -0
- hydpy/models/evap_ret_tw2002.py +165 -0
- hydpy/models/exch/__init__.py +14 -0
- hydpy/models/exch/exch_control.py +262 -0
- hydpy/models/exch/exch_derived.py +36 -0
- hydpy/models/exch/exch_factors.py +26 -0
- hydpy/models/exch/exch_fluxes.py +48 -0
- hydpy/models/exch/exch_inlets.py +11 -0
- hydpy/models/exch/exch_logs.py +12 -0
- hydpy/models/exch/exch_model.py +451 -0
- hydpy/models/exch/exch_outlets.py +17 -0
- hydpy/models/exch/exch_receivers.py +17 -0
- hydpy/models/exch_branch_hbv96.py +186 -0
- hydpy/models/exch_waterlevel.py +73 -0
- hydpy/models/exch_weir_hbv96.py +609 -0
- hydpy/models/ga/__init__.py +14 -0
- hydpy/models/ga/ga_aides.py +17 -0
- hydpy/models/ga/ga_control.py +208 -0
- hydpy/models/ga/ga_derived.py +77 -0
- hydpy/models/ga/ga_fluxes.py +83 -0
- hydpy/models/ga/ga_inputs.py +26 -0
- hydpy/models/ga/ga_logs.py +17 -0
- hydpy/models/ga/ga_model.py +2952 -0
- hydpy/models/ga/ga_states.py +87 -0
- hydpy/models/ga_garto.py +1001 -0
- hydpy/models/ga_garto_submodel1.py +79 -0
- hydpy/models/gland/__init__.py +14 -0
- hydpy/models/gland/gland_control.py +90 -0
- hydpy/models/gland/gland_derived.py +113 -0
- hydpy/models/gland/gland_fluxes.py +137 -0
- hydpy/models/gland/gland_inputs.py +12 -0
- hydpy/models/gland/gland_model.py +1439 -0
- hydpy/models/gland/gland_outlets.py +11 -0
- hydpy/models/gland/gland_states.py +90 -0
- hydpy/models/gland_gr4.py +501 -0
- hydpy/models/gland_gr5.py +463 -0
- hydpy/models/gland_gr6.py +487 -0
- hydpy/models/hland/__init__.py +20 -0
- hydpy/models/hland/hland_aides.py +19 -0
- hydpy/models/hland/hland_constants.py +37 -0
- hydpy/models/hland/hland_control.py +1530 -0
- hydpy/models/hland/hland_derived.py +683 -0
- hydpy/models/hland/hland_factors.py +57 -0
- hydpy/models/hland/hland_fixed.py +42 -0
- hydpy/models/hland/hland_fluxes.py +279 -0
- hydpy/models/hland/hland_inputs.py +19 -0
- hydpy/models/hland/hland_masks.py +107 -0
- hydpy/models/hland/hland_model.py +4664 -0
- hydpy/models/hland/hland_outlets.py +11 -0
- hydpy/models/hland/hland_parameters.py +227 -0
- hydpy/models/hland/hland_sequences.py +382 -0
- hydpy/models/hland/hland_states.py +236 -0
- hydpy/models/hland_96.py +1812 -0
- hydpy/models/hland_96c.py +1196 -0
- hydpy/models/hland_96p.py +1204 -0
- hydpy/models/kinw/__init__.py +18 -0
- hydpy/models/kinw/kinw_aides.py +306 -0
- hydpy/models/kinw/kinw_control.py +270 -0
- hydpy/models/kinw/kinw_derived.py +197 -0
- hydpy/models/kinw/kinw_fixed.py +33 -0
- hydpy/models/kinw/kinw_fluxes.py +37 -0
- hydpy/models/kinw/kinw_inlets.py +11 -0
- hydpy/models/kinw/kinw_model.py +3026 -0
- hydpy/models/kinw/kinw_outlets.py +11 -0
- hydpy/models/kinw/kinw_solver.py +45 -0
- hydpy/models/kinw/kinw_states.py +17 -0
- hydpy/models/kinw_williams.py +1299 -0
- hydpy/models/kinw_williams_ext.py +768 -0
- hydpy/models/lland/__init__.py +42 -0
- hydpy/models/lland/lland_aides.py +38 -0
- hydpy/models/lland/lland_constants.py +88 -0
- hydpy/models/lland/lland_control.py +1329 -0
- hydpy/models/lland/lland_derived.py +380 -0
- hydpy/models/lland/lland_factors.py +18 -0
- hydpy/models/lland/lland_fixed.py +128 -0
- hydpy/models/lland/lland_fluxes.py +626 -0
- hydpy/models/lland/lland_inlets.py +12 -0
- hydpy/models/lland/lland_inputs.py +33 -0
- hydpy/models/lland/lland_logs.py +17 -0
- hydpy/models/lland/lland_masks.py +212 -0
- hydpy/models/lland/lland_model.py +7690 -0
- hydpy/models/lland/lland_outlets.py +12 -0
- hydpy/models/lland/lland_parameters.py +195 -0
- hydpy/models/lland/lland_sequences.py +67 -0
- hydpy/models/lland/lland_states.py +280 -0
- hydpy/models/lland_dd.py +2270 -0
- hydpy/models/lland_knauf.py +2156 -0
- hydpy/models/lland_knauf_ic.py +1920 -0
- hydpy/models/meteo/__init__.py +12 -0
- hydpy/models/meteo/meteo_control.py +154 -0
- hydpy/models/meteo/meteo_derived.py +159 -0
- hydpy/models/meteo/meteo_factors.py +88 -0
- hydpy/models/meteo/meteo_fixed.py +19 -0
- hydpy/models/meteo/meteo_fluxes.py +46 -0
- hydpy/models/meteo/meteo_inputs.py +47 -0
- hydpy/models/meteo/meteo_logs.py +30 -0
- hydpy/models/meteo/meteo_model.py +2904 -0
- hydpy/models/meteo/meteo_parameters.py +14 -0
- hydpy/models/meteo/meteo_sequences.py +22 -0
- hydpy/models/meteo_clear_glob_io.py +77 -0
- hydpy/models/meteo_glob_fao56.py +217 -0
- hydpy/models/meteo_glob_io.py +68 -0
- hydpy/models/meteo_glob_morsim.py +444 -0
- hydpy/models/meteo_precip_io.py +76 -0
- hydpy/models/meteo_psun_sun_glob_io.py +83 -0
- hydpy/models/meteo_sun_fao56.py +188 -0
- hydpy/models/meteo_sun_morsim.py +466 -0
- hydpy/models/meteo_temp_io.py +76 -0
- hydpy/models/musk/__init__.py +15 -0
- hydpy/models/musk/musk_control.py +328 -0
- hydpy/models/musk/musk_derived.py +32 -0
- hydpy/models/musk/musk_factors.py +53 -0
- hydpy/models/musk/musk_fluxes.py +24 -0
- hydpy/models/musk/musk_inlets.py +11 -0
- hydpy/models/musk/musk_masks.py +15 -0
- hydpy/models/musk/musk_model.py +838 -0
- hydpy/models/musk/musk_outlets.py +11 -0
- hydpy/models/musk/musk_sequences.py +88 -0
- hydpy/models/musk/musk_solver.py +68 -0
- hydpy/models/musk/musk_states.py +64 -0
- hydpy/models/musk_classic.py +228 -0
- hydpy/models/musk_mct.py +1247 -0
- hydpy/models/rconc/__init__.py +12 -0
- hydpy/models/rconc/rconc_control.py +473 -0
- hydpy/models/rconc/rconc_derived.py +76 -0
- hydpy/models/rconc/rconc_fluxes.py +19 -0
- hydpy/models/rconc/rconc_logs.py +74 -0
- hydpy/models/rconc/rconc_model.py +260 -0
- hydpy/models/rconc/rconc_states.py +11 -0
- hydpy/models/rconc_nash.py +48 -0
- hydpy/models/rconc_uh.py +53 -0
- hydpy/models/sw1d/__init__.py +17 -0
- hydpy/models/sw1d/sw1d_control.py +356 -0
- hydpy/models/sw1d/sw1d_derived.py +85 -0
- hydpy/models/sw1d/sw1d_factors.py +78 -0
- hydpy/models/sw1d/sw1d_fixed.py +12 -0
- hydpy/models/sw1d/sw1d_fluxes.py +55 -0
- hydpy/models/sw1d/sw1d_inlets.py +17 -0
- hydpy/models/sw1d/sw1d_model.py +3385 -0
- hydpy/models/sw1d/sw1d_outlets.py +11 -0
- hydpy/models/sw1d/sw1d_receivers.py +11 -0
- hydpy/models/sw1d/sw1d_senders.py +11 -0
- hydpy/models/sw1d/sw1d_states.py +23 -0
- hydpy/models/sw1d_channel.py +2051 -0
- hydpy/models/sw1d_gate_out.py +599 -0
- hydpy/models/sw1d_lias.py +105 -0
- hydpy/models/sw1d_lias_sluice.py +531 -0
- hydpy/models/sw1d_network.py +1219 -0
- hydpy/models/sw1d_pump.py +448 -0
- hydpy/models/sw1d_q_in.py +79 -0
- hydpy/models/sw1d_q_out.py +81 -0
- hydpy/models/sw1d_storage.py +78 -0
- hydpy/models/sw1d_weir_out.py +75 -0
- hydpy/models/test/__init__.py +14 -0
- hydpy/models/test/test_control.py +28 -0
- hydpy/models/test/test_fluxes.py +17 -0
- hydpy/models/test/test_model.py +201 -0
- hydpy/models/test/test_solver.py +48 -0
- hydpy/models/test/test_states.py +17 -0
- hydpy/models/test_discontinous.py +46 -0
- hydpy/models/test_stiff0d.py +47 -0
- hydpy/models/test_stiff1d.py +42 -0
- hydpy/models/whmod/__init__.py +21 -0
- hydpy/models/whmod/whmod_constants.py +77 -0
- hydpy/models/whmod/whmod_control.py +333 -0
- hydpy/models/whmod/whmod_derived.py +210 -0
- hydpy/models/whmod/whmod_factors.py +9 -0
- hydpy/models/whmod/whmod_fluxes.py +105 -0
- hydpy/models/whmod/whmod_inputs.py +15 -0
- hydpy/models/whmod/whmod_masks.py +178 -0
- hydpy/models/whmod/whmod_model.py +2091 -0
- hydpy/models/whmod/whmod_parameters.py +155 -0
- hydpy/models/whmod/whmod_sequences.py +193 -0
- hydpy/models/whmod/whmod_states.py +73 -0
- hydpy/models/whmod_rural.py +794 -0
- hydpy/models/whmod_urban.py +1011 -0
- hydpy/models/wland/__init__.py +43 -0
- hydpy/models/wland/wland_aides.py +55 -0
- hydpy/models/wland/wland_constants.py +103 -0
- hydpy/models/wland/wland_control.py +508 -0
- hydpy/models/wland/wland_derived.py +330 -0
- hydpy/models/wland/wland_factors.py +11 -0
- hydpy/models/wland/wland_fixed.py +12 -0
- hydpy/models/wland/wland_fluxes.py +166 -0
- hydpy/models/wland/wland_inputs.py +33 -0
- hydpy/models/wland/wland_masks.py +54 -0
- hydpy/models/wland/wland_model.py +3755 -0
- hydpy/models/wland/wland_outlets.py +11 -0
- hydpy/models/wland/wland_parameters.py +214 -0
- hydpy/models/wland/wland_sequences.py +108 -0
- hydpy/models/wland/wland_solver.py +45 -0
- hydpy/models/wland/wland_states.py +56 -0
- hydpy/models/wland_gd.py +888 -0
- hydpy/models/wland_wag.py +1244 -0
- hydpy/models/wq/__init__.py +14 -0
- hydpy/models/wq/wq_control.py +117 -0
- hydpy/models/wq/wq_derived.py +182 -0
- hydpy/models/wq/wq_factors.py +79 -0
- hydpy/models/wq/wq_fluxes.py +17 -0
- hydpy/models/wq/wq_model.py +1889 -0
- hydpy/models/wq_trapeze.py +168 -0
- hydpy/models/wq_trapeze_strickler.py +101 -0
- hydpy/models/wq_walrus.py +57 -0
- hydpy/py.typed +0 -0
- hydpy/tests/.coveragerc +22 -0
- hydpy/tests/__init__.py +0 -0
- hydpy/tests/check_consistency.py +32 -0
- hydpy/tests/hydpydoctestcustomize.pth +1 -0
- hydpy/tests/hydpydoctestcustomize.py +15 -0
- hydpy/tests/iotesting/__init__.py +0 -0
- hydpy/tests/run_doctests.py +233 -0
- hydpy-6.2.dev1.data/scripts/hyd.py +277 -0
- hydpy-6.2.dev1.dist-info/LICENSE +165 -0
- hydpy-6.2.dev1.dist-info/METADATA +163 -0
- hydpy-6.2.dev1.dist-info/RECORD +890 -0
- hydpy-6.2.dev1.dist-info/WHEEL +5 -0
- hydpy-6.2.dev1.dist-info/licenses_hydpy_installer.txt +42 -0
- hydpy-6.2.dev1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1947 @@
|
|
|
1
|
+
"""This module implements tools for increasing the level of automation and
|
|
2
|
+
standardisation of the online documentation generated with Sphinx."""
|
|
3
|
+
|
|
4
|
+
# import...
|
|
5
|
+
# ...from standard library
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import abc
|
|
8
|
+
import builtins
|
|
9
|
+
import collections
|
|
10
|
+
import copy
|
|
11
|
+
import datetime
|
|
12
|
+
import doctest
|
|
13
|
+
import enum
|
|
14
|
+
import functools
|
|
15
|
+
import importlib
|
|
16
|
+
import inspect
|
|
17
|
+
import itertools
|
|
18
|
+
import io
|
|
19
|
+
import math
|
|
20
|
+
import mimetypes
|
|
21
|
+
import os
|
|
22
|
+
import platform
|
|
23
|
+
import pkgutil
|
|
24
|
+
import subprocess
|
|
25
|
+
import sys
|
|
26
|
+
import time
|
|
27
|
+
import types
|
|
28
|
+
import typing
|
|
29
|
+
import unittest
|
|
30
|
+
import warnings
|
|
31
|
+
|
|
32
|
+
# ...from site-packages
|
|
33
|
+
# import matplotlib actual import below
|
|
34
|
+
import numpy
|
|
35
|
+
import typing_extensions
|
|
36
|
+
|
|
37
|
+
# import pandas actual import below
|
|
38
|
+
# import scipy actual import below
|
|
39
|
+
# ...from HydPy
|
|
40
|
+
import hydpy
|
|
41
|
+
from hydpy import auxs
|
|
42
|
+
from hydpy import core
|
|
43
|
+
from hydpy import cythons
|
|
44
|
+
from hydpy import exe
|
|
45
|
+
from hydpy import interfaces
|
|
46
|
+
from hydpy import models
|
|
47
|
+
from hydpy.core import modeltools
|
|
48
|
+
from hydpy.core import objecttools
|
|
49
|
+
from hydpy.core import sequencetools
|
|
50
|
+
from hydpy.core import typingtools
|
|
51
|
+
from hydpy.core.typingtools import *
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if TYPE_CHECKING:
|
|
55
|
+
from hydpy.cythons import annutils
|
|
56
|
+
from hydpy.cythons import interputils
|
|
57
|
+
from hydpy.cythons import ppolyutils
|
|
58
|
+
from hydpy.cythons import pointerutils
|
|
59
|
+
from hydpy.cythons import quadutils
|
|
60
|
+
from hydpy.cythons import rootutils
|
|
61
|
+
from hydpy.cythons import smoothutils
|
|
62
|
+
else:
|
|
63
|
+
from hydpy.cythons.autogen import annutils
|
|
64
|
+
from hydpy.cythons.autogen import interputils
|
|
65
|
+
from hydpy.cythons.autogen import ppolyutils
|
|
66
|
+
from hydpy.cythons.autogen import pointerutils
|
|
67
|
+
from hydpy.cythons.autogen import quadutils
|
|
68
|
+
from hydpy.cythons.autogen import rootutils
|
|
69
|
+
from hydpy.cythons.autogen import smoothutils
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Priority(enum.Enum):
|
|
73
|
+
"""Priority level for members defined in different sources."""
|
|
74
|
+
|
|
75
|
+
BUILTINS = 0
|
|
76
|
+
"""Priority level for members defined in |builtins|."""
|
|
77
|
+
CORE = 1
|
|
78
|
+
"""Priority level for members defined in the `core` subpackage."""
|
|
79
|
+
EXE = 2
|
|
80
|
+
"""Priority level for members defined in the `exe` subpackage."""
|
|
81
|
+
AUXS = 3
|
|
82
|
+
"""Priority level for members defined in the `auxs` subpackage."""
|
|
83
|
+
CYTHONS = 4
|
|
84
|
+
"""Priority level for members defined in the `cythons` subpackage."""
|
|
85
|
+
MODELS = 5
|
|
86
|
+
"""Priority level for members defined in the `models` subpackage."""
|
|
87
|
+
HYDPY = 6
|
|
88
|
+
"""Priority level for *HydPy* members not falling in the other categories."""
|
|
89
|
+
ELSE = 7
|
|
90
|
+
"""Priority level for non-*HydPy* and non |builtins| members."""
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def get_priority(cls, modulename: str) -> Priority:
|
|
94
|
+
"""Return the priority for the given module name.
|
|
95
|
+
|
|
96
|
+
>>> from hydpy.core.autodoctools import Priority
|
|
97
|
+
>>> assert Priority.get_priority("builtins") == Priority.BUILTINS
|
|
98
|
+
>>> assert Priority.get_priority("hydpy.core.test") == Priority.CORE
|
|
99
|
+
>>> assert Priority.get_priority("hydpy.exe.test") == Priority.EXE
|
|
100
|
+
>>> assert Priority.get_priority("hydpy.auxs.test") == Priority.AUXS
|
|
101
|
+
>>> assert Priority.get_priority("hydpy.cythons.test") == Priority.CYTHONS
|
|
102
|
+
>>> assert Priority.get_priority("hydpy.models.test") == Priority.MODELS
|
|
103
|
+
>>> assert Priority.get_priority("hydpy.test") == Priority.HYDPY
|
|
104
|
+
>>> assert Priority.get_priority("numpy.test") == Priority.ELSE
|
|
105
|
+
"""
|
|
106
|
+
if "builtin" in modulename:
|
|
107
|
+
return BUILTINS
|
|
108
|
+
if modulename.startswith("hydpy.core"):
|
|
109
|
+
return CORE
|
|
110
|
+
if modulename.startswith("hydpy.exe"):
|
|
111
|
+
return EXE
|
|
112
|
+
if modulename.startswith("hydpy.auxs"):
|
|
113
|
+
return AUXS
|
|
114
|
+
if modulename.startswith("hydpy.cythons"):
|
|
115
|
+
return CYTHONS
|
|
116
|
+
if modulename.startswith("hydpy.models"):
|
|
117
|
+
return MODELS
|
|
118
|
+
if modulename.startswith("hydpy"):
|
|
119
|
+
return HYDPY
|
|
120
|
+
return ELSE
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
BUILTINS = Priority.BUILTINS
|
|
124
|
+
CORE = Priority.CORE
|
|
125
|
+
EXE = Priority.EXE
|
|
126
|
+
AUXS = Priority.AUXS
|
|
127
|
+
CYTHONS = Priority.CYTHONS
|
|
128
|
+
MODELS = Priority.MODELS
|
|
129
|
+
HYDPY = Priority.HYDPY
|
|
130
|
+
ELSE = Priority.ELSE
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
excluded_members = {
|
|
134
|
+
"CLASSES",
|
|
135
|
+
"RUN_METHODS",
|
|
136
|
+
"INTERFACE_METHODS",
|
|
137
|
+
"ADD_METHODS",
|
|
138
|
+
"INLET_METHODS",
|
|
139
|
+
"OUTLET_METHODS",
|
|
140
|
+
"RECEIVER_METHODS",
|
|
141
|
+
"SENDER_METHODS",
|
|
142
|
+
"PART_ODE_METHODS",
|
|
143
|
+
"FULL_ODE_METHODS",
|
|
144
|
+
"CONTROLPARAMETERS",
|
|
145
|
+
"DERIVEDPARAMETERS",
|
|
146
|
+
"FIXEDPARAMETERS",
|
|
147
|
+
"REQUIREDSEQUENCES",
|
|
148
|
+
"UPDATEDSEQUENCES",
|
|
149
|
+
"RESULTSEQUENCES",
|
|
150
|
+
"SOLVERPARAMETERS",
|
|
151
|
+
"SOLVERSEQUENCES",
|
|
152
|
+
"SUBMETHODS",
|
|
153
|
+
"SUBMODELINTERFACES",
|
|
154
|
+
"SUBMODELS",
|
|
155
|
+
"fastaccess",
|
|
156
|
+
"fastaccess_new",
|
|
157
|
+
"fastaccess_old",
|
|
158
|
+
"pars",
|
|
159
|
+
"seqs",
|
|
160
|
+
"subvars",
|
|
161
|
+
"subpars",
|
|
162
|
+
"subseqs",
|
|
163
|
+
}
|
|
164
|
+
excluded_members.update(typing.__all__)
|
|
165
|
+
excluded_members.update(typing_extensions.__all__)
|
|
166
|
+
|
|
167
|
+
_PAR_SPEC2CAPT = collections.OrderedDict(
|
|
168
|
+
(
|
|
169
|
+
("parameters", "Parameter tools"),
|
|
170
|
+
("constants", "Constants"),
|
|
171
|
+
("control", "Control parameters"),
|
|
172
|
+
("derived", "Derived parameters"),
|
|
173
|
+
("fixed", "Fixed parameters"),
|
|
174
|
+
("solver", "Solver parameters"),
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
_SEQ_SPEC2CAPT = collections.OrderedDict(
|
|
179
|
+
(
|
|
180
|
+
("sequences", "Sequence tools"),
|
|
181
|
+
("inputs", "Input sequences"),
|
|
182
|
+
("factors", "Factor sequences"),
|
|
183
|
+
("fluxes", "Flux sequences"),
|
|
184
|
+
("states", "State sequences"),
|
|
185
|
+
("logs", "Log sequences"),
|
|
186
|
+
("inlets", "Inlet sequences"),
|
|
187
|
+
("outlets", "Outlet sequences"),
|
|
188
|
+
("receivers", "Receiver sequences"),
|
|
189
|
+
("senders", "Sender sequences"),
|
|
190
|
+
("aides", "Aide sequences"),
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
_AUX_SPEC2CAPT = collections.OrderedDict((("masks", "Masks"),))
|
|
195
|
+
|
|
196
|
+
_all_spec2capt = _PAR_SPEC2CAPT.copy()
|
|
197
|
+
_all_spec2capt.update(_SEQ_SPEC2CAPT)
|
|
198
|
+
_all_spec2capt.update(_AUX_SPEC2CAPT)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _add_title(title: str, marker: str) -> list[str]:
|
|
202
|
+
"""Return a title for a basemodels docstring."""
|
|
203
|
+
return ["", title, marker * len(title)]
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _add_lines(specification: str, module: types.ModuleType) -> list[str]:
|
|
207
|
+
"""Return autodoc commands for a basemodels docstring.
|
|
208
|
+
|
|
209
|
+
Note that `collection classes` (e.g. `Model`, `ControlParameters`, `InputSequences`
|
|
210
|
+
are placed on top of the respective section and the `contained classes` (e.g. model
|
|
211
|
+
methods, `ControlParameter` instances, `InputSequence` instances at the bottom.
|
|
212
|
+
This differs from the order of their definition in the respective modules, but
|
|
213
|
+
results in a better documentation structure.
|
|
214
|
+
"""
|
|
215
|
+
caption = _all_spec2capt.get(specification, "dummy")
|
|
216
|
+
if caption.split()[-1] in ("parameters", "sequences", "Masks"):
|
|
217
|
+
name_collectionclass = caption.title().replace(" ", "")
|
|
218
|
+
else:
|
|
219
|
+
name_collectionclass = None
|
|
220
|
+
lines = []
|
|
221
|
+
exc_mem = ", ".join(excluded_members)
|
|
222
|
+
if specification == "model":
|
|
223
|
+
lines += [
|
|
224
|
+
"",
|
|
225
|
+
f".. autoclass:: {module.__name__}.Model",
|
|
226
|
+
" :members:",
|
|
227
|
+
" :show-inheritance:",
|
|
228
|
+
f" :exclude-members: {exc_mem}",
|
|
229
|
+
]
|
|
230
|
+
elif name_collectionclass is not None:
|
|
231
|
+
lines += [
|
|
232
|
+
"",
|
|
233
|
+
f'.. autoclass:: {module.__name__.rpartition(".")[0]}'
|
|
234
|
+
f".{name_collectionclass}",
|
|
235
|
+
" :members:",
|
|
236
|
+
" :noindex:",
|
|
237
|
+
" :show-inheritance:",
|
|
238
|
+
f" :exclude-members: {exc_mem}",
|
|
239
|
+
]
|
|
240
|
+
lines += [
|
|
241
|
+
"",
|
|
242
|
+
".. automodule:: " + module.__name__,
|
|
243
|
+
" :members:",
|
|
244
|
+
" :show-inheritance:",
|
|
245
|
+
]
|
|
246
|
+
if specification == "model":
|
|
247
|
+
lines += [f" :exclude-members: Model, {exc_mem}"]
|
|
248
|
+
elif name_collectionclass is None:
|
|
249
|
+
lines += [f" :exclude-members: {exc_mem}"]
|
|
250
|
+
else:
|
|
251
|
+
lines += [f" :exclude-members: {name_collectionclass}, {exc_mem}"]
|
|
252
|
+
return lines
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def autodoc_basemodel(module: types.ModuleType) -> None:
|
|
256
|
+
"""Add an exhaustive docstring to the given module of a basemodel.
|
|
257
|
+
|
|
258
|
+
Works onlye when all modules of the basemodel are named in the standard way, e.g.
|
|
259
|
+
`lland_model`, `lland_control`, `lland_inputs`.
|
|
260
|
+
"""
|
|
261
|
+
autodoc_tuple2doc(module)
|
|
262
|
+
namespace = module.__dict__
|
|
263
|
+
moduledoc = namespace.get("__doc__")
|
|
264
|
+
assert isinstance(moduledoc, str)
|
|
265
|
+
basemodulename = namespace["__name__"].split(".")[-1]
|
|
266
|
+
modules = {
|
|
267
|
+
key: value
|
|
268
|
+
for key, value in namespace.items()
|
|
269
|
+
if (
|
|
270
|
+
isinstance(value, types.ModuleType) and key.startswith(basemodulename + "_")
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
substituter = Substituter(hydpy.substituter)
|
|
274
|
+
lines = []
|
|
275
|
+
specification = "model"
|
|
276
|
+
modulename = f"{basemodulename}_{specification}"
|
|
277
|
+
methods: tuple[type[modeltools.Method], ...] = ()
|
|
278
|
+
if modulename in modules:
|
|
279
|
+
module = modules[modulename]
|
|
280
|
+
lines += _add_title("Method Features", "-")
|
|
281
|
+
lines += _add_lines(specification, module)
|
|
282
|
+
substituter.add_module(module)
|
|
283
|
+
model = module.Model
|
|
284
|
+
assert issubclass(model, modeltools.Model)
|
|
285
|
+
methods = tuple(model.get_methods())
|
|
286
|
+
_extend_methoddocstrings(module)
|
|
287
|
+
_gain_and_insert_additional_information_into_docstrings(module, methods)
|
|
288
|
+
for title, spec2capt in (
|
|
289
|
+
("Parameter Features", _PAR_SPEC2CAPT),
|
|
290
|
+
("Sequence Features", _SEQ_SPEC2CAPT),
|
|
291
|
+
("Auxiliary Features", _AUX_SPEC2CAPT),
|
|
292
|
+
):
|
|
293
|
+
found_module = False
|
|
294
|
+
new_lines = _add_title(title, "-")
|
|
295
|
+
for specification, caption in spec2capt.items():
|
|
296
|
+
modulename = f"{basemodulename}_{specification}"
|
|
297
|
+
if modulename in modules:
|
|
298
|
+
module = modules[modulename]
|
|
299
|
+
found_module = True
|
|
300
|
+
new_lines += _add_title(caption, ".")
|
|
301
|
+
new_lines += _add_lines(specification, module)
|
|
302
|
+
substituter.add_module(module)
|
|
303
|
+
_gain_and_insert_additional_information_into_docstrings(module, methods)
|
|
304
|
+
if found_module:
|
|
305
|
+
lines += new_lines
|
|
306
|
+
moduledoc += "\n".join(lines)
|
|
307
|
+
namespace["__doc__"] = moduledoc
|
|
308
|
+
basemodule = importlib.import_module(namespace["__name__"])
|
|
309
|
+
substituter.add_module(basemodule)
|
|
310
|
+
insert_docname_substitutions(
|
|
311
|
+
module=modules[f"{basemodulename}_model"],
|
|
312
|
+
name=basemodulename,
|
|
313
|
+
substituter=substituter,
|
|
314
|
+
)
|
|
315
|
+
substituter.update_masters()
|
|
316
|
+
namespace["substituter"] = substituter
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _insert_links_into_docstring(target: object, insertion: str) -> None:
|
|
320
|
+
try:
|
|
321
|
+
target.__doc__ += "" # type: ignore[operator]
|
|
322
|
+
except BaseException:
|
|
323
|
+
return
|
|
324
|
+
doc = getattr(target, "__doc__", None)
|
|
325
|
+
if doc is not None:
|
|
326
|
+
position = target.__doc__.find("\n\n")
|
|
327
|
+
if position == -1:
|
|
328
|
+
target.__doc__ = "\n\n".join([doc, insertion])
|
|
329
|
+
else:
|
|
330
|
+
position += 2
|
|
331
|
+
target.__doc__ = "".join([doc[:position], insertion, doc[position:]])
|
|
332
|
+
return
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _extend_methoddocstrings(module: types.ModuleType) -> None:
|
|
336
|
+
model = module.Model
|
|
337
|
+
assert issubclass(model, modeltools.Model)
|
|
338
|
+
for method in model.get_methods():
|
|
339
|
+
_insert_links_into_docstring(
|
|
340
|
+
method, "\n".join(_get_methoddocstringinsertions(method))
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _get_ending(container: Sized) -> str:
|
|
345
|
+
return "s" if len(container) > 1 else ""
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _get_methoddocstringinsertions(method: modeltools.Method) -> list[str]:
|
|
349
|
+
insertions = []
|
|
350
|
+
submethods = getattr(method, "SUBMETHODS", ())
|
|
351
|
+
if submethods:
|
|
352
|
+
insertions.append(f" Required submethod{_get_ending(submethods)}:")
|
|
353
|
+
for submethod in submethods:
|
|
354
|
+
insertions.append(
|
|
355
|
+
f" :class:`~{submethod.__module__}." f"{submethod.__name__}`"
|
|
356
|
+
)
|
|
357
|
+
insertions.append("")
|
|
358
|
+
for pargroup in ("control", "derived", "fixed", "solver"):
|
|
359
|
+
pars = getattr(method, f"{pargroup.upper()}PARAMETERS", ())
|
|
360
|
+
if pars:
|
|
361
|
+
insertions.append(
|
|
362
|
+
f" Requires the {pargroup} parameter{_get_ending(pars)}:"
|
|
363
|
+
)
|
|
364
|
+
for par in pars:
|
|
365
|
+
insertions.append(f" :class:`~{par.__module__}.{par.__name__}`")
|
|
366
|
+
insertions.append("")
|
|
367
|
+
for statement, tuplename in (
|
|
368
|
+
("Requires the", "REQUIREDSEQUENCES"),
|
|
369
|
+
("Updates the", "UPDATEDSEQUENCES"),
|
|
370
|
+
("Calculates the", "RESULTSEQUENCES"),
|
|
371
|
+
):
|
|
372
|
+
for seqtype in (
|
|
373
|
+
sequencetools.InletSequence,
|
|
374
|
+
sequencetools.ReceiverSequence,
|
|
375
|
+
sequencetools.InputSequence,
|
|
376
|
+
sequencetools.FactorSequence,
|
|
377
|
+
sequencetools.FluxSequence,
|
|
378
|
+
sequencetools.StateSequence,
|
|
379
|
+
sequencetools.LogSequence,
|
|
380
|
+
sequencetools.AideSequence,
|
|
381
|
+
sequencetools.OutletSequence,
|
|
382
|
+
sequencetools.SenderSequence,
|
|
383
|
+
):
|
|
384
|
+
seqs = [
|
|
385
|
+
seq
|
|
386
|
+
for seq in getattr(method, tuplename, ())
|
|
387
|
+
if issubclass(seq, seqtype)
|
|
388
|
+
]
|
|
389
|
+
if seqs:
|
|
390
|
+
insertions.append(
|
|
391
|
+
f" {statement} "
|
|
392
|
+
f"{seqtype.__name__[:-8].lower()} "
|
|
393
|
+
f"sequence{_get_ending(seqs)}:"
|
|
394
|
+
)
|
|
395
|
+
for seq in seqs:
|
|
396
|
+
insertions.append(
|
|
397
|
+
f" :class:`~{seq.__module__}.{seq.__name__}`"
|
|
398
|
+
)
|
|
399
|
+
insertions.append("")
|
|
400
|
+
if insertions:
|
|
401
|
+
insertions.append("")
|
|
402
|
+
return insertions
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def _gain_and_insert_additional_information_into_docstrings(
|
|
406
|
+
module: types.ModuleType, allmethods: tuple[type[modeltools.Method], ...]
|
|
407
|
+
) -> None:
|
|
408
|
+
for value in vars(module).values():
|
|
409
|
+
insertions = []
|
|
410
|
+
for role, description in (
|
|
411
|
+
("SUBMETHODS", "Required"),
|
|
412
|
+
("CONTROLPARAMETERS", "Required"),
|
|
413
|
+
("DERIVEDPARAMETERS", "Required"),
|
|
414
|
+
("FIXEDPARAMETERS", "Required"),
|
|
415
|
+
("SOLVERPARAMETERS", "Required"),
|
|
416
|
+
("RESULTSEQUENCES", "Calculated"),
|
|
417
|
+
("UPDATEDSEQUENCES", "Updated"),
|
|
418
|
+
("REQUIREDSEQUENCES", "Required"),
|
|
419
|
+
):
|
|
420
|
+
relevantmethods = set()
|
|
421
|
+
for method in allmethods:
|
|
422
|
+
if value in getattr(method, role, ()):
|
|
423
|
+
relevantmethods.add(method)
|
|
424
|
+
if relevantmethods:
|
|
425
|
+
subinsertions = []
|
|
426
|
+
for method in relevantmethods:
|
|
427
|
+
subinsertions.append(
|
|
428
|
+
f" :class:`~{method.__module__}." f"{method.__name__}`"
|
|
429
|
+
)
|
|
430
|
+
insertions.append(
|
|
431
|
+
f" {description} by the " f"method{_get_ending(subinsertions)}:"
|
|
432
|
+
)
|
|
433
|
+
insertions.extend(sorted(subinsertions))
|
|
434
|
+
insertions.append("\n")
|
|
435
|
+
|
|
436
|
+
_insert_links_into_docstring(value, "\n".join(insertions))
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def autodoc_applicationmodel(module: types.ModuleType) -> None:
|
|
440
|
+
"""Improves the docstrings of application models.
|
|
441
|
+
|
|
442
|
+
|autodoc_applicationmodel| requires, similar to |autodoc_basemodel|, that both the
|
|
443
|
+
application model and its base model are defined in the conventional way.
|
|
444
|
+
"""
|
|
445
|
+
autodoc_tuple2doc(module)
|
|
446
|
+
path_applicationmodel = module.__name__
|
|
447
|
+
path_basemodel = path_applicationmodel.split("_")[0]
|
|
448
|
+
module_basemodel = importlib.import_module(path_basemodel)
|
|
449
|
+
substituter = Substituter(module_basemodel.substituter)
|
|
450
|
+
substituter.add_module(module)
|
|
451
|
+
insert_docname_substitutions(
|
|
452
|
+
module=module,
|
|
453
|
+
name=path_applicationmodel.split(".")[-1],
|
|
454
|
+
substituter=substituter,
|
|
455
|
+
)
|
|
456
|
+
substituter.update_masters()
|
|
457
|
+
module.substituter = substituter # type: ignore[attr-defined]
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def insert_docname_substitutions(
|
|
461
|
+
module: types.ModuleType, name: str, substituter: Substituter
|
|
462
|
+
) -> None:
|
|
463
|
+
r"""Insert model-specific substitutions based on the definitions provided by the
|
|
464
|
+
available |DocName| member.
|
|
465
|
+
|
|
466
|
+
>>> from hydpy.core.autodoctools import insert_docname_substitutions, Substituter
|
|
467
|
+
>>> from hydpy.models import wland_wag
|
|
468
|
+
>>> substituter = Substituter()
|
|
469
|
+
>>> insert_docname_substitutions(wland_wag, "wland_wag", substituter)
|
|
470
|
+
>>> for command in substituter.get_commands().split("\n"):
|
|
471
|
+
... print(command) # doctest: +ELLIPSIS
|
|
472
|
+
.. |wland_wag.DOCNAME.complete| replace:: HydPy-W-Wag (extended version ...
|
|
473
|
+
.. |wland_wag.DOCNAME.description| replace:: extended version ...
|
|
474
|
+
.. |wland_wag.DOCNAME.family| replace:: HydPy-W
|
|
475
|
+
.. |wland_wag.DOCNAME.long| replace:: HydPy-W-Wag
|
|
476
|
+
.. |wland_wag.DOCNAME.short| replace:: W-Wag
|
|
477
|
+
.. |wland_wag.Model.DOCNAME.complete| replace:: HydPy-W-Wag (extended version ...
|
|
478
|
+
.. |wland_wag.Model.DOCNAME.description| replace:: extended version ...
|
|
479
|
+
.. |wland_wag.Model.DOCNAME.family| replace:: HydPy-W
|
|
480
|
+
.. |wland_wag.Model.DOCNAME.long| replace:: HydPy-W-Wag
|
|
481
|
+
.. |wland_wag.Model.DOCNAME.short| replace:: W-Wag
|
|
482
|
+
|
|
483
|
+
>>> from hydpy.models.wland import wland_model
|
|
484
|
+
>>> substituter = Substituter()
|
|
485
|
+
>>> insert_docname_substitutions(wland_model, "wland", substituter)
|
|
486
|
+
>>> for command in substituter.get_commands().split("\n"):
|
|
487
|
+
... print(command) # doctest: +ELLIPSIS
|
|
488
|
+
.. |wland.DOCNAME.complete| replace:: HydPy-W (base model)
|
|
489
|
+
.. |wland.DOCNAME.description| replace:: base model
|
|
490
|
+
.. |wland.DOCNAME.family| replace:: HydPy-W
|
|
491
|
+
.. |wland.DOCNAME.long| replace:: HydPy-W
|
|
492
|
+
.. |wland.DOCNAME.short| replace:: W
|
|
493
|
+
.. |wland.Model.DOCNAME.complete| replace:: HydPy-W (base model)
|
|
494
|
+
.. |wland.Model.DOCNAME.description| replace:: base model
|
|
495
|
+
.. |wland.Model.DOCNAME.family| replace:: HydPy-W
|
|
496
|
+
.. |wland.Model.DOCNAME.long| replace:: HydPy-W
|
|
497
|
+
.. |wland.Model.DOCNAME.short| replace:: W
|
|
498
|
+
"""
|
|
499
|
+
docname = module.Model.DOCNAME
|
|
500
|
+
for member in dir(docname):
|
|
501
|
+
if not (member.startswith("_") or hasattr(tuple, member)):
|
|
502
|
+
substituter.add_substitution(
|
|
503
|
+
short=f"|{name}.DOCNAME.{member}|",
|
|
504
|
+
medium=f"|{name}.Model.DOCNAME.{member}|",
|
|
505
|
+
long=getattr(docname, member),
|
|
506
|
+
module=module,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
class Substituter:
|
|
511
|
+
"""Implements a HydPy specific docstring substitution mechanism."""
|
|
512
|
+
|
|
513
|
+
master: Substituter | None
|
|
514
|
+
slaves: list[Substituter]
|
|
515
|
+
short2long: dict[str, str]
|
|
516
|
+
short2priority: dict[str, Priority]
|
|
517
|
+
medium2long: dict[str, str]
|
|
518
|
+
|
|
519
|
+
def __init__(self, master: Substituter | None = None) -> None:
|
|
520
|
+
self.master = master
|
|
521
|
+
self.slaves = []
|
|
522
|
+
if master:
|
|
523
|
+
master.slaves.append(self)
|
|
524
|
+
self.short2long = copy.deepcopy(master.short2long)
|
|
525
|
+
self.short2priority = copy.deepcopy(master.short2priority)
|
|
526
|
+
self.medium2long = copy.deepcopy(master.medium2long)
|
|
527
|
+
else:
|
|
528
|
+
self.short2long = {}
|
|
529
|
+
self.short2priority = {}
|
|
530
|
+
self.medium2long = {}
|
|
531
|
+
|
|
532
|
+
@staticmethod
|
|
533
|
+
def consider_member(
|
|
534
|
+
name_member: str,
|
|
535
|
+
member: Any,
|
|
536
|
+
module: types.ModuleType,
|
|
537
|
+
class_: type[object] | None = None,
|
|
538
|
+
ignore: dict[str, object] | None = None,
|
|
539
|
+
) -> bool:
|
|
540
|
+
"""Return |True| if the given member should be added to the substitutions. If
|
|
541
|
+
not, return |False|.
|
|
542
|
+
|
|
543
|
+
Some examples based on the site-package |numpy|:
|
|
544
|
+
|
|
545
|
+
>>> from hydpy.core.autodoctools import Substituter
|
|
546
|
+
>>> import numpy
|
|
547
|
+
|
|
548
|
+
A constant like |numpy.nan| should be added:
|
|
549
|
+
|
|
550
|
+
>>> Substituter.consider_member("nan", numpy.nan, numpy)
|
|
551
|
+
True
|
|
552
|
+
|
|
553
|
+
Members with a prefixed underscore should not be added:
|
|
554
|
+
|
|
555
|
+
>>> Substituter.consider_member("_NoValue", numpy._NoValue, numpy)
|
|
556
|
+
False
|
|
557
|
+
|
|
558
|
+
Members that are actually imported modules should not be added:
|
|
559
|
+
|
|
560
|
+
>>> Substituter.consider_member("random", numpy.random, numpy)
|
|
561
|
+
False
|
|
562
|
+
|
|
563
|
+
Members that are actually defined in other modules should not be added:
|
|
564
|
+
|
|
565
|
+
>>> numpy.Substituter = Substituter
|
|
566
|
+
>>> Substituter.consider_member("Substituter", numpy.Substituter, numpy)
|
|
567
|
+
False
|
|
568
|
+
>>> del numpy.Substituter
|
|
569
|
+
|
|
570
|
+
Members that are defined in submodules of a given package (either from the
|
|
571
|
+
standard library or from site-packages) should be added...
|
|
572
|
+
|
|
573
|
+
>>> Substituter.consider_member("clip", numpy.clip, numpy)
|
|
574
|
+
True
|
|
575
|
+
|
|
576
|
+
...but not members defined in *HydPy* submodules:
|
|
577
|
+
|
|
578
|
+
>>> import hydpy
|
|
579
|
+
>>> Substituter.consider_member("Node", hydpy.Node, hydpy)
|
|
580
|
+
False
|
|
581
|
+
|
|
582
|
+
Module |typingtools| is unique, as it is the only one for which
|
|
583
|
+
|Substituter.consider_member| returns |True| all explicitly exported type
|
|
584
|
+
aliases:
|
|
585
|
+
|
|
586
|
+
>>> from hydpy.core import sequencetools, typingtools
|
|
587
|
+
>>> Substituter.consider_member(
|
|
588
|
+
... "NDArrayFloat", typingtools.NDArrayFloat, typingtools)
|
|
589
|
+
True
|
|
590
|
+
|
|
591
|
+
>>> Substituter.consider_member(
|
|
592
|
+
... "NDArrayFloat", typingtools.NDArrayFloat, sequencetools)
|
|
593
|
+
False
|
|
594
|
+
|
|
595
|
+
For descriptor instances (with method `__get__`) being members of classes
|
|
596
|
+
should be added:
|
|
597
|
+
|
|
598
|
+
>>> from hydpy.auxs import anntools
|
|
599
|
+
>>> Substituter.consider_member(
|
|
600
|
+
... "shape_neurons", anntools.ANN.shape_neurons, anntools, anntools.ANN)
|
|
601
|
+
True
|
|
602
|
+
|
|
603
|
+
You can decide to ignore certain members:
|
|
604
|
+
|
|
605
|
+
>>> Substituter.consider_member(
|
|
606
|
+
... "shape_neurons", anntools.ANN.shape_neurons, anntools, anntools.ANN,
|
|
607
|
+
... {"test": 1.0})
|
|
608
|
+
True
|
|
609
|
+
>>> Substituter.consider_member(
|
|
610
|
+
... "shape_neurons", anntools.ANN.shape_neurons, anntools, anntools.ANN,
|
|
611
|
+
... {"shape_neurons": anntools.ANN.shape_neurons})
|
|
612
|
+
False
|
|
613
|
+
"""
|
|
614
|
+
if ignore and (name_member in ignore):
|
|
615
|
+
return False
|
|
616
|
+
if name_member.startswith("_"):
|
|
617
|
+
return False
|
|
618
|
+
if inspect.ismodule(member):
|
|
619
|
+
return False
|
|
620
|
+
real_module = getattr(member, "__module__", None)
|
|
621
|
+
if (module is not typing) and (name_member in typing.__all__):
|
|
622
|
+
return False
|
|
623
|
+
if (module is typingtools) and (name_member in typingtools.__all__):
|
|
624
|
+
return True
|
|
625
|
+
if not real_module:
|
|
626
|
+
return True
|
|
627
|
+
if real_module != module.__name__:
|
|
628
|
+
if class_ and hasattr(member, "__get__"):
|
|
629
|
+
return True
|
|
630
|
+
if "hydpy" in real_module:
|
|
631
|
+
return False
|
|
632
|
+
if module.__name__ not in real_module:
|
|
633
|
+
return False
|
|
634
|
+
return True
|
|
635
|
+
|
|
636
|
+
@staticmethod
|
|
637
|
+
def get_role(member: object, cython: bool = False) -> str:
|
|
638
|
+
"""Return the reStructuredText role `func`, `class`, or `const` best describing
|
|
639
|
+
the given member.
|
|
640
|
+
|
|
641
|
+
Some examples based on the site-package |numpy|. |numpy.clip| is a function:
|
|
642
|
+
|
|
643
|
+
>>> from hydpy.core.autodoctools import Substituter
|
|
644
|
+
>>> import numpy
|
|
645
|
+
>>> Substituter.get_role(numpy.clip)
|
|
646
|
+
'func'
|
|
647
|
+
|
|
648
|
+
|numpy.ndarray| is a class:
|
|
649
|
+
|
|
650
|
+
>>> Substituter.get_role(numpy.ndarray)
|
|
651
|
+
'class'
|
|
652
|
+
|
|
653
|
+
|numpy.ndarray.clip| is a method, for which also the `function` role is
|
|
654
|
+
returned:
|
|
655
|
+
|
|
656
|
+
>>> Substituter.get_role(numpy.ndarray.clip)
|
|
657
|
+
'func'
|
|
658
|
+
|
|
659
|
+
For everything else the `constant` role is returned:
|
|
660
|
+
|
|
661
|
+
>>> Substituter.get_role(numpy.nan)
|
|
662
|
+
'const'
|
|
663
|
+
|
|
664
|
+
When analysing cython extension modules, set the option `cython` flag to |True|.
|
|
665
|
+
|Double| is correctly identified as a class:
|
|
666
|
+
|
|
667
|
+
>>> from hydpy.cythons import pointerutils
|
|
668
|
+
>>> Substituter.get_role(pointerutils.Double, cython=True)
|
|
669
|
+
'class'
|
|
670
|
+
|
|
671
|
+
Only with the `cython` flag beeing |True|, for everything else the `function`
|
|
672
|
+
text role is returned (doesn't make sense here, but the |numpy| module is not
|
|
673
|
+
something defined in module |pointerutils| anyway):
|
|
674
|
+
|
|
675
|
+
>>> Substituter.get_role(pointerutils.numpy, cython=True)
|
|
676
|
+
'func'
|
|
677
|
+
"""
|
|
678
|
+
if inspect.isroutine(member) or isinstance(member, numpy.ufunc):
|
|
679
|
+
return "func"
|
|
680
|
+
if inspect.isclass(member):
|
|
681
|
+
return "class"
|
|
682
|
+
if cython:
|
|
683
|
+
return "func"
|
|
684
|
+
return "const"
|
|
685
|
+
|
|
686
|
+
def add_substitution(
|
|
687
|
+
self, short: str, medium: str, long: str, module: types.ModuleType
|
|
688
|
+
) -> None:
|
|
689
|
+
"""Add the given substitutions both as a `short2long` and a `medium2long`
|
|
690
|
+
mapping.
|
|
691
|
+
|
|
692
|
+
Assume `variable1`, `variable2`, and `variable3` are defined in the *HydPy*
|
|
693
|
+
module `module1` of subpackage `exe` and the short and medium descriptions are
|
|
694
|
+
`var1` and `mod1.var1` and so on:
|
|
695
|
+
|
|
696
|
+
>>> import types
|
|
697
|
+
>>> module1 = types.ModuleType("hydpy.exe.module1")
|
|
698
|
+
>>> from hydpy.core.autodoctools import Substituter
|
|
699
|
+
>>> substituter = Substituter()
|
|
700
|
+
>>> substituter.add_substitution(
|
|
701
|
+
... "var1", "mod1.var1", "hydpy.exe.module1.variable1", module1)
|
|
702
|
+
>>> substituter.add_substitution(
|
|
703
|
+
... "var2", "mod1.var2", "hydpy.exe.module1.variable2", module1)
|
|
704
|
+
>>> substituter.add_substitution(
|
|
705
|
+
... "var3", "mod1.var3", "hydpy.exe.module1.variable3", module1)
|
|
706
|
+
>>> print(substituter.get_commands())
|
|
707
|
+
.. var1 replace:: hydpy.exe.module1.variable1
|
|
708
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
709
|
+
.. var3 replace:: hydpy.exe.module1.variable3
|
|
710
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
711
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
712
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
713
|
+
|
|
714
|
+
If we add an object with the same, the updating of |Substituter.short2long|
|
|
715
|
+
depends on its priority. Builtins have the highest priority. Objects defined
|
|
716
|
+
in the `core`, `exe`, `auxs`, `cythons`, and `models` subpackages have the
|
|
717
|
+
priorities two to six. All other objects (incuding those of other
|
|
718
|
+
site-packages) have the lowest priority. If we add `variable1`, said to be
|
|
719
|
+
defined in the `core` subpackage (higher priority than the `exe` subpackage),
|
|
720
|
+
the new short substitution replaces the old one:
|
|
721
|
+
|
|
722
|
+
>>> module2 = types.ModuleType("hydpy.core.module2")
|
|
723
|
+
>>> substituter.add_substitution(
|
|
724
|
+
... "var1", "mod2.var1", "hydpy.core.module2.variable1", module2)
|
|
725
|
+
>>> print(substituter.get_commands())
|
|
726
|
+
.. var1 replace:: hydpy.core.module2.variable1
|
|
727
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
728
|
+
.. var3 replace:: hydpy.exe.module1.variable3
|
|
729
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
730
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
731
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
732
|
+
.. mod2.var1 replace:: hydpy.core.module2.variable1
|
|
733
|
+
|
|
734
|
+
If we add `variable2`, said to be defined in the `auxs` subpackage (lower
|
|
735
|
+
priority than the `exe` subpackage), the old short substitution does not change:
|
|
736
|
+
|
|
737
|
+
>>> module3 = types.ModuleType("hydpy.auxs.module3")
|
|
738
|
+
>>> substituter.add_substitution(
|
|
739
|
+
... "var2", "mod3.var2", "hydpy.auxs.module3.variable2", module3)
|
|
740
|
+
>>> print(substituter.get_commands())
|
|
741
|
+
.. var1 replace:: hydpy.core.module2.variable1
|
|
742
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
743
|
+
.. var3 replace:: hydpy.exe.module1.variable3
|
|
744
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
745
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
746
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
747
|
+
.. mod2.var1 replace:: hydpy.core.module2.variable1
|
|
748
|
+
.. mod3.var2 replace:: hydpy.auxs.module3.variable2
|
|
749
|
+
|
|
750
|
+
If we add `variable3`, said to be also defined in the `exe` subpackage, the
|
|
751
|
+
short substitution is removed to avoid ambiguity:
|
|
752
|
+
|
|
753
|
+
>>> module4 = types.ModuleType("hydpy.exe.module4")
|
|
754
|
+
>>> substituter.add_substitution(
|
|
755
|
+
... "var3", "mod4.var3", "hydpy.exe.module4.variable3", module4)
|
|
756
|
+
>>> print(substituter.get_commands())
|
|
757
|
+
.. var1 replace:: hydpy.core.module2.variable1
|
|
758
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
759
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
760
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
761
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
762
|
+
.. mod2.var1 replace:: hydpy.core.module2.variable1
|
|
763
|
+
.. mod3.var2 replace:: hydpy.auxs.module3.variable2
|
|
764
|
+
.. mod4.var3 replace:: hydpy.exe.module4.variable3
|
|
765
|
+
|
|
766
|
+
Adding `variable3` of `module1` accidentally again does not result in any
|
|
767
|
+
undesired side-effects:
|
|
768
|
+
|
|
769
|
+
>>> substituter.add_substitution(
|
|
770
|
+
... "var3", "mod1.var3", "hydpy.exe.module1.variable3", module1)
|
|
771
|
+
>>> print(substituter.get_commands())
|
|
772
|
+
.. var1 replace:: hydpy.core.module2.variable1
|
|
773
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
774
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
775
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
776
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
777
|
+
.. mod2.var1 replace:: hydpy.core.module2.variable1
|
|
778
|
+
.. mod3.var2 replace:: hydpy.auxs.module3.variable2
|
|
779
|
+
.. mod4.var3 replace:: hydpy.exe.module4.variable3
|
|
780
|
+
|
|
781
|
+
In order to reduce the risk of name conflicts, only the `medium2long` mapping
|
|
782
|
+
is supported for modules not part of the *HydPy* package:
|
|
783
|
+
|
|
784
|
+
>>> module5 = types.ModuleType("external")
|
|
785
|
+
>>> substituter.add_substitution(
|
|
786
|
+
... "var4", "mod5.var4", "external.variable4", module5)
|
|
787
|
+
>>> print(substituter.get_commands())
|
|
788
|
+
.. var1 replace:: hydpy.core.module2.variable1
|
|
789
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
790
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
791
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
792
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
793
|
+
.. mod2.var1 replace:: hydpy.core.module2.variable1
|
|
794
|
+
.. mod3.var2 replace:: hydpy.auxs.module3.variable2
|
|
795
|
+
.. mod4.var3 replace:: hydpy.exe.module4.variable3
|
|
796
|
+
.. mod5.var4 replace:: external.variable4
|
|
797
|
+
|
|
798
|
+
The only exception to this rule is |builtins|, for which only the
|
|
799
|
+
|Substituter.short2long| mapping is supported (note also, that the module name
|
|
800
|
+
`builtins` is removed from string `long`):
|
|
801
|
+
|
|
802
|
+
>>> import builtins
|
|
803
|
+
>>> substituter.add_substitution(
|
|
804
|
+
... "str", "blt.str", ":func:`~builtins.str`", builtins)
|
|
805
|
+
>>> print(substituter.get_commands())
|
|
806
|
+
.. str replace:: :func:`str`
|
|
807
|
+
.. var1 replace:: hydpy.core.module2.variable1
|
|
808
|
+
.. var2 replace:: hydpy.exe.module1.variable2
|
|
809
|
+
.. mod1.var1 replace:: hydpy.exe.module1.variable1
|
|
810
|
+
.. mod1.var2 replace:: hydpy.exe.module1.variable2
|
|
811
|
+
.. mod1.var3 replace:: hydpy.exe.module1.variable3
|
|
812
|
+
.. mod2.var1 replace:: hydpy.core.module2.variable1
|
|
813
|
+
.. mod3.var2 replace:: hydpy.auxs.module3.variable2
|
|
814
|
+
.. mod4.var3 replace:: hydpy.exe.module4.variable3
|
|
815
|
+
.. mod5.var4 replace:: external.variable4
|
|
816
|
+
"""
|
|
817
|
+
name = module.__name__
|
|
818
|
+
priority = Priority.get_priority(name)
|
|
819
|
+
if priority == BUILTINS:
|
|
820
|
+
self.short2long[short] = long.split("~")[0] + long.split(".")[-1]
|
|
821
|
+
self.short2priority[short] = priority
|
|
822
|
+
else:
|
|
823
|
+
self.medium2long[medium] = long
|
|
824
|
+
if priority != ELSE:
|
|
825
|
+
if priority.value < self.short2priority.get(short, ELSE).value:
|
|
826
|
+
self.short2long[short] = long
|
|
827
|
+
self.short2priority[short] = priority
|
|
828
|
+
elif priority == self.short2priority[short]:
|
|
829
|
+
self.short2long.pop(short, None)
|
|
830
|
+
|
|
831
|
+
def add_module(self, module: types.ModuleType, cython: bool = False) -> None:
|
|
832
|
+
"""Add the given module, its members, and their submembers.
|
|
833
|
+
|
|
834
|
+
The first examples are based on the site-package |numpy|: which is passed to
|
|
835
|
+
method |Substituter.add_module|:
|
|
836
|
+
|
|
837
|
+
>>> from hydpy.core.autodoctools import Substituter
|
|
838
|
+
>>> substituter = Substituter()
|
|
839
|
+
>>> import numpy
|
|
840
|
+
>>> substituter.add_module(numpy)
|
|
841
|
+
|
|
842
|
+
First, the module itself is added:
|
|
843
|
+
|
|
844
|
+
>>> substituter.find("|numpy|")
|
|
845
|
+
|numpy| :mod:`~numpy`
|
|
846
|
+
|
|
847
|
+
Second, constants like |numpy.nan| are added:
|
|
848
|
+
|
|
849
|
+
>>> substituter.find("|numpy.nan|")
|
|
850
|
+
|numpy.nan| :const:`~numpy.nan`
|
|
851
|
+
|
|
852
|
+
Third, functions like |numpy.clip| are added:
|
|
853
|
+
|
|
854
|
+
>>> substituter.find("|numpy.clip|")
|
|
855
|
+
|numpy.clip| :func:`~numpy.clip`
|
|
856
|
+
|
|
857
|
+
Fourth, clases line |numpy.ndarray| are added:
|
|
858
|
+
|
|
859
|
+
>>> substituter.find("|numpy.ndarray|")
|
|
860
|
+
|numpy.ndarray| :class:`~numpy.ndarray`
|
|
861
|
+
|
|
862
|
+
Method |Substituter.add_module| also searches for available annotations:
|
|
863
|
+
|
|
864
|
+
>>> from hydpy.core import timetools
|
|
865
|
+
>>> substituter.add_module(timetools)
|
|
866
|
+
>>> substituter.find("Timegrids.init")
|
|
867
|
+
|Timegrids.initindices| :const:`~hydpy.core.timetools.Timegrids.initindices`
|
|
868
|
+
|Timegrids.init| :attr:`~hydpy.core.timetools.Timegrids.init`
|
|
869
|
+
|timetools.Timegrids.initindices| \
|
|
870
|
+
:const:`~hydpy.core.timetools.Timegrids.initindices`
|
|
871
|
+
|timetools.Timegrids.init| :attr:`~hydpy.core.timetools.Timegrids.init`
|
|
872
|
+
|
|
873
|
+
>>> from hydpy.auxs import calibtools
|
|
874
|
+
>>> substituter.add_module(calibtools)
|
|
875
|
+
>>> substituter.find("RuleIUH.update_parameters")
|
|
876
|
+
|RuleIUH.update_parameters| \
|
|
877
|
+
:attr:`~hydpy.auxs.calibtools.RuleIUH.update_parameters`
|
|
878
|
+
|calibtools.RuleIUH.update_parameters| \
|
|
879
|
+
:attr:`~hydpy.auxs.calibtools.RuleIUH.update_parameters`
|
|
880
|
+
|
|
881
|
+
Module |typingtools| is unique, as it is the only one for which
|
|
882
|
+
|Substituter.add_module| considers all explicitly exported type aliases:
|
|
883
|
+
|
|
884
|
+
>>> from hydpy.core import typingtools
|
|
885
|
+
>>> substituter.add_module(typingtools)
|
|
886
|
+
>>> substituter.find("|NDArrayFloat|") # doctest: +ELLIPSIS
|
|
887
|
+
|NDArrayFloat| :...:`~hydpy.core.typingtools.NDArrayFloat`
|
|
888
|
+
|
|
889
|
+
When adding Cython modules, the `cython` flag should be set |True|:
|
|
890
|
+
|
|
891
|
+
>>> from hydpy.cythons import pointerutils
|
|
892
|
+
>>> substituter.add_module(pointerutils, cython=True)
|
|
893
|
+
>>> substituter.find("set_pointer")
|
|
894
|
+
|PPDouble.set_pointer| \
|
|
895
|
+
:func:`~hydpy.cythons.autogen.pointerutils.PPDouble.set_pointer`
|
|
896
|
+
|pointerutils.PPDouble.set_pointer| \
|
|
897
|
+
:func:`~hydpy.cythons.autogen.pointerutils.PPDouble.set_pointer`
|
|
898
|
+
"""
|
|
899
|
+
name_module = module.__name__.split(".")[-1]
|
|
900
|
+
short = f"|{name_module}|"
|
|
901
|
+
long = f":mod:`~{module.__name__}`"
|
|
902
|
+
self.short2long[short] = long
|
|
903
|
+
for name_member, member in vars(module).items():
|
|
904
|
+
if self.consider_member(name_member, member, module):
|
|
905
|
+
role = self.get_role(member, cython)
|
|
906
|
+
short = f"|{name_member}|"
|
|
907
|
+
medium = f"|{name_module}.{name_member}|"
|
|
908
|
+
long = f":{role}:`~{module.__name__}.{name_member}`"
|
|
909
|
+
self.add_substitution(short, medium, long, module)
|
|
910
|
+
if inspect.isclass(member):
|
|
911
|
+
annotations = getattr(member, "__annotations__", {})
|
|
912
|
+
for name_submember, submember in vars(member).items():
|
|
913
|
+
if self.consider_member(
|
|
914
|
+
name_member=name_submember,
|
|
915
|
+
member=submember,
|
|
916
|
+
module=module,
|
|
917
|
+
class_=member,
|
|
918
|
+
ignore=annotations,
|
|
919
|
+
):
|
|
920
|
+
role = self.get_role(submember, cython)
|
|
921
|
+
short = f"|{name_member}.{name_submember}|"
|
|
922
|
+
medium = (
|
|
923
|
+
f"|{name_module}.{name_member}." f"{name_submember}|"
|
|
924
|
+
)
|
|
925
|
+
long = (
|
|
926
|
+
f":{role}:`~{module.__name__}."
|
|
927
|
+
f"{name_member}.{name_submember}`"
|
|
928
|
+
)
|
|
929
|
+
self.add_substitution(short, medium, long, module)
|
|
930
|
+
for name_submember, submember in annotations.items():
|
|
931
|
+
short = f"|{name_member}.{name_submember}|"
|
|
932
|
+
medium = f"|{name_module}.{name_member}." f"{name_submember}|"
|
|
933
|
+
long = (
|
|
934
|
+
f":attr:`~{module.__name__}."
|
|
935
|
+
f"{name_member}.{name_submember}`"
|
|
936
|
+
)
|
|
937
|
+
self.add_substitution(short, medium, long, module)
|
|
938
|
+
|
|
939
|
+
def add_modules(self, package: types.ModuleType) -> None:
|
|
940
|
+
"""Add the modules of the given package without their members."""
|
|
941
|
+
for name in sorted(os.listdir(package.__path__[0])):
|
|
942
|
+
if name.startswith("_"):
|
|
943
|
+
continue
|
|
944
|
+
name = name.split(".")[0]
|
|
945
|
+
short = f"|{name}|"
|
|
946
|
+
long = f":mod:`~{package.__package__}.{name}`"
|
|
947
|
+
self.short2long[short] = long
|
|
948
|
+
|
|
949
|
+
def update_masters(self) -> None:
|
|
950
|
+
"""Update all `master` |Substituter| objects.
|
|
951
|
+
|
|
952
|
+
If a |Substituter| object is passed to the constructor of another |Substituter|
|
|
953
|
+
object, they become `master` and `slave`:
|
|
954
|
+
|
|
955
|
+
>>> from hydpy.core.autodoctools import Substituter
|
|
956
|
+
>>> sub1 = Substituter()
|
|
957
|
+
>>> from hydpy.core import devicetools
|
|
958
|
+
>>> sub1.add_module(devicetools)
|
|
959
|
+
>>> sub2 = Substituter(sub1)
|
|
960
|
+
>>> sub3 = Substituter(sub2)
|
|
961
|
+
>>> sub3.master.master is sub1
|
|
962
|
+
True
|
|
963
|
+
>>> sub2 in sub1.slaves
|
|
964
|
+
True
|
|
965
|
+
|
|
966
|
+
During initialisation, all mappings handled by the master object are passed to
|
|
967
|
+
its new slave:
|
|
968
|
+
|
|
969
|
+
>>> sub3.find("Node|")
|
|
970
|
+
|Node| :class:`~hydpy.core.devicetools.Node`
|
|
971
|
+
|devicetools.Node| :class:`~hydpy.core.devicetools.Node`
|
|
972
|
+
|
|
973
|
+
Updating a slave, does not affect its master directly:
|
|
974
|
+
|
|
975
|
+
>>> from hydpy.core import hydpytools
|
|
976
|
+
>>> sub3.add_module(hydpytools)
|
|
977
|
+
>>> sub3.find("HydPy|")
|
|
978
|
+
|HydPy| :class:`~hydpy.core.hydpytools.HydPy`
|
|
979
|
+
|hydpytools.HydPy| :class:`~hydpy.core.hydpytools.HydPy`
|
|
980
|
+
>>> sub2.find("HydPy|")
|
|
981
|
+
|
|
982
|
+
Through calling |Substituter.update_masters|, the `medium2long` mappings are
|
|
983
|
+
passed from the slave to its master:
|
|
984
|
+
|
|
985
|
+
>>> sub3.update_masters()
|
|
986
|
+
>>> sub2.find("HydPy|")
|
|
987
|
+
|hydpytools.HydPy| :class:`~hydpy.core.hydpytools.HydPy`
|
|
988
|
+
|
|
989
|
+
Then each master object updates its own master object also:
|
|
990
|
+
|
|
991
|
+
>>> sub1.find("HydPy|")
|
|
992
|
+
|hydpytools.HydPy| :class:`~hydpy.core.hydpytools.HydPy`
|
|
993
|
+
|
|
994
|
+
In reverse, subsequent updates of master objects to not affect their slaves
|
|
995
|
+
directly:
|
|
996
|
+
|
|
997
|
+
>>> from hydpy.core import masktools
|
|
998
|
+
>>> sub1.add_module(masktools)
|
|
999
|
+
>>> sub1.find("Masks|")
|
|
1000
|
+
|Masks| :class:`~hydpy.core.masktools.Masks`
|
|
1001
|
+
|NodeMasks| :class:`~hydpy.core.masktools.NodeMasks`
|
|
1002
|
+
|masktools.Masks| :class:`~hydpy.core.masktools.Masks`
|
|
1003
|
+
|masktools.NodeMasks| :class:`~hydpy.core.masktools.NodeMasks`
|
|
1004
|
+
>>> sub2.find("Masks|")
|
|
1005
|
+
|
|
1006
|
+
Through calling |Substituter.update_slaves|, the `medium2long` mappings are
|
|
1007
|
+
passed the master to all of its slaves:
|
|
1008
|
+
|
|
1009
|
+
>>> sub1.update_slaves()
|
|
1010
|
+
>>> sub2.find("Masks|")
|
|
1011
|
+
|masktools.Masks| :class:`~hydpy.core.masktools.Masks`
|
|
1012
|
+
|masktools.NodeMasks| :class:`~hydpy.core.masktools.NodeMasks`
|
|
1013
|
+
>>> sub3.find("Masks|")
|
|
1014
|
+
|masktools.Masks| :class:`~hydpy.core.masktools.Masks`
|
|
1015
|
+
|masktools.NodeMasks| :class:`~hydpy.core.masktools.NodeMasks`
|
|
1016
|
+
"""
|
|
1017
|
+
if self.master is not None:
|
|
1018
|
+
self.master.medium2long.update(self.medium2long)
|
|
1019
|
+
self.master.update_masters()
|
|
1020
|
+
|
|
1021
|
+
def update_slaves(self) -> None:
|
|
1022
|
+
"""Update all `slave` |Substituter| objects.
|
|
1023
|
+
|
|
1024
|
+
See method |Substituter.update_masters| for further information.
|
|
1025
|
+
"""
|
|
1026
|
+
for slave in self.slaves:
|
|
1027
|
+
slave.medium2long.update(self.medium2long)
|
|
1028
|
+
slave.update_slaves()
|
|
1029
|
+
|
|
1030
|
+
def get_commands(self, source: str | None = None) -> str:
|
|
1031
|
+
"""Return a string containing multiple `reStructuredText` replacements with the
|
|
1032
|
+
substitutions currently defined.
|
|
1033
|
+
|
|
1034
|
+
Some examples based on the subpackage |optiontools|:
|
|
1035
|
+
|
|
1036
|
+
>>> from hydpy.core.autodoctools import Substituter
|
|
1037
|
+
>>> substituter = Substituter()
|
|
1038
|
+
>>> from hydpy.core import optiontools
|
|
1039
|
+
>>> substituter.add_module(optiontools)
|
|
1040
|
+
|
|
1041
|
+
When calling |Substituter.get_commands| with the `source` argument, the
|
|
1042
|
+
complete `short2long` and `medium2long` mappings are translated into
|
|
1043
|
+
replacement commands (only a few of them are shown):
|
|
1044
|
+
|
|
1045
|
+
>>> print(substituter.get_commands()) # doctest: +ELLIPSIS
|
|
1046
|
+
.. |OptionContextBase._new_value| replace:: \
|
|
1047
|
+
:attr:`~hydpy.core.optiontools.OptionContextBase._new_value`
|
|
1048
|
+
.. |OptionContextBase._old_value| replace:: \
|
|
1049
|
+
:attr:`~hydpy.core.optiontools.OptionContextBase._old_value`
|
|
1050
|
+
...
|
|
1051
|
+
.. |optiontools.TypeOption| replace:: \
|
|
1052
|
+
:const:`~hydpy.core.optiontools.TypeOption`
|
|
1053
|
+
.. |optiontools.l1| replace:: :const:`~hydpy.core.optiontools.l1`
|
|
1054
|
+
|
|
1055
|
+
Through passing a string (usually the source code of a file to be documented),
|
|
1056
|
+
only the replacement commands relevant for this string are translated:
|
|
1057
|
+
|
|
1058
|
+
>>> from hydpy.core import objecttools
|
|
1059
|
+
>>> import inspect
|
|
1060
|
+
>>> source = inspect.getsource(objecttools)
|
|
1061
|
+
>>> print(substituter.get_commands(source))
|
|
1062
|
+
.. |Options.ellipsis| replace:: \
|
|
1063
|
+
:const:`~hydpy.core.optiontools.Options.ellipsis`
|
|
1064
|
+
.. |Options.reprdigits| replace:: \
|
|
1065
|
+
:const:`~hydpy.core.optiontools.Options.reprdigits`
|
|
1066
|
+
"""
|
|
1067
|
+
commands = []
|
|
1068
|
+
for key, value in self:
|
|
1069
|
+
if (source is None) or (key in source):
|
|
1070
|
+
commands.append(f".. {key} replace:: {value}")
|
|
1071
|
+
return "\n".join(commands)
|
|
1072
|
+
|
|
1073
|
+
def find(self, text: str) -> None:
|
|
1074
|
+
"""Print all substitutions that include the given text string."""
|
|
1075
|
+
for key, value in self:
|
|
1076
|
+
if (text in key) or (text in value):
|
|
1077
|
+
print(key, value)
|
|
1078
|
+
|
|
1079
|
+
def __iter__(self) -> Iterator[tuple[str, str]]:
|
|
1080
|
+
yield from sorted(self.short2long.items())
|
|
1081
|
+
yield from sorted(self.medium2long.items())
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
def prepare_mainsubstituter() -> Substituter:
|
|
1085
|
+
"""Prepare and return a |Substituter| object for the main `__init__` file of
|
|
1086
|
+
*HydPy*."""
|
|
1087
|
+
# pylint: disable=import-outside-toplevel
|
|
1088
|
+
import matplotlib
|
|
1089
|
+
from matplotlib import figure
|
|
1090
|
+
from matplotlib import pyplot
|
|
1091
|
+
import pandas
|
|
1092
|
+
import scipy
|
|
1093
|
+
|
|
1094
|
+
substituter = Substituter()
|
|
1095
|
+
for module in (
|
|
1096
|
+
abc,
|
|
1097
|
+
builtins,
|
|
1098
|
+
numpy,
|
|
1099
|
+
datetime,
|
|
1100
|
+
unittest,
|
|
1101
|
+
doctest,
|
|
1102
|
+
inspect,
|
|
1103
|
+
io,
|
|
1104
|
+
os,
|
|
1105
|
+
sys,
|
|
1106
|
+
time,
|
|
1107
|
+
collections,
|
|
1108
|
+
itertools,
|
|
1109
|
+
subprocess,
|
|
1110
|
+
scipy,
|
|
1111
|
+
typing,
|
|
1112
|
+
platform,
|
|
1113
|
+
math,
|
|
1114
|
+
mimetypes,
|
|
1115
|
+
pandas,
|
|
1116
|
+
matplotlib,
|
|
1117
|
+
figure,
|
|
1118
|
+
pyplot,
|
|
1119
|
+
warnings,
|
|
1120
|
+
):
|
|
1121
|
+
substituter.add_module(module)
|
|
1122
|
+
for subpackage in (auxs, core, cythons, interfaces, exe):
|
|
1123
|
+
for _, name, _ in pkgutil.iter_modules(subpackage.__path__):
|
|
1124
|
+
full_name = subpackage.__name__ + "." + name
|
|
1125
|
+
substituter.add_module(importlib.import_module(full_name))
|
|
1126
|
+
substituter.add_modules(models)
|
|
1127
|
+
for cymodule in (
|
|
1128
|
+
annutils,
|
|
1129
|
+
interputils,
|
|
1130
|
+
ppolyutils,
|
|
1131
|
+
pointerutils,
|
|
1132
|
+
quadutils,
|
|
1133
|
+
rootutils,
|
|
1134
|
+
smoothutils,
|
|
1135
|
+
):
|
|
1136
|
+
substituter.add_module(cymodule, cython=True)
|
|
1137
|
+
substituter.short2long["|pub|"] = ":mod:`~hydpy.pub`"
|
|
1138
|
+
substituter.short2priority["|pub|"] = BUILTINS
|
|
1139
|
+
substituter.short2long["|config|"] = ":mod:`~hydpy.config`"
|
|
1140
|
+
substituter.short2priority["|config|"] = BUILTINS
|
|
1141
|
+
return substituter
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
def _number_of_line(member_tuple: tuple[str, object]) -> int:
|
|
1145
|
+
"""Try to return the number of the first line of the definition of a member of a
|
|
1146
|
+
module."""
|
|
1147
|
+
|
|
1148
|
+
def _query_index_first_line(member_: object) -> int:
|
|
1149
|
+
result = member_.__code__.co_firstlineno # type: ignore[attr-defined]
|
|
1150
|
+
assert isinstance(result, int)
|
|
1151
|
+
return result
|
|
1152
|
+
|
|
1153
|
+
member = member_tuple[1]
|
|
1154
|
+
try:
|
|
1155
|
+
return _query_index_first_line(member)
|
|
1156
|
+
except AttributeError:
|
|
1157
|
+
pass
|
|
1158
|
+
try:
|
|
1159
|
+
return inspect.findsource(member)[1] # type: ignore[arg-type]
|
|
1160
|
+
except BaseException:
|
|
1161
|
+
pass
|
|
1162
|
+
if (submembers := getattr(member, "__dict__", None)) is not None:
|
|
1163
|
+
for value in submembers.values():
|
|
1164
|
+
try:
|
|
1165
|
+
return _query_index_first_line(value)
|
|
1166
|
+
except AttributeError:
|
|
1167
|
+
pass
|
|
1168
|
+
return 0
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
def autodoc_module(module: types.ModuleType) -> None:
|
|
1172
|
+
"""Add a short summary of all implemented members to a module's docstring."""
|
|
1173
|
+
doc = getattr(module, "__doc__")
|
|
1174
|
+
members = []
|
|
1175
|
+
for name, member in inspect.getmembers(module):
|
|
1176
|
+
if (not name.startswith("_")) and (inspect.getmodule(member) is module):
|
|
1177
|
+
members.append((name, member))
|
|
1178
|
+
members = sorted(members, key=_number_of_line)
|
|
1179
|
+
if members:
|
|
1180
|
+
lines = [
|
|
1181
|
+
f"\n\nModule :mod:`~{module.__name__}` implements the following members:\n"
|
|
1182
|
+
]
|
|
1183
|
+
for name, member in members:
|
|
1184
|
+
if inspect.isfunction(member):
|
|
1185
|
+
type_ = "func"
|
|
1186
|
+
elif inspect.isclass(member):
|
|
1187
|
+
type_ = "class"
|
|
1188
|
+
else:
|
|
1189
|
+
type_ = "obj"
|
|
1190
|
+
lines.append(
|
|
1191
|
+
f" * :{type_}:`~{name}` {objecttools.description(member)}"
|
|
1192
|
+
)
|
|
1193
|
+
doc = doc + "\n\n" + "\n".join(lines) + "\n\n" + 80 * "_"
|
|
1194
|
+
module.__doc__ = doc
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
_name2descr = {
|
|
1198
|
+
"CLASSES": "The following classes are selected",
|
|
1199
|
+
"RECEIVER_METHODS": (
|
|
1200
|
+
'The following "receiver update methods" are called in the given sequence '
|
|
1201
|
+
"before performing a simulation step"
|
|
1202
|
+
),
|
|
1203
|
+
"INLET_METHODS": (
|
|
1204
|
+
'The following "inlet update methods" are called in the given sequence at the '
|
|
1205
|
+
"beginning of each simulation step"
|
|
1206
|
+
),
|
|
1207
|
+
"RUN_METHODS": (
|
|
1208
|
+
'The following "run methods" are called in the given sequence during each '
|
|
1209
|
+
"simulation step"
|
|
1210
|
+
),
|
|
1211
|
+
"PART_ODE_METHODS": (
|
|
1212
|
+
"The following methods define the relevant components of a system of ODE "
|
|
1213
|
+
"equations (e.g. direct runoff)"
|
|
1214
|
+
),
|
|
1215
|
+
"FULL_ODE_METHODS": (
|
|
1216
|
+
"The following methods define the complete equations of an ODE system (e.g. "
|
|
1217
|
+
"change in storage of `fast water` due to effective precipitation and direct "
|
|
1218
|
+
"runoff)"
|
|
1219
|
+
),
|
|
1220
|
+
"OUTLET_METHODS": (
|
|
1221
|
+
'The following "outlet update methods" are called in the given sequence at '
|
|
1222
|
+
"the end of each simulation step"
|
|
1223
|
+
),
|
|
1224
|
+
"SENDER_METHODS": (
|
|
1225
|
+
'The following "sender update methods" are called in the given sequence after '
|
|
1226
|
+
"performing a simulation step"
|
|
1227
|
+
),
|
|
1228
|
+
"INTERFACE_METHODS": (
|
|
1229
|
+
"The following interface methods are available to main models using the "
|
|
1230
|
+
"defined model as a submodel"
|
|
1231
|
+
),
|
|
1232
|
+
"ADD_METHODS": (
|
|
1233
|
+
'The following "additional methods" might be called by one or more of the '
|
|
1234
|
+
"other methods or are meant to be directly called by the user"
|
|
1235
|
+
),
|
|
1236
|
+
"SUBMODELINTERFACES": (
|
|
1237
|
+
"Users can hook submodels into the defined main model if they satisfy one of "
|
|
1238
|
+
"the following interfaces"
|
|
1239
|
+
),
|
|
1240
|
+
"SUBMODELS": (
|
|
1241
|
+
'The following "submodels" might be called by one or more of the implemented '
|
|
1242
|
+
"methods or are meant to be directly called by the user"
|
|
1243
|
+
),
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
_loggedtuples: set[str] = set()
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
def autodoc_tuple2doc(module: types.ModuleType) -> None:
|
|
1250
|
+
"""Include tuples as `CLASSES` of `ControlParameters` and `RUN_METHODS` of `Models`
|
|
1251
|
+
into the respective docstring."""
|
|
1252
|
+
modulename = module.__name__
|
|
1253
|
+
for membername, member in inspect.getmembers(module):
|
|
1254
|
+
for tuplename, descr in _name2descr.items():
|
|
1255
|
+
tuple_ = getattr(member, tuplename, None)
|
|
1256
|
+
if tuple_:
|
|
1257
|
+
logstring = f"{modulename}.{membername}.{tuplename}"
|
|
1258
|
+
if logstring not in _loggedtuples:
|
|
1259
|
+
_loggedtuples.add(logstring)
|
|
1260
|
+
lst = [f"\n\n\n {descr}:"]
|
|
1261
|
+
if tuplename == "CLASSES":
|
|
1262
|
+
type_ = "func"
|
|
1263
|
+
else:
|
|
1264
|
+
type_ = "class"
|
|
1265
|
+
for cls in tuple_:
|
|
1266
|
+
lst.append(
|
|
1267
|
+
f" * "
|
|
1268
|
+
f":{type_}:`~{cls.__module__}.{cls.__name__}`"
|
|
1269
|
+
f" {objecttools.description(cls)}"
|
|
1270
|
+
)
|
|
1271
|
+
doc = getattr(member, "__doc__")
|
|
1272
|
+
member.__doc__ = doc + "\n".join(l for l in lst)
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
def _make_cssstyle(
|
|
1276
|
+
*,
|
|
1277
|
+
marginleft: str | None = None,
|
|
1278
|
+
marginbottom: str | None = None,
|
|
1279
|
+
margintop: str | None = None,
|
|
1280
|
+
colour: str | None = None,
|
|
1281
|
+
fontfamily: str | None = None,
|
|
1282
|
+
fontstyle: str | None = None,
|
|
1283
|
+
fontsize: str | None = None,
|
|
1284
|
+
) -> str:
|
|
1285
|
+
|
|
1286
|
+
styles = []
|
|
1287
|
+
if marginleft is not None:
|
|
1288
|
+
styles.append(f"margin-left:{marginleft}")
|
|
1289
|
+
if marginbottom is not None:
|
|
1290
|
+
styles.append(f"margin-bottom:{marginbottom}")
|
|
1291
|
+
if margintop is not None:
|
|
1292
|
+
styles.append(f"margin-top:{margintop}")
|
|
1293
|
+
if colour is not None:
|
|
1294
|
+
styles.append(f"color:{colour}")
|
|
1295
|
+
if fontfamily is not None:
|
|
1296
|
+
styles.append(f"font-family:{fontfamily}")
|
|
1297
|
+
if fontstyle is not None:
|
|
1298
|
+
styles.append(f"font-style:{fontstyle}")
|
|
1299
|
+
if fontsize is not None:
|
|
1300
|
+
styles.append(f"font-size:{fontsize}")
|
|
1301
|
+
style = "; ".join(styles)
|
|
1302
|
+
return f'style="{style}"'
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
class Directory(TypedDict):
|
|
1306
|
+
"""Helper for representing directory structures."""
|
|
1307
|
+
|
|
1308
|
+
subdirectories: dict[str, Directory]
|
|
1309
|
+
"""Mapping between the subdirectory names and the subdirectories of a directory."""
|
|
1310
|
+
|
|
1311
|
+
files: list[str]
|
|
1312
|
+
"""The names of all files of a directory."""
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
class ProjectStructure:
|
|
1316
|
+
"""Analyser and visualiser of the file structure of HydPy projects."""
|
|
1317
|
+
|
|
1318
|
+
_dirpath: str
|
|
1319
|
+
"""Directory path to the HydPy project."""
|
|
1320
|
+
_projectname: str
|
|
1321
|
+
"""Directory name of the HydPy project."""
|
|
1322
|
+
_branch: str
|
|
1323
|
+
"""The relevant git branch (required to build stable references to the correct
|
|
1324
|
+
project files on GitHub)."""
|
|
1325
|
+
|
|
1326
|
+
def __init__(self, *, projectpath: str, branch: str) -> None:
|
|
1327
|
+
self._dirpath = projectpath
|
|
1328
|
+
self._projectname = os.path.split(projectpath)[-1]
|
|
1329
|
+
self._branch = branch
|
|
1330
|
+
|
|
1331
|
+
@functools.cached_property
|
|
1332
|
+
def url_prefix(self) -> str:
|
|
1333
|
+
"""The base GitHub URL that is common to all project files of the relevant
|
|
1334
|
+
branch.
|
|
1335
|
+
|
|
1336
|
+
>>> import os
|
|
1337
|
+
>>> from hydpy import data
|
|
1338
|
+
>>> projectpath = os.path.join(data.__path__[0], "HydPy-H-Lahn")
|
|
1339
|
+
>>> from hydpy.core.autodoctools import ProjectStructure
|
|
1340
|
+
>>> ProjectStructure(projectpath=projectpath, branch="master").url_prefix
|
|
1341
|
+
'https://github.com/hydpy-dev/hydpy/blob/master/hydpy/data'
|
|
1342
|
+
>>> ProjectStructure(projectpath=projectpath, branch="release/v6.0").url_prefix
|
|
1343
|
+
'https://github.com/hydpy-dev/hydpy/blob/release/v6.0/hydpy/data'
|
|
1344
|
+
"""
|
|
1345
|
+
|
|
1346
|
+
return f"https://github.com/hydpy-dev/hydpy/blob/{self._branch}/hydpy/data"
|
|
1347
|
+
|
|
1348
|
+
def _get_filereference(self, url_dirpath: str, filename: str) -> str:
|
|
1349
|
+
url_suffix = "/".join([url_dirpath, filename])
|
|
1350
|
+
return (
|
|
1351
|
+
f"<a "
|
|
1352
|
+
f'class="reference external" '
|
|
1353
|
+
f'href="{self.url_prefix}/{url_suffix}">{filename}'
|
|
1354
|
+
f"</a>"
|
|
1355
|
+
)
|
|
1356
|
+
|
|
1357
|
+
@functools.cached_property
|
|
1358
|
+
def directories(self) -> Directory:
|
|
1359
|
+
"""A representation of the project's file structure based on nested |Directory|
|
|
1360
|
+
dictionaries.
|
|
1361
|
+
|
|
1362
|
+
>>> import os
|
|
1363
|
+
>>> from hydpy import data
|
|
1364
|
+
>>> dirpath = os.path.join(data.__path__[0], "HydPy-H-Lahn")
|
|
1365
|
+
>>> from hydpy.core.autodoctools import ProjectStructure
|
|
1366
|
+
>>> pj = ProjectStructure(projectpath=dirpath, branch="master")
|
|
1367
|
+
>>> from pprint import pprint
|
|
1368
|
+
>>> pprint(pj.directories["files"])
|
|
1369
|
+
['multiple_runs.xml',
|
|
1370
|
+
'multiple_runs_alpha.xml',
|
|
1371
|
+
'single_run.xml',
|
|
1372
|
+
'single_run.xmlt']
|
|
1373
|
+
>>> list(pj.directories["subdirectories"])
|
|
1374
|
+
['conditions', 'control', 'network', 'series']
|
|
1375
|
+
>>> control = pj.directories["subdirectories"]["control"]
|
|
1376
|
+
>>> pprint(control["subdirectories"]["default"]["files"])
|
|
1377
|
+
['land.py',
|
|
1378
|
+
'land_dill_assl.py',
|
|
1379
|
+
'land_lahn_kalk.py',
|
|
1380
|
+
'land_lahn_leun.py',
|
|
1381
|
+
'land_lahn_marb.py',
|
|
1382
|
+
'stream_dill_assl_lahn_leun.py',
|
|
1383
|
+
'stream_lahn_leun_lahn_kalk.py',
|
|
1384
|
+
'stream_lahn_marb_lahn_leun.py']
|
|
1385
|
+
>>> pprint(control["subdirectories"]["default"]["subdirectories"])
|
|
1386
|
+
{}
|
|
1387
|
+
"""
|
|
1388
|
+
|
|
1389
|
+
def _make_directory(dirpath: str) -> Directory:
|
|
1390
|
+
subdir: Directory = {"subdirectories": {}, "files": []}
|
|
1391
|
+
for name in sorted(os.listdir(dirpath)):
|
|
1392
|
+
if name.startswith("_"):
|
|
1393
|
+
continue
|
|
1394
|
+
path = os.path.join(dirpath, name)
|
|
1395
|
+
if os.path.isfile(path):
|
|
1396
|
+
subdir["files"].append(name)
|
|
1397
|
+
else:
|
|
1398
|
+
subdirpath = os.path.join(dirpath, name)
|
|
1399
|
+
subdir["subdirectories"][name] = _make_directory(subdirpath)
|
|
1400
|
+
return subdir
|
|
1401
|
+
|
|
1402
|
+
return _make_directory(self._dirpath)
|
|
1403
|
+
|
|
1404
|
+
@functools.cached_property
|
|
1405
|
+
def html(self) -> str:
|
|
1406
|
+
"""A representation of the project's file structure based on nested HTML
|
|
1407
|
+
`describe` elements, including inline CSS instructions.
|
|
1408
|
+
|
|
1409
|
+
>>> import os
|
|
1410
|
+
>>> from hydpy import data
|
|
1411
|
+
>>> projectpath = os.path.join(data.__path__[0], "HydPy-H-Lahn")
|
|
1412
|
+
>>> from hydpy.core.autodoctools import ProjectStructure
|
|
1413
|
+
>>> pj = ProjectStructure(projectpath=projectpath, branch="master")
|
|
1414
|
+
>>> print(pj.html) # doctest: +ELLIPSIS
|
|
1415
|
+
<details style="margin-left:1em; color:#20435c; font-family:'Trebuchet MS'">
|
|
1416
|
+
<summary><b>HydPy-H-Lahn</b></summary>
|
|
1417
|
+
...
|
|
1418
|
+
<details style="margin-left:1em">
|
|
1419
|
+
<summary><b>control</b></summary>
|
|
1420
|
+
<details style="margin-left:1em">
|
|
1421
|
+
<summary><b>default</b></summary>
|
|
1422
|
+
<h style="margin-left:1em"><a class="reference external" \
|
|
1423
|
+
href="https://github.com/hydpy-dev/hydpy/blob/master/hydpy/data/HydPy-H-Lahn/control\
|
|
1424
|
+
/default/land.py">land.py</a></h><br/>
|
|
1425
|
+
...
|
|
1426
|
+
<h style="margin-left:1em"><a class="reference external" \
|
|
1427
|
+
href="https://github.com/hydpy-dev/hydpy/blob/master/hydpy/data/HydPy-H-Lahn/control\
|
|
1428
|
+
/default/stream_lahn_marb_lahn_leun.py">stream_lahn_marb_lahn_leun.py</a></h><br/>
|
|
1429
|
+
</details>
|
|
1430
|
+
</details>
|
|
1431
|
+
...
|
|
1432
|
+
</details>
|
|
1433
|
+
"""
|
|
1434
|
+
|
|
1435
|
+
def _make_html(
|
|
1436
|
+
dirname: str, dir_: Directory, url: str, indent: int
|
|
1437
|
+
) -> list[str]:
|
|
1438
|
+
if indent == 0:
|
|
1439
|
+
style = _make_cssstyle(
|
|
1440
|
+
marginleft="1em", colour="#20435c", fontfamily="'Trebuchet MS'"
|
|
1441
|
+
)
|
|
1442
|
+
else:
|
|
1443
|
+
style = _make_cssstyle(marginleft="1em")
|
|
1444
|
+
prefix = indent * " "
|
|
1445
|
+
lines = []
|
|
1446
|
+
lines.append(f"{prefix}<details {style}>")
|
|
1447
|
+
lines.append(f"{prefix} <summary><b>{dirname}</b></summary>")
|
|
1448
|
+
for subdirname, subdir in dir_["subdirectories"].items():
|
|
1449
|
+
html_ = _make_html(
|
|
1450
|
+
dirname=subdirname,
|
|
1451
|
+
dir_=subdir,
|
|
1452
|
+
url="/".join([url, subdirname]),
|
|
1453
|
+
indent=indent + 1,
|
|
1454
|
+
)
|
|
1455
|
+
lines.extend(html_)
|
|
1456
|
+
for filename in dir_["files"]:
|
|
1457
|
+
ref = self._get_filereference(url_dirpath=url, filename=filename)
|
|
1458
|
+
lines.append(f"{prefix} <h {style}>{ref}</h><br/>")
|
|
1459
|
+
lines.append(f"{prefix}</details>")
|
|
1460
|
+
return lines
|
|
1461
|
+
|
|
1462
|
+
html = _make_html(
|
|
1463
|
+
dirname=self._projectname,
|
|
1464
|
+
dir_=self.directories,
|
|
1465
|
+
url=self._projectname,
|
|
1466
|
+
indent=0,
|
|
1467
|
+
)
|
|
1468
|
+
return "\n".join(html)
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
def make_modellink(model: type[modeltools.Model]) -> str:
|
|
1472
|
+
"""Create an internal HTML reference pointing to an application model.
|
|
1473
|
+
|
|
1474
|
+
>>> from hydpy.core.autodoctools import make_modellink
|
|
1475
|
+
>>> from hydpy.models import hland_96
|
|
1476
|
+
>>> make_modellink(hland_96.Model)
|
|
1477
|
+
'<a class="reference internal" \
|
|
1478
|
+
href="hland_96.html#module-hydpy.models.hland_96" \
|
|
1479
|
+
title="HydPy-H-HBV96 (adoption of SMHI-IHMS-HBV96)">\
|
|
1480
|
+
<code class="xref py py-mod docutils literal notranslate">\
|
|
1481
|
+
<span class="pre">hland_96</span></code></a>'
|
|
1482
|
+
"""
|
|
1483
|
+
name = model.__HYDPY_NAME__
|
|
1484
|
+
return (
|
|
1485
|
+
'<a class="reference internal" '
|
|
1486
|
+
f'href="{name}.html#module-hydpy.models.{name}" '
|
|
1487
|
+
f'title="{model.DOCNAME.complete}">'
|
|
1488
|
+
'<code class="xref py py-mod docutils literal notranslate">'
|
|
1489
|
+
f'<span class="pre">{name}</span></code></a>'
|
|
1490
|
+
)
|
|
1491
|
+
|
|
1492
|
+
|
|
1493
|
+
def make_interfacelink(interface: type[modeltools.SubmodelInterface]) -> str:
|
|
1494
|
+
"""Create an internal HTML reference pointing to a submodel interface.
|
|
1495
|
+
|
|
1496
|
+
>>> from hydpy.core.autodoctools import make_interfacelink
|
|
1497
|
+
>>> from hydpy.interfaces.aetinterfaces import AETModel_V1
|
|
1498
|
+
>>> make_interfacelink(AETModel_V1)
|
|
1499
|
+
'<a class="reference internal" \
|
|
1500
|
+
href="aetinterfaces.html#hydpy.interfaces.aetinterfaces.AETModel_V1" \
|
|
1501
|
+
title="hydpy.interfaces.aetinterfaces.AETModel_V1">\
|
|
1502
|
+
<code class="xref py py-class docutils literal notranslate">\
|
|
1503
|
+
<span class="pre">AETModel_V1</span></code></a>'
|
|
1504
|
+
"""
|
|
1505
|
+
classname = interface.__name__
|
|
1506
|
+
modulepath = interface.__module__
|
|
1507
|
+
modulename = modulepath.split(".")[-1]
|
|
1508
|
+
classpath = f"{modulepath}.{classname}"
|
|
1509
|
+
return (
|
|
1510
|
+
f'<a class="reference internal" '
|
|
1511
|
+
f'href="{modulename}.html#{classpath}" '
|
|
1512
|
+
f'title="{classpath}"><code '
|
|
1513
|
+
f'class="xref py py-class docutils literal notranslate"><span '
|
|
1514
|
+
f'class="pre">{classname}</span></code></a>'
|
|
1515
|
+
)
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
Port: TypeAlias = modeltools.SubmodelProperty | modeltools.SubmodelsProperty
|
|
1519
|
+
|
|
1520
|
+
Subgraphs: TypeAlias = dict[
|
|
1521
|
+
type[modeltools.Model], dict[Port, list[type[modeltools.Model]]]
|
|
1522
|
+
]
|
|
1523
|
+
|
|
1524
|
+
Graph: TypeAlias = dict[
|
|
1525
|
+
type[modeltools.Model], dict[Port, tuple["Graph", list[type[modeltools.Model]]]]
|
|
1526
|
+
]
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
class SubmodelGraph:
|
|
1530
|
+
"""Analyser and visualiser of the advisable connections between main models and
|
|
1531
|
+
submodels."""
|
|
1532
|
+
|
|
1533
|
+
_modelname: str | None
|
|
1534
|
+
|
|
1535
|
+
def __init__(self, *, modelname: str | None = None) -> None:
|
|
1536
|
+
self._modelname = modelname
|
|
1537
|
+
|
|
1538
|
+
@functools.cached_property
|
|
1539
|
+
def interfaces(self) -> tuple[type[modeltools.SubmodelInterface], ...]:
|
|
1540
|
+
"""All available submodel interfaces.
|
|
1541
|
+
|
|
1542
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1543
|
+
>>> for interface in SubmodelGraph().interfaces:
|
|
1544
|
+
... print(interface.__HYDPY_NAME__) # doctest: +ELLIPSIS
|
|
1545
|
+
AETModel_V1
|
|
1546
|
+
ChannelModel_V1
|
|
1547
|
+
...
|
|
1548
|
+
TempModel_V1
|
|
1549
|
+
TempModel_V2
|
|
1550
|
+
WaterLevelModel_V1
|
|
1551
|
+
"""
|
|
1552
|
+
dirpath = interfaces.__path__[0]
|
|
1553
|
+
filenames = (n for n in os.listdir(dirpath) if n.endswith(".py"))
|
|
1554
|
+
modulenames = (n[:-3] for n in filenames if n != "__init__.py")
|
|
1555
|
+
classes = []
|
|
1556
|
+
for modulename in modulenames:
|
|
1557
|
+
module = importlib.import_module(f"hydpy.interfaces.{modulename}")
|
|
1558
|
+
for _, member in inspect.getmembers(module):
|
|
1559
|
+
if (
|
|
1560
|
+
inspect.isclass(member)
|
|
1561
|
+
and (inspect.getmodule(member) is module)
|
|
1562
|
+
and issubclass(member, modeltools.SubmodelInterface)
|
|
1563
|
+
):
|
|
1564
|
+
classes.append(member)
|
|
1565
|
+
return tuple(sorted(classes, key=lambda c: c.__name__))
|
|
1566
|
+
|
|
1567
|
+
@functools.cached_property
|
|
1568
|
+
def models(self) -> tuple[type[modeltools.Model], ...]:
|
|
1569
|
+
"""All available application models.
|
|
1570
|
+
|
|
1571
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1572
|
+
>>> for model in SubmodelGraph().models:
|
|
1573
|
+
... print(model.__HYDPY_NAME__) # doctest: +ELLIPSIS
|
|
1574
|
+
arma_rimorido
|
|
1575
|
+
conv_idw
|
|
1576
|
+
...
|
|
1577
|
+
wland_wag
|
|
1578
|
+
wq_trapeze
|
|
1579
|
+
wq_trapeze_strickler
|
|
1580
|
+
wq_walrus
|
|
1581
|
+
"""
|
|
1582
|
+
dirpath = models.__path__[0]
|
|
1583
|
+
filenames = (n for n in os.listdir(dirpath) if n.endswith(".py"))
|
|
1584
|
+
modulenames = (n[:-3] for n in filenames if n != "__init__.py")
|
|
1585
|
+
classes = []
|
|
1586
|
+
for modulename in modulenames:
|
|
1587
|
+
module = importlib.import_module(f"hydpy.models.{modulename}")
|
|
1588
|
+
for _, member in inspect.getmembers(module):
|
|
1589
|
+
if (
|
|
1590
|
+
inspect.isclass(member)
|
|
1591
|
+
and issubclass(member, modeltools.Model)
|
|
1592
|
+
and (inspect.getmodule(member) is module)
|
|
1593
|
+
and member.__name__ == "Model"
|
|
1594
|
+
):
|
|
1595
|
+
classes.append(member)
|
|
1596
|
+
return tuple(sorted(classes, key=lambda c: c.__HYDPY_NAME__))
|
|
1597
|
+
|
|
1598
|
+
@functools.cached_property
|
|
1599
|
+
def rootmodels(self) -> tuple[type[modeltools.Model], ...]:
|
|
1600
|
+
"""The models that build the roots of the submodel graph.
|
|
1601
|
+
|
|
1602
|
+
By default, all documentation-relevant main models:
|
|
1603
|
+
|
|
1604
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1605
|
+
>>> for model in SubmodelGraph().rootmodels:
|
|
1606
|
+
... print(model.__HYDPY_NAME__) # doctest: +ELLIPSIS
|
|
1607
|
+
arma_rimorido
|
|
1608
|
+
conv_idw
|
|
1609
|
+
...
|
|
1610
|
+
whmod_urban
|
|
1611
|
+
wland_gd
|
|
1612
|
+
wland_wag
|
|
1613
|
+
|
|
1614
|
+
Or only the selected model:
|
|
1615
|
+
|
|
1616
|
+
>>> for model in SubmodelGraph(modelname="wland_gd").rootmodels:
|
|
1617
|
+
... print(model.__HYDPY_NAME__)
|
|
1618
|
+
wland_gd
|
|
1619
|
+
"""
|
|
1620
|
+
rootmodels = []
|
|
1621
|
+
for model in self.models:
|
|
1622
|
+
if (model.__HYDPY_ROOTMODEL__ is True) and (
|
|
1623
|
+
((name := self._modelname) is None) or (name == model.__HYDPY_NAME__)
|
|
1624
|
+
):
|
|
1625
|
+
rootmodels.append(model)
|
|
1626
|
+
assert rootmodels
|
|
1627
|
+
return tuple(rootmodels)
|
|
1628
|
+
|
|
1629
|
+
@functools.cached_property
|
|
1630
|
+
def subgraphs(self) -> Subgraphs:
|
|
1631
|
+
"""Mappings from all models over their ports to their potential submodels.
|
|
1632
|
+
|
|
1633
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1634
|
+
>>> subgraphs = SubmodelGraph().subgraphs
|
|
1635
|
+
>>> from hydpy.models import exch_branch_hbv96, hland_96
|
|
1636
|
+
>>> subgraphs[exch_branch_hbv96.Model]
|
|
1637
|
+
{}
|
|
1638
|
+
>>> for port, models in subgraphs[hland_96.Model].items():
|
|
1639
|
+
... print(port.name, *(model.__HYDPY_NAME__ for model in models))
|
|
1640
|
+
aetmodel evap_aet_hbv96 evap_aet_minhas evap_aet_morsim
|
|
1641
|
+
rconcmodel rconc_nash rconc_uh
|
|
1642
|
+
"""
|
|
1643
|
+
main2port2subs: Subgraphs = {}
|
|
1644
|
+
for main in self.models:
|
|
1645
|
+
main2port2subs[main] = {}
|
|
1646
|
+
for _, port in inspect.getmembers(main):
|
|
1647
|
+
if isinstance(
|
|
1648
|
+
port, (modeltools.SubmodelProperty, modeltools.SubmodelsProperty)
|
|
1649
|
+
):
|
|
1650
|
+
main2port2subs[main][port] = [
|
|
1651
|
+
m for m in self.models if issubclass(m, port.interfaces)
|
|
1652
|
+
]
|
|
1653
|
+
return main2port2subs
|
|
1654
|
+
|
|
1655
|
+
@functools.cached_property
|
|
1656
|
+
def graph(self) -> Graph:
|
|
1657
|
+
"""The complete (recursive) graph for all or the selected root models.
|
|
1658
|
+
|
|
1659
|
+
Example for a main model without any submodels:
|
|
1660
|
+
|
|
1661
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1662
|
+
>>> graph = SubmodelGraph(modelname="exch_branch_hbv96").graph
|
|
1663
|
+
>>> for model, subgraph in graph.items():
|
|
1664
|
+
... print(model.__HYDPY_NAME__, subgraph)
|
|
1665
|
+
exch_branch_hbv96 {}
|
|
1666
|
+
|
|
1667
|
+
Complex example that covers two important cases: (1) main models used as
|
|
1668
|
+
sub-submodels; (2) PET models are not suggested as submodel candidates for
|
|
1669
|
+
other PET models due to special-casing:
|
|
1670
|
+
|
|
1671
|
+
>>> graph = SubmodelGraph(modelname="hland_96").graph
|
|
1672
|
+
>>> for model, subgraph in graph.items():
|
|
1673
|
+
... print(model.__HYDPY_NAME__, *(port.name for port in subgraph))
|
|
1674
|
+
hland_96 aetmodel rconcmodel
|
|
1675
|
+
|
|
1676
|
+
>>> selected = tuple(graph.values())[0]
|
|
1677
|
+
>>> for port, (subgraphs, mainsubmodels) in selected.items():
|
|
1678
|
+
... print(port.name)
|
|
1679
|
+
... print("main-submodels:", *(m.__HYDPY_NAME__ for m in mainsubmodels))
|
|
1680
|
+
... print("sub-submodels:", *(m.__HYDPY_NAME__ for m in subgraphs))
|
|
1681
|
+
aetmodel
|
|
1682
|
+
main-submodels:
|
|
1683
|
+
sub-submodels: evap_aet_hbv96 evap_aet_minhas evap_aet_morsim
|
|
1684
|
+
rconcmodel
|
|
1685
|
+
main-submodels:
|
|
1686
|
+
sub-submodels: rconc_nash rconc_uh
|
|
1687
|
+
|
|
1688
|
+
>>> selected = tuple(selected.values())[0][0]
|
|
1689
|
+
>>> for model, subgraph in selected.items():
|
|
1690
|
+
... print(model.__HYDPY_NAME__, *(port.name for port in subgraph))
|
|
1691
|
+
evap_aet_hbv96 intercmodel petmodel snowcovermodel soilwatermodel tempmodel
|
|
1692
|
+
evap_aet_minhas intercmodel petmodel soilwatermodel
|
|
1693
|
+
evap_aet_morsim intercmodel radiationmodel snowalbedomodel snowcovermodel \
|
|
1694
|
+
snowycanopymodel soilwatermodel tempmodel
|
|
1695
|
+
|
|
1696
|
+
>>> selected = tuple(tuple(selected.values())[0].items())[:2]
|
|
1697
|
+
>>> for port, (subgraphs, mainsubmodels) in selected:
|
|
1698
|
+
... print(port.name)
|
|
1699
|
+
... print("main-submodels:", *(m.__HYDPY_NAME__ for m in mainsubmodels))
|
|
1700
|
+
... print("sub-submodels:", *(m.__HYDPY_NAME__ for m in subgraphs))
|
|
1701
|
+
intercmodel
|
|
1702
|
+
main-submodels: hland_96
|
|
1703
|
+
sub-submodels: dummy_interceptedwater
|
|
1704
|
+
petmodel
|
|
1705
|
+
main-submodels:
|
|
1706
|
+
sub-submodels: evap_pet_ambav1 evap_pet_hbv96 evap_pet_m evap_pet_mlc \
|
|
1707
|
+
evap_ret_fao56 evap_ret_io evap_ret_tw2002
|
|
1708
|
+
|
|
1709
|
+
>>> selected = selected[1][1][0]
|
|
1710
|
+
>>> for model, subgraph in selected.items():
|
|
1711
|
+
... print(model.__HYDPY_NAME__, *(port.name for port in subgraph))
|
|
1712
|
+
evap_pet_ambav1 precipmodel radiationmodel snowcovermodel tempmodel
|
|
1713
|
+
evap_pet_hbv96 precipmodel tempmodel
|
|
1714
|
+
evap_pet_m retmodel
|
|
1715
|
+
evap_pet_mlc retmodel
|
|
1716
|
+
evap_ret_fao56 radiationmodel tempmodel
|
|
1717
|
+
evap_ret_io
|
|
1718
|
+
evap_ret_tw2002 radiationmodel tempmodel
|
|
1719
|
+
|
|
1720
|
+
>>> selected = tuple(selected.values())[2]
|
|
1721
|
+
>>> for port, (subgraphs, mainsubmodels) in selected.items():
|
|
1722
|
+
... print(port.name)
|
|
1723
|
+
... print("main-submodels:", *(m.__HYDPY_NAME__ for m in mainsubmodels))
|
|
1724
|
+
... print("sub-submodels:", *(m.__HYDPY_NAME__ for m in subgraphs))
|
|
1725
|
+
retmodel
|
|
1726
|
+
main-submodels:
|
|
1727
|
+
sub-submodels: evap_ret_fao56 evap_ret_io evap_ret_tw2002
|
|
1728
|
+
|
|
1729
|
+
Example showing that "side-model" ports are ignored:
|
|
1730
|
+
|
|
1731
|
+
>>> graph = SubmodelGraph(modelname="sw1d_channel").graph
|
|
1732
|
+
>>> for model, subgraph in graph.items():
|
|
1733
|
+
... print(model.__HYDPY_NAME__, *(port.name for port in subgraph))
|
|
1734
|
+
sw1d_channel routingmodels storagemodels
|
|
1735
|
+
|
|
1736
|
+
>>> selected = tuple(graph.values())[0]
|
|
1737
|
+
>>> for port, (subgraphs, mainsubmodels) in selected.items():
|
|
1738
|
+
... print(port.name)
|
|
1739
|
+
... print("main-submodels:", *(m.__HYDPY_NAME__ for m in mainsubmodels))
|
|
1740
|
+
... print("sub-submodels:", *(m.__HYDPY_NAME__ for m in subgraphs))
|
|
1741
|
+
routingmodels
|
|
1742
|
+
main-submodels:
|
|
1743
|
+
sub-submodels: sw1d_gate_out sw1d_lias sw1d_lias_sluice sw1d_pump sw1d_q_in \
|
|
1744
|
+
sw1d_q_out sw1d_weir_out
|
|
1745
|
+
storagemodels
|
|
1746
|
+
main-submodels:
|
|
1747
|
+
sub-submodels: sw1d_storage
|
|
1748
|
+
|
|
1749
|
+
>>> selected = tuple(selected.values())[0][0]
|
|
1750
|
+
>>> for model, subgraph in selected.items():
|
|
1751
|
+
... print(model.__HYDPY_NAME__, *(port.name for port in subgraph))
|
|
1752
|
+
sw1d_gate_out
|
|
1753
|
+
sw1d_lias crosssection
|
|
1754
|
+
sw1d_lias_sluice crosssection
|
|
1755
|
+
sw1d_pump crosssection
|
|
1756
|
+
sw1d_q_in crosssection
|
|
1757
|
+
sw1d_q_out crosssection
|
|
1758
|
+
sw1d_weir_out
|
|
1759
|
+
"""
|
|
1760
|
+
|
|
1761
|
+
def _exclude(
|
|
1762
|
+
mainmodel: type[modeltools.Model], submodel: type[modeltools.Model]
|
|
1763
|
+
) -> bool:
|
|
1764
|
+
name_main = mainmodel.__HYDPY_NAME__
|
|
1765
|
+
name_sub = submodel.__HYDPY_NAME__
|
|
1766
|
+
main_comps = name_main.split("_")
|
|
1767
|
+
sub_comps = name_sub.split("_")
|
|
1768
|
+
if "evap" == main_comps[0] == sub_comps[0]:
|
|
1769
|
+
if (main_comps[1] == "pet") and (sub_comps[1] != "ret"):
|
|
1770
|
+
return True
|
|
1771
|
+
return False
|
|
1772
|
+
|
|
1773
|
+
def _get_subgraph(
|
|
1774
|
+
model: type[modeltools.Model], visited: set[type[modeltools.Model]]
|
|
1775
|
+
) -> Graph:
|
|
1776
|
+
|
|
1777
|
+
visited.add(model)
|
|
1778
|
+
|
|
1779
|
+
graph: Graph = {model: {}}
|
|
1780
|
+
|
|
1781
|
+
for port, submodels in self.subgraphs[model].items():
|
|
1782
|
+
|
|
1783
|
+
if isinstance(port, modeltools.SubmodelProperty):
|
|
1784
|
+
if port.sidemodel:
|
|
1785
|
+
continue
|
|
1786
|
+
elif port.sidemodels:
|
|
1787
|
+
continue
|
|
1788
|
+
|
|
1789
|
+
mainsubmodels = []
|
|
1790
|
+
subgraph: Graph = {}
|
|
1791
|
+
for submodel in submodels:
|
|
1792
|
+
if _exclude(model, submodel):
|
|
1793
|
+
continue
|
|
1794
|
+
if (
|
|
1795
|
+
(submodel in visited)
|
|
1796
|
+
and issubclass(model, modeltools.SubmodelInterface)
|
|
1797
|
+
and model().add_mainmodel_as_subsubmodel(submodel())
|
|
1798
|
+
):
|
|
1799
|
+
mainsubmodels.append(submodel)
|
|
1800
|
+
continue
|
|
1801
|
+
if submodel.__HYDPY_ROOTMODEL__:
|
|
1802
|
+
continue
|
|
1803
|
+
subgraph |= _get_subgraph(submodel, visited.copy())
|
|
1804
|
+
graph[model][port] = (subgraph, mainsubmodels)
|
|
1805
|
+
|
|
1806
|
+
return graph
|
|
1807
|
+
|
|
1808
|
+
complete: Graph = {}
|
|
1809
|
+
for root in self.rootmodels:
|
|
1810
|
+
complete[root] = _get_subgraph(model=root, visited=set())[root]
|
|
1811
|
+
return complete
|
|
1812
|
+
|
|
1813
|
+
@staticmethod
|
|
1814
|
+
def make_portinfo(port: Port, mainsubmodels: list[type[modeltools.Model]]) -> str:
|
|
1815
|
+
"""Create an informative sentence about the given port (if available, in the
|
|
1816
|
+
context of the given main models usable as sub-submodels).
|
|
1817
|
+
|
|
1818
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1819
|
+
>>> from hydpy.models.hland_96 import Model as h
|
|
1820
|
+
>>> SubmodelGraph.make_portinfo(h.rconcmodel, []) # doctest: +ELLIPSIS
|
|
1821
|
+
'Allows one submodel that follows the <a ...RConcModel_V1...</a> interface.'
|
|
1822
|
+
>>> SubmodelGraph.make_portinfo(h.aetmodel, []) # doctest: +ELLIPSIS
|
|
1823
|
+
'Requires one submodel that follows the <a ...AETModel_V1...</a> interface \
|
|
1824
|
+
(no default available).'
|
|
1825
|
+
>>> from hydpy.models.evap_aet_hbv96 import Model as e
|
|
1826
|
+
>>> SubmodelGraph.make_portinfo(e.tempmodel, [h]) # doctest: +ELLIPSIS
|
|
1827
|
+
'Requires one submodel that follows the <a ...TempModel_V1...</a> or \
|
|
1828
|
+
<a ...TempModel_V2...</a> interface (default is <a ...HydPy-H-HBV96...</a>).'
|
|
1829
|
+
>>> from hydpy.models.sw1d_channel import Model as s
|
|
1830
|
+
>>> SubmodelGraph.make_portinfo(s.storagemodels, []) # doctest: +ELLIPSIS
|
|
1831
|
+
'Allows multiple submodels that follow the <a ...StorageModel_V1...</a> \
|
|
1832
|
+
interface.'
|
|
1833
|
+
"""
|
|
1834
|
+
if isinstance(port, modeltools.SubmodelProperty):
|
|
1835
|
+
nmb_models = "one submodel that follows"
|
|
1836
|
+
if port.optional:
|
|
1837
|
+
necessity = "Allows"
|
|
1838
|
+
default = ""
|
|
1839
|
+
else:
|
|
1840
|
+
necessity = "Requires"
|
|
1841
|
+
if mainsubmodels:
|
|
1842
|
+
assert len(mainsubmodels) == 1
|
|
1843
|
+
default = f" (default is {make_modellink(mainsubmodels[0])})"
|
|
1844
|
+
else:
|
|
1845
|
+
default = " (no default available)"
|
|
1846
|
+
else:
|
|
1847
|
+
nmb_models = "multiple submodels that follow"
|
|
1848
|
+
necessity = "Allows"
|
|
1849
|
+
default = ""
|
|
1850
|
+
links = objecttools.enumeration(
|
|
1851
|
+
[make_interfacelink(i) for i in port.interfaces], conjunction="or"
|
|
1852
|
+
)
|
|
1853
|
+
return f"{necessity} {nmb_models} the {links} interface{default}."
|
|
1854
|
+
|
|
1855
|
+
@functools.cached_property
|
|
1856
|
+
def html(self) -> str:
|
|
1857
|
+
"""A representation of the complete or selected part of the submodel graph
|
|
1858
|
+
based on nested HTML `describe` elements, including inline CSS instructions.
|
|
1859
|
+
|
|
1860
|
+
>>> from hydpy.core.autodoctools import SubmodelGraph
|
|
1861
|
+
>>> print(SubmodelGraph().html) # doctest: +ELLIPSIS
|
|
1862
|
+
<details style="margin-left:1.0em; color:#20435c; font-family:'Trebuchet MS'">
|
|
1863
|
+
<summary><b>Complete Submodel Graph</b></summary>
|
|
1864
|
+
<h style="margin-left:1.9em"><a ...HydPy-ARMA-RIMO/RIDO...</a></h></br>
|
|
1865
|
+
...
|
|
1866
|
+
</details>
|
|
1867
|
+
|
|
1868
|
+
>>> print(SubmodelGraph(modelname="hland_96").html) # doctest: +ELLIPSIS
|
|
1869
|
+
<details style="margin-left:1.0em; color:#20435c; font-family:'Trebuchet MS'">
|
|
1870
|
+
<summary><b>Submodel Graph of HydPy-H-HBV96 (adoption of ...)</b></summary>
|
|
1871
|
+
<details style="margin-left:1.0em">
|
|
1872
|
+
<summary><a ...HydPy-H-HBV96...</a></summary>
|
|
1873
|
+
<details style="margin-left:1.0em">
|
|
1874
|
+
<summary>aetmodel</summary>
|
|
1875
|
+
<p style="margin-left:1.2em; margin-bottom:0.0em; margin-top:0.2em; \
|
|
1876
|
+
font-style:italic; font-size:80%">Requires one submodel ...</p>
|
|
1877
|
+
<details style="margin-left:1.0em">
|
|
1878
|
+
<summary><a ...HydPy-Evap-AET-HBV96...</a></summary>
|
|
1879
|
+
<details style="margin-left:1.0em">
|
|
1880
|
+
<summary>intercmodel</summary>
|
|
1881
|
+
<p style="margin-left:1.2em; margin-bottom:0.0em; margin-top:0.2em; \
|
|
1882
|
+
font-style:italic; font-size:80%">Requires one submodel ...</p>
|
|
1883
|
+
<h style="margin-left:1.9em"><a ...HydPy-H-HBV96...</a><br/></h>
|
|
1884
|
+
<h style="margin-left:1.9em"><a ...HydPy-Dummy-InterceptedWater ...\
|
|
1885
|
+
</a></h></br>
|
|
1886
|
+
...
|
|
1887
|
+
</details>
|
|
1888
|
+
</details>
|
|
1889
|
+
"""
|
|
1890
|
+
style_main = _make_cssstyle(
|
|
1891
|
+
marginleft="1.0em", colour="#20435c", fontfamily="'Trebuchet MS'"
|
|
1892
|
+
)
|
|
1893
|
+
style_10em = _make_cssstyle(marginleft="1.0em")
|
|
1894
|
+
style_19em = _make_cssstyle(marginleft="1.9em")
|
|
1895
|
+
style_descr = _make_cssstyle(
|
|
1896
|
+
marginleft="1.2em",
|
|
1897
|
+
margintop="0.2em",
|
|
1898
|
+
marginbottom="0.0em",
|
|
1899
|
+
fontstyle="italic",
|
|
1900
|
+
fontsize="80%",
|
|
1901
|
+
)
|
|
1902
|
+
|
|
1903
|
+
def _make_html(graph: Graph, indent: int) -> list[str]:
|
|
1904
|
+
prefix = indent * " "
|
|
1905
|
+
lines = []
|
|
1906
|
+
for model, port2subgraph_mainsubs in graph.items():
|
|
1907
|
+
modellink = make_modellink(model)
|
|
1908
|
+
if not port2subgraph_mainsubs:
|
|
1909
|
+
lines.append(f"{prefix}<h {style_19em}>{modellink}</h></br>")
|
|
1910
|
+
continue
|
|
1911
|
+
lines.append(f"{prefix}<details {style_10em}>")
|
|
1912
|
+
lines.append(f"{prefix} <summary>{modellink}</summary>")
|
|
1913
|
+
for port, (subgraph, mainsubmodels) in port2subgraph_mainsubs.items():
|
|
1914
|
+
lines.append(f"{prefix} <details {style_10em}>")
|
|
1915
|
+
lines.append(f"{prefix} <summary>{port.name}</summary>")
|
|
1916
|
+
info = self.make_portinfo(port, mainsubmodels)
|
|
1917
|
+
lines.append(f"{prefix} <p {style_descr}>{info}</p>")
|
|
1918
|
+
for mainsubmodel in mainsubmodels:
|
|
1919
|
+
link = make_modellink(mainsubmodel)
|
|
1920
|
+
lines.append(f"{prefix} <h {style_19em}>{link}<br/></h>")
|
|
1921
|
+
lines.extend(_make_html(subgraph, indent + 4))
|
|
1922
|
+
lines.append(f"{prefix} </details>")
|
|
1923
|
+
lines.append(f"{prefix}</details>")
|
|
1924
|
+
return lines
|
|
1925
|
+
|
|
1926
|
+
lines_ = [f"<details {style_main}>"]
|
|
1927
|
+
if self._modelname is None:
|
|
1928
|
+
lines_.append(" <summary><b>Complete Submodel Graph</b></summary>")
|
|
1929
|
+
else:
|
|
1930
|
+
docname = tuple(self.graph)[0].DOCNAME.complete
|
|
1931
|
+
lines_.append(f" <summary><b>Submodel Graph of {docname}</b></summary>")
|
|
1932
|
+
lines_.extend(_make_html(self.graph, 2))
|
|
1933
|
+
lines_.append("</details>")
|
|
1934
|
+
return "\n".join(lines_)
|
|
1935
|
+
|
|
1936
|
+
|
|
1937
|
+
# ToDo: remove when stopping supporting Python 3.12
|
|
1938
|
+
# (see https://github.com/python/cpython/issues/107995)
|
|
1939
|
+
__test__ = {
|
|
1940
|
+
f"ProjectStructure.{name}": member
|
|
1941
|
+
for name, member in inspect.getmembers(ProjectStructure)
|
|
1942
|
+
if isinstance(member, functools.cached_property)
|
|
1943
|
+
} | {
|
|
1944
|
+
f"SubmodelGraph.{name}": member
|
|
1945
|
+
for name, member in inspect.getmembers(SubmodelGraph)
|
|
1946
|
+
if isinstance(member, functools.cached_property)
|
|
1947
|
+
}
|