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.
Files changed (890) hide show
  1. hydpy/__init__.py +275 -0
  2. hydpy/aliases.py +2554 -0
  3. hydpy/auxs/__init__.py +0 -0
  4. hydpy/auxs/anntools.py +1305 -0
  5. hydpy/auxs/armatools.py +883 -0
  6. hydpy/auxs/calibtools.py +3337 -0
  7. hydpy/auxs/interptools.py +1094 -0
  8. hydpy/auxs/iuhtools.py +543 -0
  9. hydpy/auxs/networktools.py +597 -0
  10. hydpy/auxs/ppolytools.py +809 -0
  11. hydpy/auxs/quadtools.py +61 -0
  12. hydpy/auxs/roottools.py +228 -0
  13. hydpy/auxs/smoothtools.py +273 -0
  14. hydpy/auxs/statstools.py +2125 -0
  15. hydpy/auxs/validtools.py +81 -0
  16. hydpy/conf/HydPyConfigBase.xsd +68637 -0
  17. hydpy/conf/HydPyConfigBase.xsdt +358 -0
  18. hydpy/conf/HydPyConfigMultipleRuns.xsd +25 -0
  19. hydpy/conf/HydPyConfigSingleRun.xsd +24 -0
  20. hydpy/conf/__init__.py +0 -0
  21. hydpy/conf/a_coefficients_explicit_lobatto_sequence.npy +0 -0
  22. hydpy/conf/support_points_for_smoothpar_logistic2.npy +0 -0
  23. hydpy/config.py +42 -0
  24. hydpy/core/__init__.py +0 -0
  25. hydpy/core/aliastools.py +214 -0
  26. hydpy/core/autodoctools.py +1947 -0
  27. hydpy/core/auxfiletools.py +1169 -0
  28. hydpy/core/devicetools.py +3810 -0
  29. hydpy/core/exceptiontools.py +269 -0
  30. hydpy/core/filetools.py +1985 -0
  31. hydpy/core/hydpytools.py +3089 -0
  32. hydpy/core/importtools.py +1398 -0
  33. hydpy/core/indextools.py +345 -0
  34. hydpy/core/itemtools.py +1849 -0
  35. hydpy/core/masktools.py +460 -0
  36. hydpy/core/modeltools.py +4868 -0
  37. hydpy/core/netcdftools.py +2683 -0
  38. hydpy/core/objecttools.py +2023 -0
  39. hydpy/core/optiontools.py +1045 -0
  40. hydpy/core/parametertools.py +4674 -0
  41. hydpy/core/printtools.py +222 -0
  42. hydpy/core/propertytools.py +643 -0
  43. hydpy/core/pubtools.py +254 -0
  44. hydpy/core/selectiontools.py +1571 -0
  45. hydpy/core/sequencetools.py +4476 -0
  46. hydpy/core/seriestools.py +339 -0
  47. hydpy/core/testtools.py +2483 -0
  48. hydpy/core/timetools.py +3567 -0
  49. hydpy/core/typingtools.py +333 -0
  50. hydpy/core/variabletools.py +2615 -0
  51. hydpy/cythons/__init__.py +24 -0
  52. hydpy/cythons/annutils.pxd +33 -0
  53. hydpy/cythons/annutils.pyi +25 -0
  54. hydpy/cythons/annutils.pyx +120 -0
  55. hydpy/cythons/autogen/__init__.py +0 -0
  56. hydpy/cythons/autogen/annutils.cp313-win_amd64.pyd +0 -0
  57. hydpy/cythons/autogen/annutils.pxd +42 -0
  58. hydpy/cythons/autogen/annutils.pyx +129 -0
  59. hydpy/cythons/autogen/c_arma.cp313-win_amd64.pyd +0 -0
  60. hydpy/cythons/autogen/c_arma.pxd +179 -0
  61. hydpy/cythons/autogen/c_arma.pyx +356 -0
  62. hydpy/cythons/autogen/c_arma_rimorido.cp313-win_amd64.pyd +0 -0
  63. hydpy/cythons/autogen/c_arma_rimorido.pxd +179 -0
  64. hydpy/cythons/autogen/c_arma_rimorido.pyx +356 -0
  65. hydpy/cythons/autogen/c_conv.cp313-win_amd64.pyd +0 -0
  66. hydpy/cythons/autogen/c_conv.pxd +198 -0
  67. hydpy/cythons/autogen/c_conv.pyx +491 -0
  68. hydpy/cythons/autogen/c_conv_idw.cp313-win_amd64.pyd +0 -0
  69. hydpy/cythons/autogen/c_conv_idw.pxd +124 -0
  70. hydpy/cythons/autogen/c_conv_idw.pyx +264 -0
  71. hydpy/cythons/autogen/c_conv_idw_ed.cp313-win_amd64.pyd +0 -0
  72. hydpy/cythons/autogen/c_conv_idw_ed.pxd +197 -0
  73. hydpy/cythons/autogen/c_conv_idw_ed.pyx +481 -0
  74. hydpy/cythons/autogen/c_conv_nn.cp313-win_amd64.pyd +0 -0
  75. hydpy/cythons/autogen/c_conv_nn.pxd +120 -0
  76. hydpy/cythons/autogen/c_conv_nn.pyx +224 -0
  77. hydpy/cythons/autogen/c_dam.cp313-win_amd64.pyd +0 -0
  78. hydpy/cythons/autogen/c_dam.pxd +805 -0
  79. hydpy/cythons/autogen/c_dam.pyx +1477 -0
  80. hydpy/cythons/autogen/c_dam_llake.cp313-win_amd64.pyd +0 -0
  81. hydpy/cythons/autogen/c_dam_llake.pxd +364 -0
  82. hydpy/cythons/autogen/c_dam_llake.pyx +705 -0
  83. hydpy/cythons/autogen/c_dam_lreservoir.cp313-win_amd64.pyd +0 -0
  84. hydpy/cythons/autogen/c_dam_lreservoir.pxd +365 -0
  85. hydpy/cythons/autogen/c_dam_lreservoir.pyx +708 -0
  86. hydpy/cythons/autogen/c_dam_lretention.cp313-win_amd64.pyd +0 -0
  87. hydpy/cythons/autogen/c_dam_lretention.pxd +340 -0
  88. hydpy/cythons/autogen/c_dam_lretention.pyx +625 -0
  89. hydpy/cythons/autogen/c_dam_pump.cp313-win_amd64.pyd +0 -0
  90. hydpy/cythons/autogen/c_dam_pump.pxd +402 -0
  91. hydpy/cythons/autogen/c_dam_pump.pyx +724 -0
  92. hydpy/cythons/autogen/c_dam_pump_sluice.cp313-win_amd64.pyd +0 -0
  93. hydpy/cythons/autogen/c_dam_pump_sluice.pxd +452 -0
  94. hydpy/cythons/autogen/c_dam_pump_sluice.pyx +829 -0
  95. hydpy/cythons/autogen/c_dam_sluice.cp313-win_amd64.pyd +0 -0
  96. hydpy/cythons/autogen/c_dam_sluice.pxd +404 -0
  97. hydpy/cythons/autogen/c_dam_sluice.pyx +726 -0
  98. hydpy/cythons/autogen/c_dam_v001.cp313-win_amd64.pyd +0 -0
  99. hydpy/cythons/autogen/c_dam_v001.pxd +452 -0
  100. hydpy/cythons/autogen/c_dam_v001.pyx +816 -0
  101. hydpy/cythons/autogen/c_dam_v002.cp313-win_amd64.pyd +0 -0
  102. hydpy/cythons/autogen/c_dam_v002.pxd +394 -0
  103. hydpy/cythons/autogen/c_dam_v002.pyx +703 -0
  104. hydpy/cythons/autogen/c_dam_v003.cp313-win_amd64.pyd +0 -0
  105. hydpy/cythons/autogen/c_dam_v003.pxd +417 -0
  106. hydpy/cythons/autogen/c_dam_v003.pyx +744 -0
  107. hydpy/cythons/autogen/c_dam_v004.cp313-win_amd64.pyd +0 -0
  108. hydpy/cythons/autogen/c_dam_v004.pxd +486 -0
  109. hydpy/cythons/autogen/c_dam_v004.pyx +891 -0
  110. hydpy/cythons/autogen/c_dam_v005.cp313-win_amd64.pyd +0 -0
  111. hydpy/cythons/autogen/c_dam_v005.pxd +524 -0
  112. hydpy/cythons/autogen/c_dam_v005.pyx +928 -0
  113. hydpy/cythons/autogen/c_dummy.cp313-win_amd64.pyd +0 -0
  114. hydpy/cythons/autogen/c_dummy.pxd +151 -0
  115. hydpy/cythons/autogen/c_dummy.pyx +263 -0
  116. hydpy/cythons/autogen/c_dummy_interceptedwater.cp313-win_amd64.pyd +0 -0
  117. hydpy/cythons/autogen/c_dummy_interceptedwater.pxd +69 -0
  118. hydpy/cythons/autogen/c_dummy_interceptedwater.pyx +104 -0
  119. hydpy/cythons/autogen/c_dummy_node2node.cp313-win_amd64.pyd +0 -0
  120. hydpy/cythons/autogen/c_dummy_node2node.pxd +89 -0
  121. hydpy/cythons/autogen/c_dummy_node2node.pyx +148 -0
  122. hydpy/cythons/autogen/c_dummy_snowalbedo.cp313-win_amd64.pyd +0 -0
  123. hydpy/cythons/autogen/c_dummy_snowalbedo.pxd +69 -0
  124. hydpy/cythons/autogen/c_dummy_snowalbedo.pyx +104 -0
  125. hydpy/cythons/autogen/c_dummy_snowcover.cp313-win_amd64.pyd +0 -0
  126. hydpy/cythons/autogen/c_dummy_snowcover.pxd +69 -0
  127. hydpy/cythons/autogen/c_dummy_snowcover.pyx +104 -0
  128. hydpy/cythons/autogen/c_dummy_snowycanopy.cp313-win_amd64.pyd +0 -0
  129. hydpy/cythons/autogen/c_dummy_snowycanopy.pxd +69 -0
  130. hydpy/cythons/autogen/c_dummy_snowycanopy.pyx +104 -0
  131. hydpy/cythons/autogen/c_dummy_soilwater.cp313-win_amd64.pyd +0 -0
  132. hydpy/cythons/autogen/c_dummy_soilwater.pxd +69 -0
  133. hydpy/cythons/autogen/c_dummy_soilwater.pyx +104 -0
  134. hydpy/cythons/autogen/c_evap.cp313-win_amd64.pyd +0 -0
  135. hydpy/cythons/autogen/c_evap.pxd +1029 -0
  136. hydpy/cythons/autogen/c_evap.pyx +2601 -0
  137. hydpy/cythons/autogen/c_evap_aet_hbv96.cp313-win_amd64.pyd +0 -0
  138. hydpy/cythons/autogen/c_evap_aet_hbv96.pxd +227 -0
  139. hydpy/cythons/autogen/c_evap_aet_hbv96.pyx +584 -0
  140. hydpy/cythons/autogen/c_evap_aet_minhas.cp313-win_amd64.pyd +0 -0
  141. hydpy/cythons/autogen/c_evap_aet_minhas.pxd +193 -0
  142. hydpy/cythons/autogen/c_evap_aet_minhas.pyx +478 -0
  143. hydpy/cythons/autogen/c_evap_aet_morsim.cp313-win_amd64.pyd +0 -0
  144. hydpy/cythons/autogen/c_evap_aet_morsim.pxd +681 -0
  145. hydpy/cythons/autogen/c_evap_aet_morsim.pyx +1642 -0
  146. hydpy/cythons/autogen/c_evap_pet_ambav1.cp313-win_amd64.pyd +0 -0
  147. hydpy/cythons/autogen/c_evap_pet_ambav1.pxd +532 -0
  148. hydpy/cythons/autogen/c_evap_pet_ambav1.pyx +1296 -0
  149. hydpy/cythons/autogen/c_evap_pet_hbv96.cp313-win_amd64.pyd +0 -0
  150. hydpy/cythons/autogen/c_evap_pet_hbv96.pxd +179 -0
  151. hydpy/cythons/autogen/c_evap_pet_hbv96.pyx +328 -0
  152. hydpy/cythons/autogen/c_evap_pet_m.cp313-win_amd64.pyd +0 -0
  153. hydpy/cythons/autogen/c_evap_pet_m.pxd +124 -0
  154. hydpy/cythons/autogen/c_evap_pet_m.pyx +214 -0
  155. hydpy/cythons/autogen/c_evap_pet_mlc.cp313-win_amd64.pyd +0 -0
  156. hydpy/cythons/autogen/c_evap_pet_mlc.pxd +126 -0
  157. hydpy/cythons/autogen/c_evap_pet_mlc.pyx +214 -0
  158. hydpy/cythons/autogen/c_evap_ret_fao56.cp313-win_amd64.pyd +0 -0
  159. hydpy/cythons/autogen/c_evap_ret_fao56.pxd +305 -0
  160. hydpy/cythons/autogen/c_evap_ret_fao56.pyx +624 -0
  161. hydpy/cythons/autogen/c_evap_ret_io.cp313-win_amd64.pyd +0 -0
  162. hydpy/cythons/autogen/c_evap_ret_io.pxd +112 -0
  163. hydpy/cythons/autogen/c_evap_ret_io.pyx +176 -0
  164. hydpy/cythons/autogen/c_evap_ret_tw2002.cp313-win_amd64.pyd +0 -0
  165. hydpy/cythons/autogen/c_evap_ret_tw2002.pxd +139 -0
  166. hydpy/cythons/autogen/c_evap_ret_tw2002.pyx +273 -0
  167. hydpy/cythons/autogen/c_exch.cp313-win_amd64.pyd +0 -0
  168. hydpy/cythons/autogen/c_exch.pxd +230 -0
  169. hydpy/cythons/autogen/c_exch.pyx +462 -0
  170. hydpy/cythons/autogen/c_exch_branch_hbv96.cp313-win_amd64.pyd +0 -0
  171. hydpy/cythons/autogen/c_exch_branch_hbv96.pxd +134 -0
  172. hydpy/cythons/autogen/c_exch_branch_hbv96.pyx +255 -0
  173. hydpy/cythons/autogen/c_exch_waterlevel.cp313-win_amd64.pyd +0 -0
  174. hydpy/cythons/autogen/c_exch_waterlevel.pxd +54 -0
  175. hydpy/cythons/autogen/c_exch_waterlevel.pyx +78 -0
  176. hydpy/cythons/autogen/c_exch_weir_hbv96.cp313-win_amd64.pyd +0 -0
  177. hydpy/cythons/autogen/c_exch_weir_hbv96.pxd +156 -0
  178. hydpy/cythons/autogen/c_exch_weir_hbv96.pyx +282 -0
  179. hydpy/cythons/autogen/c_ga.cp313-win_amd64.pyd +0 -0
  180. hydpy/cythons/autogen/c_ga.pxd +353 -0
  181. hydpy/cythons/autogen/c_ga.pyx +1204 -0
  182. hydpy/cythons/autogen/c_ga_garto.cp313-win_amd64.pyd +0 -0
  183. hydpy/cythons/autogen/c_ga_garto.pxd +330 -0
  184. hydpy/cythons/autogen/c_ga_garto.pyx +1105 -0
  185. hydpy/cythons/autogen/c_ga_garto_submodel1.cp313-win_amd64.pyd +0 -0
  186. hydpy/cythons/autogen/c_ga_garto_submodel1.pxd +236 -0
  187. hydpy/cythons/autogen/c_ga_garto_submodel1.pyx +944 -0
  188. hydpy/cythons/autogen/c_gland.cp313-win_amd64.pyd +0 -0
  189. hydpy/cythons/autogen/c_gland.pxd +437 -0
  190. hydpy/cythons/autogen/c_gland.pyx +726 -0
  191. hydpy/cythons/autogen/c_gland_gr4.cp313-win_amd64.pyd +0 -0
  192. hydpy/cythons/autogen/c_gland_gr4.pxd +382 -0
  193. hydpy/cythons/autogen/c_gland_gr4.pyx +605 -0
  194. hydpy/cythons/autogen/c_gland_gr5.cp313-win_amd64.pyd +0 -0
  195. hydpy/cythons/autogen/c_gland_gr5.pxd +368 -0
  196. hydpy/cythons/autogen/c_gland_gr5.pyx +568 -0
  197. hydpy/cythons/autogen/c_gland_gr6.cp313-win_amd64.pyd +0 -0
  198. hydpy/cythons/autogen/c_gland_gr6.pxd +420 -0
  199. hydpy/cythons/autogen/c_gland_gr6.pyx +673 -0
  200. hydpy/cythons/autogen/c_hland.cp313-win_amd64.pyd +0 -0
  201. hydpy/cythons/autogen/c_hland.pxd +855 -0
  202. hydpy/cythons/autogen/c_hland.pyx +2486 -0
  203. hydpy/cythons/autogen/c_hland_96.cp313-win_amd64.pyd +0 -0
  204. hydpy/cythons/autogen/c_hland_96.pxd +631 -0
  205. hydpy/cythons/autogen/c_hland_96.pyx +1724 -0
  206. hydpy/cythons/autogen/c_hland_96c.cp313-win_amd64.pyd +0 -0
  207. hydpy/cythons/autogen/c_hland_96c.pxd +621 -0
  208. hydpy/cythons/autogen/c_hland_96c.pyx +1822 -0
  209. hydpy/cythons/autogen/c_hland_96p.cp313-win_amd64.pyd +0 -0
  210. hydpy/cythons/autogen/c_hland_96p.pxd +683 -0
  211. hydpy/cythons/autogen/c_hland_96p.pyx +1911 -0
  212. hydpy/cythons/autogen/c_kinw.cp313-win_amd64.pyd +0 -0
  213. hydpy/cythons/autogen/c_kinw.pxd +509 -0
  214. hydpy/cythons/autogen/c_kinw.pyx +965 -0
  215. hydpy/cythons/autogen/c_kinw_williams.cp313-win_amd64.pyd +0 -0
  216. hydpy/cythons/autogen/c_kinw_williams.pxd +409 -0
  217. hydpy/cythons/autogen/c_kinw_williams.pyx +763 -0
  218. hydpy/cythons/autogen/c_kinw_williams_ext.cp313-win_amd64.pyd +0 -0
  219. hydpy/cythons/autogen/c_kinw_williams_ext.pxd +220 -0
  220. hydpy/cythons/autogen/c_kinw_williams_ext.pyx +440 -0
  221. hydpy/cythons/autogen/c_lland.cp313-win_amd64.pyd +0 -0
  222. hydpy/cythons/autogen/c_lland.pxd +1386 -0
  223. hydpy/cythons/autogen/c_lland.pyx +3679 -0
  224. hydpy/cythons/autogen/c_lland_dd.cp313-win_amd64.pyd +0 -0
  225. hydpy/cythons/autogen/c_lland_dd.pxd +679 -0
  226. hydpy/cythons/autogen/c_lland_dd.pyx +1719 -0
  227. hydpy/cythons/autogen/c_lland_knauf.cp313-win_amd64.pyd +0 -0
  228. hydpy/cythons/autogen/c_lland_knauf.pxd +1096 -0
  229. hydpy/cythons/autogen/c_lland_knauf.pyx +2784 -0
  230. hydpy/cythons/autogen/c_lland_knauf_ic.cp313-win_amd64.pyd +0 -0
  231. hydpy/cythons/autogen/c_lland_knauf_ic.pxd +1369 -0
  232. hydpy/cythons/autogen/c_lland_knauf_ic.pyx +3625 -0
  233. hydpy/cythons/autogen/c_meteo.cp313-win_amd64.pyd +0 -0
  234. hydpy/cythons/autogen/c_meteo.pxd +469 -0
  235. hydpy/cythons/autogen/c_meteo.pyx +879 -0
  236. hydpy/cythons/autogen/c_meteo_clear_glob_io.cp313-win_amd64.pyd +0 -0
  237. hydpy/cythons/autogen/c_meteo_clear_glob_io.pxd +75 -0
  238. hydpy/cythons/autogen/c_meteo_clear_glob_io.pyx +107 -0
  239. hydpy/cythons/autogen/c_meteo_glob_fao56.cp313-win_amd64.pyd +0 -0
  240. hydpy/cythons/autogen/c_meteo_glob_fao56.pxd +209 -0
  241. hydpy/cythons/autogen/c_meteo_glob_fao56.pyx +339 -0
  242. hydpy/cythons/autogen/c_meteo_glob_io.cp313-win_amd64.pyd +0 -0
  243. hydpy/cythons/autogen/c_meteo_glob_io.pxd +63 -0
  244. hydpy/cythons/autogen/c_meteo_glob_io.pyx +91 -0
  245. hydpy/cythons/autogen/c_meteo_glob_morsim.cp313-win_amd64.pyd +0 -0
  246. hydpy/cythons/autogen/c_meteo_glob_morsim.pxd +289 -0
  247. hydpy/cythons/autogen/c_meteo_glob_morsim.pyx +527 -0
  248. hydpy/cythons/autogen/c_meteo_precip_io.cp313-win_amd64.pyd +0 -0
  249. hydpy/cythons/autogen/c_meteo_precip_io.pxd +112 -0
  250. hydpy/cythons/autogen/c_meteo_precip_io.pyx +176 -0
  251. hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.cp313-win_amd64.pyd +0 -0
  252. hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pxd +87 -0
  253. hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pyx +123 -0
  254. hydpy/cythons/autogen/c_meteo_sun_fao56.cp313-win_amd64.pyd +0 -0
  255. hydpy/cythons/autogen/c_meteo_sun_fao56.pxd +209 -0
  256. hydpy/cythons/autogen/c_meteo_sun_fao56.pyx +343 -0
  257. hydpy/cythons/autogen/c_meteo_sun_morsim.cp313-win_amd64.pyd +0 -0
  258. hydpy/cythons/autogen/c_meteo_sun_morsim.pxd +286 -0
  259. hydpy/cythons/autogen/c_meteo_sun_morsim.pyx +519 -0
  260. hydpy/cythons/autogen/c_meteo_temp_io.cp313-win_amd64.pyd +0 -0
  261. hydpy/cythons/autogen/c_meteo_temp_io.pxd +112 -0
  262. hydpy/cythons/autogen/c_meteo_temp_io.pyx +176 -0
  263. hydpy/cythons/autogen/c_musk.cp313-win_amd64.pyd +0 -0
  264. hydpy/cythons/autogen/c_musk.pxd +282 -0
  265. hydpy/cythons/autogen/c_musk.pyx +605 -0
  266. hydpy/cythons/autogen/c_musk_classic.cp313-win_amd64.pyd +0 -0
  267. hydpy/cythons/autogen/c_musk_classic.pxd +138 -0
  268. hydpy/cythons/autogen/c_musk_classic.pyx +226 -0
  269. hydpy/cythons/autogen/c_musk_mct.cp313-win_amd64.pyd +0 -0
  270. hydpy/cythons/autogen/c_musk_mct.pxd +282 -0
  271. hydpy/cythons/autogen/c_musk_mct.pyx +609 -0
  272. hydpy/cythons/autogen/c_rconc.cp313-win_amd64.pyd +0 -0
  273. hydpy/cythons/autogen/c_rconc.pxd +119 -0
  274. hydpy/cythons/autogen/c_rconc.pyx +174 -0
  275. hydpy/cythons/autogen/c_rconc_nash.cp313-win_amd64.pyd +0 -0
  276. hydpy/cythons/autogen/c_rconc_nash.pxd +111 -0
  277. hydpy/cythons/autogen/c_rconc_nash.pyx +185 -0
  278. hydpy/cythons/autogen/c_rconc_uh.cp313-win_amd64.pyd +0 -0
  279. hydpy/cythons/autogen/c_rconc_uh.pxd +92 -0
  280. hydpy/cythons/autogen/c_rconc_uh.pyx +125 -0
  281. hydpy/cythons/autogen/c_sw1d.cp313-win_amd64.pyd +0 -0
  282. hydpy/cythons/autogen/c_sw1d.pxd +511 -0
  283. hydpy/cythons/autogen/c_sw1d.pyx +1263 -0
  284. hydpy/cythons/autogen/c_sw1d_channel.cp313-win_amd64.pyd +0 -0
  285. hydpy/cythons/autogen/c_sw1d_channel.pxd +119 -0
  286. hydpy/cythons/autogen/c_sw1d_channel.pyx +300 -0
  287. hydpy/cythons/autogen/c_sw1d_gate_out.cp313-win_amd64.pyd +0 -0
  288. hydpy/cythons/autogen/c_sw1d_gate_out.pxd +240 -0
  289. hydpy/cythons/autogen/c_sw1d_gate_out.pyx +476 -0
  290. hydpy/cythons/autogen/c_sw1d_lias.cp313-win_amd64.pyd +0 -0
  291. hydpy/cythons/autogen/c_sw1d_lias.pxd +320 -0
  292. hydpy/cythons/autogen/c_sw1d_lias.pyx +619 -0
  293. hydpy/cythons/autogen/c_sw1d_lias_sluice.cp313-win_amd64.pyd +0 -0
  294. hydpy/cythons/autogen/c_sw1d_lias_sluice.pxd +325 -0
  295. hydpy/cythons/autogen/c_sw1d_lias_sluice.pyx +644 -0
  296. hydpy/cythons/autogen/c_sw1d_network.cp313-win_amd64.pyd +0 -0
  297. hydpy/cythons/autogen/c_sw1d_network.pxd +90 -0
  298. hydpy/cythons/autogen/c_sw1d_network.pyx +246 -0
  299. hydpy/cythons/autogen/c_sw1d_pump.cp313-win_amd64.pyd +0 -0
  300. hydpy/cythons/autogen/c_sw1d_pump.pxd +256 -0
  301. hydpy/cythons/autogen/c_sw1d_pump.pyx +502 -0
  302. hydpy/cythons/autogen/c_sw1d_q_in.cp313-win_amd64.pyd +0 -0
  303. hydpy/cythons/autogen/c_sw1d_q_in.pxd +224 -0
  304. hydpy/cythons/autogen/c_sw1d_q_in.pyx +383 -0
  305. hydpy/cythons/autogen/c_sw1d_q_out.cp313-win_amd64.pyd +0 -0
  306. hydpy/cythons/autogen/c_sw1d_q_out.pxd +224 -0
  307. hydpy/cythons/autogen/c_sw1d_q_out.pyx +383 -0
  308. hydpy/cythons/autogen/c_sw1d_storage.cp313-win_amd64.pyd +0 -0
  309. hydpy/cythons/autogen/c_sw1d_storage.pxd +193 -0
  310. hydpy/cythons/autogen/c_sw1d_storage.pyx +349 -0
  311. hydpy/cythons/autogen/c_sw1d_weir_out.cp313-win_amd64.pyd +0 -0
  312. hydpy/cythons/autogen/c_sw1d_weir_out.pxd +212 -0
  313. hydpy/cythons/autogen/c_sw1d_weir_out.pyx +404 -0
  314. hydpy/cythons/autogen/c_test.cp313-win_amd64.pyd +0 -0
  315. hydpy/cythons/autogen/c_test.pxd +175 -0
  316. hydpy/cythons/autogen/c_test.pyx +348 -0
  317. hydpy/cythons/autogen/c_test_discontinous.cp313-win_amd64.pyd +0 -0
  318. hydpy/cythons/autogen/c_test_discontinous.pxd +146 -0
  319. hydpy/cythons/autogen/c_test_discontinous.pyx +256 -0
  320. hydpy/cythons/autogen/c_test_stiff0d.cp313-win_amd64.pyd +0 -0
  321. hydpy/cythons/autogen/c_test_stiff0d.pxd +146 -0
  322. hydpy/cythons/autogen/c_test_stiff0d.pyx +250 -0
  323. hydpy/cythons/autogen/c_test_stiff1d.cp313-win_amd64.pyd +0 -0
  324. hydpy/cythons/autogen/c_test_stiff1d.pxd +145 -0
  325. hydpy/cythons/autogen/c_test_stiff1d.pyx +294 -0
  326. hydpy/cythons/autogen/c_whmod.cp313-win_amd64.pyd +0 -0
  327. hydpy/cythons/autogen/c_whmod.pxd +482 -0
  328. hydpy/cythons/autogen/c_whmod.pyx +1156 -0
  329. hydpy/cythons/autogen/c_whmod_rural.cp313-win_amd64.pyd +0 -0
  330. hydpy/cythons/autogen/c_whmod_rural.pxd +411 -0
  331. hydpy/cythons/autogen/c_whmod_rural.pyx +982 -0
  332. hydpy/cythons/autogen/c_whmod_urban.cp313-win_amd64.pyd +0 -0
  333. hydpy/cythons/autogen/c_whmod_urban.pxd +482 -0
  334. hydpy/cythons/autogen/c_whmod_urban.pyx +1155 -0
  335. hydpy/cythons/autogen/c_wland.cp313-win_amd64.pyd +0 -0
  336. hydpy/cythons/autogen/c_wland.pxd +842 -0
  337. hydpy/cythons/autogen/c_wland.pyx +1890 -0
  338. hydpy/cythons/autogen/c_wland_gd.cp313-win_amd64.pyd +0 -0
  339. hydpy/cythons/autogen/c_wland_gd.pxd +829 -0
  340. hydpy/cythons/autogen/c_wland_gd.pyx +1847 -0
  341. hydpy/cythons/autogen/c_wland_wag.cp313-win_amd64.pyd +0 -0
  342. hydpy/cythons/autogen/c_wland_wag.pxd +810 -0
  343. hydpy/cythons/autogen/c_wland_wag.pyx +1780 -0
  344. hydpy/cythons/autogen/c_wq.cp313-win_amd64.pyd +0 -0
  345. hydpy/cythons/autogen/c_wq.pxd +275 -0
  346. hydpy/cythons/autogen/c_wq.pyx +652 -0
  347. hydpy/cythons/autogen/c_wq_trapeze.cp313-win_amd64.pyd +0 -0
  348. hydpy/cythons/autogen/c_wq_trapeze.pxd +170 -0
  349. hydpy/cythons/autogen/c_wq_trapeze.pyx +400 -0
  350. hydpy/cythons/autogen/c_wq_trapeze_strickler.cp313-win_amd64.pyd +0 -0
  351. hydpy/cythons/autogen/c_wq_trapeze_strickler.pxd +243 -0
  352. hydpy/cythons/autogen/c_wq_trapeze_strickler.pyx +578 -0
  353. hydpy/cythons/autogen/c_wq_walrus.cp313-win_amd64.pyd +0 -0
  354. hydpy/cythons/autogen/c_wq_walrus.pxd +61 -0
  355. hydpy/cythons/autogen/c_wq_walrus.pyx +82 -0
  356. hydpy/cythons/autogen/configutils.cp313-win_amd64.pyd +0 -0
  357. hydpy/cythons/autogen/configutils.pxd +17 -0
  358. hydpy/cythons/autogen/configutils.pyx +119 -0
  359. hydpy/cythons/autogen/interfaceutils.cp313-win_amd64.pyd +0 -0
  360. hydpy/cythons/autogen/interfaceutils.pxd +31 -0
  361. hydpy/cythons/autogen/interfaceutils.pyx +82 -0
  362. hydpy/cythons/autogen/interputils.cp313-win_amd64.pyd +0 -0
  363. hydpy/cythons/autogen/interputils.pxd +42 -0
  364. hydpy/cythons/autogen/interputils.pyx +118 -0
  365. hydpy/cythons/autogen/masterinterface.cp313-win_amd64.pyd +0 -0
  366. hydpy/cythons/autogen/masterinterface.pxd +153 -0
  367. hydpy/cythons/autogen/masterinterface.pyx +222 -0
  368. hydpy/cythons/autogen/pointerutils.cp313-win_amd64.pyd +0 -0
  369. hydpy/cythons/autogen/pointerutils.pxd +31 -0
  370. hydpy/cythons/autogen/pointerutils.pyx +650 -0
  371. hydpy/cythons/autogen/ppolyutils.cp313-win_amd64.pyd +0 -0
  372. hydpy/cythons/autogen/ppolyutils.pxd +35 -0
  373. hydpy/cythons/autogen/ppolyutils.pyx +59 -0
  374. hydpy/cythons/autogen/quadutils.cp313-win_amd64.pyd +0 -0
  375. hydpy/cythons/autogen/quadutils.pxd +26 -0
  376. hydpy/cythons/autogen/quadutils.pyx +973 -0
  377. hydpy/cythons/autogen/rootutils.cp313-win_amd64.pyd +0 -0
  378. hydpy/cythons/autogen/rootutils.pxd +28 -0
  379. hydpy/cythons/autogen/rootutils.pyx +109 -0
  380. hydpy/cythons/autogen/sequenceutils.cp313-win_amd64.pyd +0 -0
  381. hydpy/cythons/autogen/sequenceutils.pxd +45 -0
  382. hydpy/cythons/autogen/sequenceutils.pyx +101 -0
  383. hydpy/cythons/autogen/smoothutils.cp313-win_amd64.pyd +0 -0
  384. hydpy/cythons/autogen/smoothutils.pxd +29 -0
  385. hydpy/cythons/autogen/smoothutils.pyx +833 -0
  386. hydpy/cythons/configutils.pxd +8 -0
  387. hydpy/cythons/configutils.pyi +5 -0
  388. hydpy/cythons/configutils.pyx +110 -0
  389. hydpy/cythons/interfaceutils.pxd +22 -0
  390. hydpy/cythons/interfaceutils.pyi +15 -0
  391. hydpy/cythons/interfaceutils.pyx +73 -0
  392. hydpy/cythons/interputils.pxd +33 -0
  393. hydpy/cythons/interputils.pyi +32 -0
  394. hydpy/cythons/interputils.pyx +109 -0
  395. hydpy/cythons/modelutils.py +2990 -0
  396. hydpy/cythons/pointerutils.pxd +22 -0
  397. hydpy/cythons/pointerutils.pyi +89 -0
  398. hydpy/cythons/pointerutils.pyx +641 -0
  399. hydpy/cythons/ppolyutils.pxd +26 -0
  400. hydpy/cythons/ppolyutils.pyi +21 -0
  401. hydpy/cythons/ppolyutils.pyx +50 -0
  402. hydpy/cythons/quadutils.pxd +17 -0
  403. hydpy/cythons/quadutils.pyi +13 -0
  404. hydpy/cythons/quadutils.pyx +964 -0
  405. hydpy/cythons/rootutils.pxd +19 -0
  406. hydpy/cythons/rootutils.pyi +21 -0
  407. hydpy/cythons/rootutils.pyx +100 -0
  408. hydpy/cythons/sequenceutils.pxd +36 -0
  409. hydpy/cythons/sequenceutils.pyi +7 -0
  410. hydpy/cythons/sequenceutils.pyx +92 -0
  411. hydpy/cythons/smoothutils.pxd +20 -0
  412. hydpy/cythons/smoothutils.pyi +15 -0
  413. hydpy/cythons/smoothutils.pyx +824 -0
  414. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_dill_assl.py +13 -0
  415. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_kalk.py +13 -0
  416. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_leun.py +14 -0
  417. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_marb.py +13 -0
  418. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_dill_assl_lahn_leun.py +5 -0
  419. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_leun_lahn_kalk.py +5 -0
  420. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_marb_lahn_leun.py +5 -0
  421. hydpy/data/HydPy-H-Lahn/control/default/land.py +9 -0
  422. hydpy/data/HydPy-H-Lahn/control/default/land_dill_assl.py +57 -0
  423. hydpy/data/HydPy-H-Lahn/control/default/land_lahn_kalk.py +57 -0
  424. hydpy/data/HydPy-H-Lahn/control/default/land_lahn_leun.py +56 -0
  425. hydpy/data/HydPy-H-Lahn/control/default/land_lahn_marb.py +57 -0
  426. hydpy/data/HydPy-H-Lahn/control/default/stream_dill_assl_lahn_leun.py +7 -0
  427. hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_leun_lahn_kalk.py +7 -0
  428. hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_marb_lahn_leun.py +7 -0
  429. hydpy/data/HydPy-H-Lahn/multiple_runs.xml +309 -0
  430. hydpy/data/HydPy-H-Lahn/multiple_runs_alpha.xml +71 -0
  431. hydpy/data/HydPy-H-Lahn/network/default/headwaters.py +11 -0
  432. hydpy/data/HydPy-H-Lahn/network/default/nonheadwaters.py +11 -0
  433. hydpy/data/HydPy-H-Lahn/network/default/streams.py +8 -0
  434. hydpy/data/HydPy-H-Lahn/series/default/dill_assl_obs_q.asc +11387 -0
  435. hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalairtemperature.nc +0 -0
  436. hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalevapotranspiration.nc +0 -0
  437. hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_p.nc +0 -0
  438. hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_t.nc +0 -0
  439. hydpy/data/HydPy-H-Lahn/series/default/lahn_kalk_obs_q.asc +11387 -0
  440. hydpy/data/HydPy-H-Lahn/series/default/lahn_leun_obs_q.asc +11387 -0
  441. hydpy/data/HydPy-H-Lahn/series/default/lahn_marb_obs_q.asc +11387 -0
  442. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  443. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  444. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_p.asc +11387 -0
  445. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_t.asc +11387 -0
  446. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  447. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  448. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_p.asc +11387 -0
  449. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_t.asc +11387 -0
  450. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  451. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  452. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_p.asc +11387 -0
  453. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_t.asc +11387 -0
  454. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  455. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  456. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_p.asc +11387 -0
  457. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_t.asc +11387 -0
  458. hydpy/data/HydPy-H-Lahn/series/default/obs_q.nc +0 -0
  459. hydpy/data/HydPy-H-Lahn/single_run.xml +152 -0
  460. hydpy/data/HydPy-H-Lahn/single_run.xmlt +143 -0
  461. hydpy/data/__init__.py +17 -0
  462. hydpy/docs/__init__.py +0 -0
  463. hydpy/docs/autofigs/__init__.py +0 -0
  464. hydpy/docs/bib/__init__.py +0 -0
  465. hydpy/docs/bib/refs.bib +566 -0
  466. hydpy/docs/combine_docversions.py +133 -0
  467. hydpy/docs/draw_model_sketches.py +1301 -0
  468. hydpy/docs/enable_autodoc.py +7 -0
  469. hydpy/docs/figs/HydPy-G-GR4.png +0 -0
  470. hydpy/docs/figs/HydPy-G-GR5.png +0 -0
  471. hydpy/docs/figs/HydPy-G-GR6.png +0 -0
  472. hydpy/docs/figs/HydPy-H-HBV96-COSERO.png +0 -0
  473. hydpy/docs/figs/HydPy-H-HBV96-PREVAH.png +0 -0
  474. hydpy/docs/figs/HydPy-H-HBV96.png +0 -0
  475. hydpy/docs/figs/HydPy-H-Lahn.png +0 -0
  476. hydpy/docs/figs/HydPy-KinW-Williams.png +0 -0
  477. hydpy/docs/figs/HydPy-L-DD.png +0 -0
  478. hydpy/docs/figs/HydPy-W-Wag.png +0 -0
  479. hydpy/docs/figs/HydPy_Logo.png +0 -0
  480. hydpy/docs/figs/HydPy_Logo_Text.png +0 -0
  481. hydpy/docs/figs/IDLE-editor.png +0 -0
  482. hydpy/docs/figs/IDLE-shell.png +0 -0
  483. hydpy/docs/figs/LAWA_river-basin-bumbers.png +0 -0
  484. hydpy/docs/figs/__init__.py +0 -0
  485. hydpy/docs/html_/__init__.py +0 -0
  486. hydpy/docs/polish_html.py +57 -0
  487. hydpy/docs/prepare.py +224 -0
  488. hydpy/docs/publish_docs.py +53 -0
  489. hydpy/docs/rst/HydPy-ARMA.rst +27 -0
  490. hydpy/docs/rst/HydPy-Conv.rst +22 -0
  491. hydpy/docs/rst/HydPy-Dam.rst +79 -0
  492. hydpy/docs/rst/HydPy-Dummy.rst +21 -0
  493. hydpy/docs/rst/HydPy-Evap.rst +26 -0
  494. hydpy/docs/rst/HydPy-Exch.rst +36 -0
  495. hydpy/docs/rst/HydPy-G.rst +40 -0
  496. hydpy/docs/rst/HydPy-GA.rst +34 -0
  497. hydpy/docs/rst/HydPy-H.rst +24 -0
  498. hydpy/docs/rst/HydPy-KinW.rst +32 -0
  499. hydpy/docs/rst/HydPy-L.rst +42 -0
  500. hydpy/docs/rst/HydPy-Meteo.rst +28 -0
  501. hydpy/docs/rst/HydPy-Musk.rst +21 -0
  502. hydpy/docs/rst/HydPy-Rconc.rst +17 -0
  503. hydpy/docs/rst/HydPy-SW1D.rst +49 -0
  504. hydpy/docs/rst/HydPy-Test.rst +19 -0
  505. hydpy/docs/rst/HydPy-W.rst +20 -0
  506. hydpy/docs/rst/HydPy-WHMod.rst +19 -0
  507. hydpy/docs/rst/HydPy-WQ.rst +20 -0
  508. hydpy/docs/rst/__init__.py +0 -0
  509. hydpy/docs/rst/additional_repositories.rst +40 -0
  510. hydpy/docs/rst/auxiliaries.rst +31 -0
  511. hydpy/docs/rst/continuous_integration.rst +75 -0
  512. hydpy/docs/rst/core.rst +75 -0
  513. hydpy/docs/rst/cythons.rst +47 -0
  514. hydpy/docs/rst/definitions.rst +506 -0
  515. hydpy/docs/rst/developer_guide.rst +54 -0
  516. hydpy/docs/rst/example_projects.rst +40 -0
  517. hydpy/docs/rst/execution.rst +22 -0
  518. hydpy/docs/rst/framework_tools.rst +56 -0
  519. hydpy/docs/rst/how_to_read_the_reference_manual.rst +156 -0
  520. hydpy/docs/rst/hydpydependencies.rst +55 -0
  521. hydpy/docs/rst/index.rst +125 -0
  522. hydpy/docs/rst/installation.rst +155 -0
  523. hydpy/docs/rst/model_families.rst +79 -0
  524. hydpy/docs/rst/model_overview.rst +291 -0
  525. hydpy/docs/rst/modelimports.rst +10 -0
  526. hydpy/docs/rst/options.rst +119 -0
  527. hydpy/docs/rst/programming_style.rst +572 -0
  528. hydpy/docs/rst/project_structure.rst +520 -0
  529. hydpy/docs/rst/quickstart.rst +304 -0
  530. hydpy/docs/rst/reference_manual.rst +29 -0
  531. hydpy/docs/rst/required_tools.rst +50 -0
  532. hydpy/docs/rst/simulation.rst +514 -0
  533. hydpy/docs/rst/submodel_interfaces.rst +32 -0
  534. hydpy/docs/rst/tests_and_documentation.rst +85 -0
  535. hydpy/docs/rst/user_guide.rst +38 -0
  536. hydpy/docs/rst/version_control.rst +116 -0
  537. hydpy/docs/rst/zbibliography.rst +8 -0
  538. hydpy/docs/sphinx/__init__.py +0 -0
  539. hydpy/docs/sphinx/_themes/basic_hydpy/changes/frameset.html +11 -0
  540. hydpy/docs/sphinx/_themes/basic_hydpy/changes/rstsource.html +15 -0
  541. hydpy/docs/sphinx/_themes/basic_hydpy/changes/versionchanges.html +33 -0
  542. hydpy/docs/sphinx/_themes/basic_hydpy/defindex.html +35 -0
  543. hydpy/docs/sphinx/_themes/basic_hydpy/domainindex.html +56 -0
  544. hydpy/docs/sphinx/_themes/basic_hydpy/genindex-single.html +63 -0
  545. hydpy/docs/sphinx/_themes/basic_hydpy/genindex-split.html +41 -0
  546. hydpy/docs/sphinx/_themes/basic_hydpy/genindex.html +76 -0
  547. hydpy/docs/sphinx/_themes/basic_hydpy/globaltoc.html +11 -0
  548. hydpy/docs/sphinx/_themes/basic_hydpy/layout.html +221 -0
  549. hydpy/docs/sphinx/_themes/basic_hydpy/localtoc.html +15 -0
  550. hydpy/docs/sphinx/_themes/basic_hydpy/opensearch.xml +13 -0
  551. hydpy/docs/sphinx/_themes/basic_hydpy/page.html +13 -0
  552. hydpy/docs/sphinx/_themes/basic_hydpy/relations.html +23 -0
  553. hydpy/docs/sphinx/_themes/basic_hydpy/search.html +65 -0
  554. hydpy/docs/sphinx/_themes/basic_hydpy/searchbox.html +21 -0
  555. hydpy/docs/sphinx/_themes/basic_hydpy/searchfield.html +23 -0
  556. hydpy/docs/sphinx/_themes/basic_hydpy/sourcelink.html +18 -0
  557. hydpy/docs/sphinx/_themes/basic_hydpy/static/basic.css_t +925 -0
  558. hydpy/docs/sphinx/_themes/basic_hydpy/static/doctools.js +156 -0
  559. hydpy/docs/sphinx/_themes/basic_hydpy/static/documentation_options.js_t +13 -0
  560. hydpy/docs/sphinx/_themes/basic_hydpy/static/file.png +0 -0
  561. hydpy/docs/sphinx/_themes/basic_hydpy/static/language_data.js_t +26 -0
  562. hydpy/docs/sphinx/_themes/basic_hydpy/static/minus.png +0 -0
  563. hydpy/docs/sphinx/_themes/basic_hydpy/static/plus.png +0 -0
  564. hydpy/docs/sphinx/_themes/basic_hydpy/static/searchtools.js +574 -0
  565. hydpy/docs/sphinx/_themes/basic_hydpy/static/sphinx_highlight.js +154 -0
  566. hydpy/docs/sphinx/_themes/basic_hydpy/theme.conf +16 -0
  567. hydpy/docs/sphinx/_themes/classic_hydpy/layout.html +23 -0
  568. hydpy/docs/sphinx/_themes/classic_hydpy/static/classic.css_t +358 -0
  569. hydpy/docs/sphinx/_themes/classic_hydpy/static/sidebar.js_t +72 -0
  570. hydpy/docs/sphinx/_themes/classic_hydpy/theme.conf +32 -0
  571. hydpy/docs/sphinx/conf.py +398 -0
  572. hydpy/docs/sphinx/defaultlinks_extension.py +36 -0
  573. hydpy/docs/sphinx/integrationtest_extension.py +104 -0
  574. hydpy/docs/sphinx/projectstructure_extension.py +58 -0
  575. hydpy/docs/sphinx/submodelgraph_extension.py +53 -0
  576. hydpy/exe/__init__.py +0 -0
  577. hydpy/exe/commandtools.py +651 -0
  578. hydpy/exe/hyd.py +277 -0
  579. hydpy/exe/modelimports.py +41 -0
  580. hydpy/exe/replacetools.py +216 -0
  581. hydpy/exe/servertools.py +2348 -0
  582. hydpy/exe/xmltools.py +3280 -0
  583. hydpy/interfaces/__init__.py +0 -0
  584. hydpy/interfaces/aetinterfaces.py +94 -0
  585. hydpy/interfaces/dischargeinterfaces.py +45 -0
  586. hydpy/interfaces/petinterfaces.py +117 -0
  587. hydpy/interfaces/precipinterfaces.py +42 -0
  588. hydpy/interfaces/radiationinterfaces.py +79 -0
  589. hydpy/interfaces/rconcinterfaces.py +30 -0
  590. hydpy/interfaces/routinginterfaces.py +324 -0
  591. hydpy/interfaces/soilinterfaces.py +96 -0
  592. hydpy/interfaces/stateinterfaces.py +98 -0
  593. hydpy/interfaces/tempinterfaces.py +46 -0
  594. hydpy/models/__init__.py +0 -0
  595. hydpy/models/arma/__init__.py +14 -0
  596. hydpy/models/arma/arma_control.py +383 -0
  597. hydpy/models/arma/arma_derived.py +204 -0
  598. hydpy/models/arma/arma_fluxes.py +41 -0
  599. hydpy/models/arma/arma_inlets.py +11 -0
  600. hydpy/models/arma/arma_logs.py +19 -0
  601. hydpy/models/arma/arma_model.py +461 -0
  602. hydpy/models/arma/arma_outlets.py +11 -0
  603. hydpy/models/arma_rimorido.py +381 -0
  604. hydpy/models/conv/__init__.py +12 -0
  605. hydpy/models/conv/conv_control.py +303 -0
  606. hydpy/models/conv/conv_derived.py +271 -0
  607. hydpy/models/conv/conv_fluxes.py +54 -0
  608. hydpy/models/conv/conv_inlets.py +11 -0
  609. hydpy/models/conv/conv_model.py +687 -0
  610. hydpy/models/conv/conv_outlets.py +11 -0
  611. hydpy/models/conv_idw.py +120 -0
  612. hydpy/models/conv_idw_ed.py +184 -0
  613. hydpy/models/conv_nn.py +112 -0
  614. hydpy/models/dam/__init__.py +16 -0
  615. hydpy/models/dam/dam_aides.py +17 -0
  616. hydpy/models/dam/dam_control.py +346 -0
  617. hydpy/models/dam/dam_derived.py +559 -0
  618. hydpy/models/dam/dam_factors.py +46 -0
  619. hydpy/models/dam/dam_fluxes.py +179 -0
  620. hydpy/models/dam/dam_inlets.py +29 -0
  621. hydpy/models/dam/dam_logs.py +52 -0
  622. hydpy/models/dam/dam_model.py +5011 -0
  623. hydpy/models/dam/dam_outlets.py +23 -0
  624. hydpy/models/dam/dam_receivers.py +41 -0
  625. hydpy/models/dam/dam_senders.py +23 -0
  626. hydpy/models/dam/dam_solver.py +75 -0
  627. hydpy/models/dam/dam_states.py +11 -0
  628. hydpy/models/dam_llake.py +499 -0
  629. hydpy/models/dam_lreservoir.py +548 -0
  630. hydpy/models/dam_lretention.py +343 -0
  631. hydpy/models/dam_pump.py +278 -0
  632. hydpy/models/dam_pump_sluice.py +339 -0
  633. hydpy/models/dam_sluice.py +319 -0
  634. hydpy/models/dam_v001.py +1127 -0
  635. hydpy/models/dam_v002.py +381 -0
  636. hydpy/models/dam_v003.py +422 -0
  637. hydpy/models/dam_v004.py +665 -0
  638. hydpy/models/dam_v005.py +479 -0
  639. hydpy/models/dummy/__init__.py +15 -0
  640. hydpy/models/dummy/dummy_control.py +22 -0
  641. hydpy/models/dummy/dummy_fluxes.py +11 -0
  642. hydpy/models/dummy/dummy_inlets.py +11 -0
  643. hydpy/models/dummy/dummy_inputs.py +41 -0
  644. hydpy/models/dummy/dummy_model.py +196 -0
  645. hydpy/models/dummy/dummy_outlets.py +11 -0
  646. hydpy/models/dummy_interceptedwater.py +85 -0
  647. hydpy/models/dummy_node2node.py +83 -0
  648. hydpy/models/dummy_snowalbedo.py +84 -0
  649. hydpy/models/dummy_snowcover.py +84 -0
  650. hydpy/models/dummy_snowycanopy.py +86 -0
  651. hydpy/models/dummy_soilwater.py +85 -0
  652. hydpy/models/evap/__init__.py +13 -0
  653. hydpy/models/evap/evap_control.py +354 -0
  654. hydpy/models/evap/evap_derived.py +236 -0
  655. hydpy/models/evap/evap_factors.py +188 -0
  656. hydpy/models/evap/evap_fixed.py +68 -0
  657. hydpy/models/evap/evap_fluxes.py +150 -0
  658. hydpy/models/evap/evap_inputs.py +54 -0
  659. hydpy/models/evap/evap_logs.py +91 -0
  660. hydpy/models/evap/evap_masks.py +48 -0
  661. hydpy/models/evap/evap_model.py +9170 -0
  662. hydpy/models/evap/evap_parameters.py +149 -0
  663. hydpy/models/evap/evap_sequences.py +32 -0
  664. hydpy/models/evap/evap_states.py +18 -0
  665. hydpy/models/evap_aet_hbv96.py +372 -0
  666. hydpy/models/evap_aet_minhas.py +331 -0
  667. hydpy/models/evap_aet_morsim.py +627 -0
  668. hydpy/models/evap_pet_ambav1.py +483 -0
  669. hydpy/models/evap_pet_hbv96.py +147 -0
  670. hydpy/models/evap_pet_m.py +94 -0
  671. hydpy/models/evap_pet_mlc.py +107 -0
  672. hydpy/models/evap_ret_fao56.py +265 -0
  673. hydpy/models/evap_ret_io.py +74 -0
  674. hydpy/models/evap_ret_tw2002.py +165 -0
  675. hydpy/models/exch/__init__.py +14 -0
  676. hydpy/models/exch/exch_control.py +262 -0
  677. hydpy/models/exch/exch_derived.py +36 -0
  678. hydpy/models/exch/exch_factors.py +26 -0
  679. hydpy/models/exch/exch_fluxes.py +48 -0
  680. hydpy/models/exch/exch_inlets.py +11 -0
  681. hydpy/models/exch/exch_logs.py +12 -0
  682. hydpy/models/exch/exch_model.py +451 -0
  683. hydpy/models/exch/exch_outlets.py +17 -0
  684. hydpy/models/exch/exch_receivers.py +17 -0
  685. hydpy/models/exch_branch_hbv96.py +186 -0
  686. hydpy/models/exch_waterlevel.py +73 -0
  687. hydpy/models/exch_weir_hbv96.py +609 -0
  688. hydpy/models/ga/__init__.py +14 -0
  689. hydpy/models/ga/ga_aides.py +17 -0
  690. hydpy/models/ga/ga_control.py +208 -0
  691. hydpy/models/ga/ga_derived.py +77 -0
  692. hydpy/models/ga/ga_fluxes.py +83 -0
  693. hydpy/models/ga/ga_inputs.py +26 -0
  694. hydpy/models/ga/ga_logs.py +17 -0
  695. hydpy/models/ga/ga_model.py +2952 -0
  696. hydpy/models/ga/ga_states.py +87 -0
  697. hydpy/models/ga_garto.py +1001 -0
  698. hydpy/models/ga_garto_submodel1.py +79 -0
  699. hydpy/models/gland/__init__.py +14 -0
  700. hydpy/models/gland/gland_control.py +90 -0
  701. hydpy/models/gland/gland_derived.py +113 -0
  702. hydpy/models/gland/gland_fluxes.py +137 -0
  703. hydpy/models/gland/gland_inputs.py +12 -0
  704. hydpy/models/gland/gland_model.py +1439 -0
  705. hydpy/models/gland/gland_outlets.py +11 -0
  706. hydpy/models/gland/gland_states.py +90 -0
  707. hydpy/models/gland_gr4.py +501 -0
  708. hydpy/models/gland_gr5.py +463 -0
  709. hydpy/models/gland_gr6.py +487 -0
  710. hydpy/models/hland/__init__.py +20 -0
  711. hydpy/models/hland/hland_aides.py +19 -0
  712. hydpy/models/hland/hland_constants.py +37 -0
  713. hydpy/models/hland/hland_control.py +1530 -0
  714. hydpy/models/hland/hland_derived.py +683 -0
  715. hydpy/models/hland/hland_factors.py +57 -0
  716. hydpy/models/hland/hland_fixed.py +42 -0
  717. hydpy/models/hland/hland_fluxes.py +279 -0
  718. hydpy/models/hland/hland_inputs.py +19 -0
  719. hydpy/models/hland/hland_masks.py +107 -0
  720. hydpy/models/hland/hland_model.py +4664 -0
  721. hydpy/models/hland/hland_outlets.py +11 -0
  722. hydpy/models/hland/hland_parameters.py +227 -0
  723. hydpy/models/hland/hland_sequences.py +382 -0
  724. hydpy/models/hland/hland_states.py +236 -0
  725. hydpy/models/hland_96.py +1812 -0
  726. hydpy/models/hland_96c.py +1196 -0
  727. hydpy/models/hland_96p.py +1204 -0
  728. hydpy/models/kinw/__init__.py +18 -0
  729. hydpy/models/kinw/kinw_aides.py +306 -0
  730. hydpy/models/kinw/kinw_control.py +270 -0
  731. hydpy/models/kinw/kinw_derived.py +197 -0
  732. hydpy/models/kinw/kinw_fixed.py +33 -0
  733. hydpy/models/kinw/kinw_fluxes.py +37 -0
  734. hydpy/models/kinw/kinw_inlets.py +11 -0
  735. hydpy/models/kinw/kinw_model.py +3026 -0
  736. hydpy/models/kinw/kinw_outlets.py +11 -0
  737. hydpy/models/kinw/kinw_solver.py +45 -0
  738. hydpy/models/kinw/kinw_states.py +17 -0
  739. hydpy/models/kinw_williams.py +1299 -0
  740. hydpy/models/kinw_williams_ext.py +768 -0
  741. hydpy/models/lland/__init__.py +42 -0
  742. hydpy/models/lland/lland_aides.py +38 -0
  743. hydpy/models/lland/lland_constants.py +88 -0
  744. hydpy/models/lland/lland_control.py +1329 -0
  745. hydpy/models/lland/lland_derived.py +380 -0
  746. hydpy/models/lland/lland_factors.py +18 -0
  747. hydpy/models/lland/lland_fixed.py +128 -0
  748. hydpy/models/lland/lland_fluxes.py +626 -0
  749. hydpy/models/lland/lland_inlets.py +12 -0
  750. hydpy/models/lland/lland_inputs.py +33 -0
  751. hydpy/models/lland/lland_logs.py +17 -0
  752. hydpy/models/lland/lland_masks.py +212 -0
  753. hydpy/models/lland/lland_model.py +7690 -0
  754. hydpy/models/lland/lland_outlets.py +12 -0
  755. hydpy/models/lland/lland_parameters.py +195 -0
  756. hydpy/models/lland/lland_sequences.py +67 -0
  757. hydpy/models/lland/lland_states.py +280 -0
  758. hydpy/models/lland_dd.py +2270 -0
  759. hydpy/models/lland_knauf.py +2156 -0
  760. hydpy/models/lland_knauf_ic.py +1920 -0
  761. hydpy/models/meteo/__init__.py +12 -0
  762. hydpy/models/meteo/meteo_control.py +154 -0
  763. hydpy/models/meteo/meteo_derived.py +159 -0
  764. hydpy/models/meteo/meteo_factors.py +88 -0
  765. hydpy/models/meteo/meteo_fixed.py +19 -0
  766. hydpy/models/meteo/meteo_fluxes.py +46 -0
  767. hydpy/models/meteo/meteo_inputs.py +47 -0
  768. hydpy/models/meteo/meteo_logs.py +30 -0
  769. hydpy/models/meteo/meteo_model.py +2904 -0
  770. hydpy/models/meteo/meteo_parameters.py +14 -0
  771. hydpy/models/meteo/meteo_sequences.py +22 -0
  772. hydpy/models/meteo_clear_glob_io.py +77 -0
  773. hydpy/models/meteo_glob_fao56.py +217 -0
  774. hydpy/models/meteo_glob_io.py +68 -0
  775. hydpy/models/meteo_glob_morsim.py +444 -0
  776. hydpy/models/meteo_precip_io.py +76 -0
  777. hydpy/models/meteo_psun_sun_glob_io.py +83 -0
  778. hydpy/models/meteo_sun_fao56.py +188 -0
  779. hydpy/models/meteo_sun_morsim.py +466 -0
  780. hydpy/models/meteo_temp_io.py +76 -0
  781. hydpy/models/musk/__init__.py +15 -0
  782. hydpy/models/musk/musk_control.py +328 -0
  783. hydpy/models/musk/musk_derived.py +32 -0
  784. hydpy/models/musk/musk_factors.py +53 -0
  785. hydpy/models/musk/musk_fluxes.py +24 -0
  786. hydpy/models/musk/musk_inlets.py +11 -0
  787. hydpy/models/musk/musk_masks.py +15 -0
  788. hydpy/models/musk/musk_model.py +838 -0
  789. hydpy/models/musk/musk_outlets.py +11 -0
  790. hydpy/models/musk/musk_sequences.py +88 -0
  791. hydpy/models/musk/musk_solver.py +68 -0
  792. hydpy/models/musk/musk_states.py +64 -0
  793. hydpy/models/musk_classic.py +228 -0
  794. hydpy/models/musk_mct.py +1247 -0
  795. hydpy/models/rconc/__init__.py +12 -0
  796. hydpy/models/rconc/rconc_control.py +473 -0
  797. hydpy/models/rconc/rconc_derived.py +76 -0
  798. hydpy/models/rconc/rconc_fluxes.py +19 -0
  799. hydpy/models/rconc/rconc_logs.py +74 -0
  800. hydpy/models/rconc/rconc_model.py +260 -0
  801. hydpy/models/rconc/rconc_states.py +11 -0
  802. hydpy/models/rconc_nash.py +48 -0
  803. hydpy/models/rconc_uh.py +53 -0
  804. hydpy/models/sw1d/__init__.py +17 -0
  805. hydpy/models/sw1d/sw1d_control.py +356 -0
  806. hydpy/models/sw1d/sw1d_derived.py +85 -0
  807. hydpy/models/sw1d/sw1d_factors.py +78 -0
  808. hydpy/models/sw1d/sw1d_fixed.py +12 -0
  809. hydpy/models/sw1d/sw1d_fluxes.py +55 -0
  810. hydpy/models/sw1d/sw1d_inlets.py +17 -0
  811. hydpy/models/sw1d/sw1d_model.py +3385 -0
  812. hydpy/models/sw1d/sw1d_outlets.py +11 -0
  813. hydpy/models/sw1d/sw1d_receivers.py +11 -0
  814. hydpy/models/sw1d/sw1d_senders.py +11 -0
  815. hydpy/models/sw1d/sw1d_states.py +23 -0
  816. hydpy/models/sw1d_channel.py +2051 -0
  817. hydpy/models/sw1d_gate_out.py +599 -0
  818. hydpy/models/sw1d_lias.py +105 -0
  819. hydpy/models/sw1d_lias_sluice.py +531 -0
  820. hydpy/models/sw1d_network.py +1219 -0
  821. hydpy/models/sw1d_pump.py +448 -0
  822. hydpy/models/sw1d_q_in.py +79 -0
  823. hydpy/models/sw1d_q_out.py +81 -0
  824. hydpy/models/sw1d_storage.py +78 -0
  825. hydpy/models/sw1d_weir_out.py +75 -0
  826. hydpy/models/test/__init__.py +14 -0
  827. hydpy/models/test/test_control.py +28 -0
  828. hydpy/models/test/test_fluxes.py +17 -0
  829. hydpy/models/test/test_model.py +201 -0
  830. hydpy/models/test/test_solver.py +48 -0
  831. hydpy/models/test/test_states.py +17 -0
  832. hydpy/models/test_discontinous.py +46 -0
  833. hydpy/models/test_stiff0d.py +47 -0
  834. hydpy/models/test_stiff1d.py +42 -0
  835. hydpy/models/whmod/__init__.py +21 -0
  836. hydpy/models/whmod/whmod_constants.py +77 -0
  837. hydpy/models/whmod/whmod_control.py +333 -0
  838. hydpy/models/whmod/whmod_derived.py +210 -0
  839. hydpy/models/whmod/whmod_factors.py +9 -0
  840. hydpy/models/whmod/whmod_fluxes.py +105 -0
  841. hydpy/models/whmod/whmod_inputs.py +15 -0
  842. hydpy/models/whmod/whmod_masks.py +178 -0
  843. hydpy/models/whmod/whmod_model.py +2091 -0
  844. hydpy/models/whmod/whmod_parameters.py +155 -0
  845. hydpy/models/whmod/whmod_sequences.py +193 -0
  846. hydpy/models/whmod/whmod_states.py +73 -0
  847. hydpy/models/whmod_rural.py +794 -0
  848. hydpy/models/whmod_urban.py +1011 -0
  849. hydpy/models/wland/__init__.py +43 -0
  850. hydpy/models/wland/wland_aides.py +55 -0
  851. hydpy/models/wland/wland_constants.py +103 -0
  852. hydpy/models/wland/wland_control.py +508 -0
  853. hydpy/models/wland/wland_derived.py +330 -0
  854. hydpy/models/wland/wland_factors.py +11 -0
  855. hydpy/models/wland/wland_fixed.py +12 -0
  856. hydpy/models/wland/wland_fluxes.py +166 -0
  857. hydpy/models/wland/wland_inputs.py +33 -0
  858. hydpy/models/wland/wland_masks.py +54 -0
  859. hydpy/models/wland/wland_model.py +3755 -0
  860. hydpy/models/wland/wland_outlets.py +11 -0
  861. hydpy/models/wland/wland_parameters.py +214 -0
  862. hydpy/models/wland/wland_sequences.py +108 -0
  863. hydpy/models/wland/wland_solver.py +45 -0
  864. hydpy/models/wland/wland_states.py +56 -0
  865. hydpy/models/wland_gd.py +888 -0
  866. hydpy/models/wland_wag.py +1244 -0
  867. hydpy/models/wq/__init__.py +14 -0
  868. hydpy/models/wq/wq_control.py +117 -0
  869. hydpy/models/wq/wq_derived.py +182 -0
  870. hydpy/models/wq/wq_factors.py +79 -0
  871. hydpy/models/wq/wq_fluxes.py +17 -0
  872. hydpy/models/wq/wq_model.py +1889 -0
  873. hydpy/models/wq_trapeze.py +168 -0
  874. hydpy/models/wq_trapeze_strickler.py +101 -0
  875. hydpy/models/wq_walrus.py +57 -0
  876. hydpy/py.typed +0 -0
  877. hydpy/tests/.coveragerc +22 -0
  878. hydpy/tests/__init__.py +0 -0
  879. hydpy/tests/check_consistency.py +32 -0
  880. hydpy/tests/hydpydoctestcustomize.pth +1 -0
  881. hydpy/tests/hydpydoctestcustomize.py +15 -0
  882. hydpy/tests/iotesting/__init__.py +0 -0
  883. hydpy/tests/run_doctests.py +233 -0
  884. hydpy-6.2.dev1.data/scripts/hyd.py +277 -0
  885. hydpy-6.2.dev1.dist-info/LICENSE +165 -0
  886. hydpy-6.2.dev1.dist-info/METADATA +163 -0
  887. hydpy-6.2.dev1.dist-info/RECORD +890 -0
  888. hydpy-6.2.dev1.dist-info/WHEEL +5 -0
  889. hydpy-6.2.dev1.dist-info/licenses_hydpy_installer.txt +42 -0
  890. 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
+ }