res2df 1.3.10__tar.gz → 1.3.12__tar.gz

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 (253) hide show
  1. {res2df-1.3.10 → res2df-1.3.12}/.github/workflows/res2df.yml +30 -20
  2. {res2df-1.3.10 → res2df-1.3.12}/.github/workflows/style.yml +1 -1
  3. {res2df-1.3.10 → res2df-1.3.12}/.github/workflows/typing.yml +1 -1
  4. {res2df-1.3.10 → res2df-1.3.12}/.pre-commit-config.yaml +1 -1
  5. {res2df-1.3.10 → res2df-1.3.12}/PKG-INFO +6 -5
  6. {res2df-1.3.10 → res2df-1.3.12}/README.md +1 -1
  7. {res2df-1.3.10 → res2df-1.3.12}/pyproject.toml +37 -11
  8. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/common.py +20 -20
  9. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/compdat.py +3 -3
  10. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/faults.py +9 -5
  11. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/fipreports.py +2 -1
  12. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/grid.py +10 -13
  13. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/gruptree.py +10 -10
  14. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/inferdims.py +2 -2
  15. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/nnc.py +2 -6
  16. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/parameters.py +5 -4
  17. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/pillars.py +1 -1
  18. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/pvt.py +1 -1
  19. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/satfunc.py +8 -9
  20. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/summary.py +8 -7
  21. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/trans.py +4 -4
  22. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/version.py +3 -3
  23. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/vfp/_vfp.py +2 -2
  24. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/vfp/_vfpcommon.py +7 -11
  25. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/vfp/_vfpinj.py +12 -15
  26. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/vfp/_vfpprod.py +9 -12
  27. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/wellcompletiondata.py +1 -1
  28. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/wellconnstatus.py +1 -1
  29. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/PKG-INFO +6 -5
  30. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/requires.txt +3 -3
  31. {res2df-1.3.10 → res2df-1.3.12}/tests/test_common.py +1 -8
  32. {res2df-1.3.10 → res2df-1.3.12}/tests/test_equil.py +1 -1
  33. {res2df-1.3.10 → res2df-1.3.12}/tests/test_gruptree.py +9 -0
  34. {res2df-1.3.10 → res2df-1.3.12}/tests/test_summary.py +24 -8
  35. {res2df-1.3.10 → res2df-1.3.12}/tests/test_summary_restarts.py +1 -1
  36. {res2df-1.3.10 → res2df-1.3.12}/tests/test_trans.py +2 -2
  37. {res2df-1.3.10 → res2df-1.3.12}/tests/test_vfp.py +9 -9
  38. {res2df-1.3.10 → res2df-1.3.12}/tests/test_welopen.py +50 -0
  39. {res2df-1.3.10 → res2df-1.3.12}/.github/dependabot.yml +0 -0
  40. {res2df-1.3.10 → res2df-1.3.12}/.github/workflows/codecov.yml +0 -0
  41. {res2df-1.3.10 → res2df-1.3.12}/.github/workflows/publish.yml +0 -0
  42. {res2df-1.3.10 → res2df-1.3.12}/.gitignore +0 -0
  43. {res2df-1.3.10 → res2df-1.3.12}/CONTRIBUTING.md +0 -0
  44. {res2df-1.3.10 → res2df-1.3.12}/LICENSE +0 -0
  45. {res2df-1.3.10 → res2df-1.3.12}/SECURITY.md +0 -0
  46. {res2df-1.3.10 → res2df-1.3.12}/ci/testkomodo.sh +0 -0
  47. {res2df-1.3.10 → res2df-1.3.12}/docs/_static/equinor-logo.png +0 -0
  48. {res2df-1.3.10 → res2df-1.3.12}/docs/_static/equinor-logo2.jpg +0 -0
  49. {res2df-1.3.10 → res2df-1.3.12}/docs/_static/equinor_logo.jpg +0 -0
  50. {res2df-1.3.10 → res2df-1.3.12}/docs/_static/equinor_logo_only.jpg +0 -0
  51. {res2df-1.3.10 → res2df-1.3.12}/docs/_templates/layout.html +0 -0
  52. {res2df-1.3.10 → res2df-1.3.12}/docs/conf.py +0 -0
  53. {res2df-1.3.10 → res2df-1.3.12}/docs/contribution.rst +0 -0
  54. {res2df-1.3.10 → res2df-1.3.12}/docs/csv2res.rst +0 -0
  55. {res2df-1.3.10 → res2df-1.3.12}/docs/glossary.rst +0 -0
  56. {res2df-1.3.10 → res2df-1.3.12}/docs/history.rst +0 -0
  57. {res2df-1.3.10 → res2df-1.3.12}/docs/index.rst +0 -0
  58. {res2df-1.3.10 → res2df-1.3.12}/docs/installation.rst +0 -0
  59. {res2df-1.3.10 → res2df-1.3.12}/docs/introduction.rst +0 -0
  60. {res2df-1.3.10 → res2df-1.3.12}/docs/res2csv.rst +0 -0
  61. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/compdat.csv +0 -0
  62. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/compdat.rst +0 -0
  63. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/equil-example.csv +0 -0
  64. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/equil.rst +0 -0
  65. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/fipnum.inc +0 -0
  66. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/fipreports-example.csv +0 -0
  67. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/fipreports-example.txt +0 -0
  68. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/fipreports.rst +0 -0
  69. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/grid.csv +0 -0
  70. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/grid.rst +0 -0
  71. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/gruptree.csv +0 -0
  72. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/gruptree.rst +0 -0
  73. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/gruptreenet.csv +0 -0
  74. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/images/injectoranalysis.png +0 -0
  75. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/images/multibranch-rftanalysis.png +0 -0
  76. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/nnc.csv +0 -0
  77. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/nnc.rst +0 -0
  78. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/outflow.csv +0 -0
  79. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/pillars-dyn1-stacked.csv +0 -0
  80. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/pillars-dyn1-unstacked.csv +0 -0
  81. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/pillars-example1.csv +0 -0
  82. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/pillars.rst +0 -0
  83. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/pvt.csv +0 -0
  84. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/pvt.rst +0 -0
  85. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/rft.rst +0 -0
  86. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/rft_columns.csv +0 -0
  87. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/satfunc.csv +0 -0
  88. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/satfunc.rst +0 -0
  89. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/summary.csv +0 -0
  90. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/summary.rst +0 -0
  91. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/trans-boundaries.csv +0 -0
  92. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/trans-group.csv +0 -0
  93. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/trans.rst +0 -0
  94. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/trans1.csv +0 -0
  95. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/wcon.csv +0 -0
  96. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/wcon.rst +0 -0
  97. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/well_connection_status.csv +0 -0
  98. {res2df-1.3.10 → res2df-1.3.12}/docs/usage/wellconnstatus.rst +0 -0
  99. {res2df-1.3.10 → res2df-1.3.12}/docs/usage.rst +0 -0
  100. {res2df-1.3.10 → res2df-1.3.12}/setup.cfg +0 -0
  101. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/__init__.py +0 -0
  102. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/__version__.py +0 -0
  103. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/constants.py +0 -0
  104. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/csv2res.py +0 -0
  105. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/equil.py +0 -0
  106. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/hook_implementations/__init__.py +0 -0
  107. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/hook_implementations/forward_model_steps.py +0 -0
  108. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/BRANPROP +0 -0
  109. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/COMPDAT +0 -0
  110. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/COMPLUMP +0 -0
  111. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/COMPSEGS +0 -0
  112. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/DENSITY +0 -0
  113. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/EQLDIMS +0 -0
  114. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/EQUIL +0 -0
  115. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/FAULTS +0 -0
  116. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/GRUPNET +0 -0
  117. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/GRUPTREE +0 -0
  118. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/NODEPROP +0 -0
  119. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PBVD +0 -0
  120. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PDVD +0 -0
  121. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PVDG +0 -0
  122. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PVDO +0 -0
  123. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PVTG +0 -0
  124. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PVTO +0 -0
  125. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/PVTW +0 -0
  126. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/ROCK +0 -0
  127. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/RSVD +0 -0
  128. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/RVVD +0 -0
  129. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SGFN +0 -0
  130. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SGOF +0 -0
  131. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SGWFN +0 -0
  132. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SLGOF +0 -0
  133. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SOF2 +0 -0
  134. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SOF3 +0 -0
  135. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SWFN +0 -0
  136. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/SWOF +0 -0
  137. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/TABDIMS +0 -0
  138. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/VFPINJ +0 -0
  139. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/VFPPROD +0 -0
  140. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WCONHIST +0 -0
  141. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WCONINJE +0 -0
  142. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WCONINJH +0 -0
  143. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WCONPROD +0 -0
  144. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WELOPEN +0 -0
  145. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WELSEGS +0 -0
  146. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WELSPECS +0 -0
  147. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WLIST +0 -0
  148. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WSEGAICD +0 -0
  149. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WSEGSICD +0 -0
  150. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/WSEGVALV +0 -0
  151. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/__init__.py +0 -0
  152. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/readme +0 -0
  153. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/opmkeywords/runmetoupdate.sh +0 -0
  154. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/py.typed +0 -0
  155. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/res2csv.py +0 -0
  156. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/res2csvlogger.py +0 -0
  157. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/resdatafiles.py +0 -0
  158. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/rft.py +0 -0
  159. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/svg_color_keyword_names.txt +0 -0
  160. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/vfp/__init__.py +0 -0
  161. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/vfp/_vfpdefs.py +0 -0
  162. {res2df-1.3.10 → res2df-1.3.12}/src/res2df/wcon.py +0 -0
  163. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/SOURCES.txt +0 -0
  164. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/dependency_links.txt +0 -0
  165. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/entry_points.txt +0 -0
  166. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/not-zip-safe +0 -0
  167. {res2df-1.3.10 → res2df-1.3.12}/src/res2df.egg-info/top_level.txt +0 -0
  168. {res2df-1.3.10 → res2df-1.3.12}/tests/__init__.py +0 -0
  169. {res2df-1.3.10 → res2df-1.3.12}/tests/conftest.py +0 -0
  170. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.DATA +0 -0
  171. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.EGRID +0 -0
  172. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.INIT +0 -0
  173. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.INSPEC +0 -0
  174. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.PRT +0 -0
  175. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.RFT +0 -0
  176. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.RSSPEC +0 -0
  177. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.SMSPEC +0 -0
  178. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.UNRST +0 -0
  179. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/EIGHTCELLS.UNSMRY +0 -0
  180. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/eightcells_duplicated_summary_vector/EIGHTCELLS_DUPES.DATA +0 -0
  181. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/eightcells_duplicated_summary_vector/EIGHTCELLS_DUPES.SMSPEC +0 -0
  182. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/eightcells_duplicated_summary_vector/EIGHTCELLS_DUPES.UNSMRY +0 -0
  183. {res2df-1.3.10 → res2df-1.3.12}/tests/data/eightcells/zones.lyr +0 -0
  184. {res2df-1.3.10 → res2df-1.3.12}/tests/data/fipreports/TEST1.PRT +0 -0
  185. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/grid/reek.faults +0 -0
  186. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/grid/reek.grid +0 -0
  187. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/grid/reek.multflt +0 -0
  188. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/grid/reek.multz +0 -0
  189. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/grid/reek.perm +0 -0
  190. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/grid/reek.poro +0 -0
  191. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/let-sgof.txt +0 -0
  192. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/let-swof.txt +0 -0
  193. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/reek.endpoints +0 -0
  194. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/reek.pvt +0 -0
  195. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/reek.swatinit +0 -0
  196. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/sgof.txt +0 -0
  197. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/swof.inc +0 -0
  198. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/props/swof.txt +0 -0
  199. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/regions/reek.eqlnum +0 -0
  200. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/regions/reek.fipnum +0 -0
  201. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/schedule/op6_aicd1_gp.sch +0 -0
  202. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/schedule/op6_icd1_gp.sch +0 -0
  203. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/schedule/op6_valve1_gp.sch +0 -0
  204. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/schedule/reek_history.sch +0 -0
  205. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/solution/reek.equil +0 -0
  206. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/include/summary/reek.smry +0 -0
  207. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0-OPMFLOW.PRT +0 -0
  208. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.DATA +0 -0
  209. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.ECLEND +0 -0
  210. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.EGRID +0 -0
  211. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.INIT +0 -0
  212. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.LOG +0 -0
  213. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.PRT +0 -0
  214. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.RFT +0 -0
  215. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.SMSPEC +0 -0
  216. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.UNRST +0 -0
  217. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/2_R001_REEK-0.UNSMRY +0 -0
  218. {res2df-1.3.10 → res2df-1.3.12}/tests/data/reek/eclipse/model/zones.lyr +0 -0
  219. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP.DATA +0 -0
  220. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP.SMSPEC +0 -0
  221. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP.UNSMRY +0 -0
  222. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_LONG.DATA +0 -0
  223. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_LONG.SMSPEC +0 -0
  224. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_LONG.UNSMRY +0 -0
  225. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP.DATA +0 -0
  226. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP.SMSPEC +0 -0
  227. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP.UNSMRY +0 -0
  228. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP_LONG.DATA +0 -0
  229. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP_LONG.SMSPEC +0 -0
  230. {res2df-1.3.10 → res2df-1.3.12}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP_LONG.UNSMRY +0 -0
  231. {res2df-1.3.10 → res2df-1.3.12}/tests/test_compdat.py +0 -0
  232. {res2df-1.3.10 → res2df-1.3.12}/tests/test_eclfiles.py +0 -0
  233. {res2df-1.3.10 → res2df-1.3.12}/tests/test_ert_hooks.py +0 -0
  234. {res2df-1.3.10 → res2df-1.3.12}/tests/test_faults.py +0 -0
  235. {res2df-1.3.10 → res2df-1.3.12}/tests/test_fipreports.py +0 -0
  236. {res2df-1.3.10 → res2df-1.3.12}/tests/test_grid.py +0 -0
  237. {res2df-1.3.10 → res2df-1.3.12}/tests/test_hook_implementations.py +0 -0
  238. {res2df-1.3.10 → res2df-1.3.12}/tests/test_inferdims.py +0 -0
  239. {res2df-1.3.10 → res2df-1.3.12}/tests/test_init.py +0 -0
  240. {res2df-1.3.10 → res2df-1.3.12}/tests/test_integration.py +0 -0
  241. {res2df-1.3.10 → res2df-1.3.12}/tests/test_logging.py +0 -0
  242. {res2df-1.3.10 → res2df-1.3.12}/tests/test_nnc.py +0 -0
  243. {res2df-1.3.10 → res2df-1.3.12}/tests/test_parameters.py +0 -0
  244. {res2df-1.3.10 → res2df-1.3.12}/tests/test_pillars.py +0 -0
  245. {res2df-1.3.10 → res2df-1.3.12}/tests/test_pvt.py +0 -0
  246. {res2df-1.3.10 → res2df-1.3.12}/tests/test_rft.py +0 -0
  247. {res2df-1.3.10 → res2df-1.3.12}/tests/test_satfunc.py +0 -0
  248. {res2df-1.3.10 → res2df-1.3.12}/tests/test_userapi.py +0 -0
  249. {res2df-1.3.10 → res2df-1.3.12}/tests/test_wcon.py +0 -0
  250. {res2df-1.3.10 → res2df-1.3.12}/tests/test_wellcompletiondata.py +0 -0
  251. {res2df-1.3.10 → res2df-1.3.12}/tests/test_wellconnstatus.py +0 -0
  252. {res2df-1.3.10 → res2df-1.3.12}/tests/test_wlist.py +0 -0
  253. {res2df-1.3.10 → res2df-1.3.12}/tests/test_zonemap.py +0 -0
@@ -10,7 +10,7 @@ on:
10
10
 
11
11
  schedule:
12
12
  # Run CI every night and check that tests are working with latest dependencies
13
- - cron: '0 0 * * *'
13
+ - cron: "0 0 * * *"
14
14
 
15
15
  env:
16
16
  ERT_SHOW_BACKTRACE: 1
@@ -21,16 +21,23 @@ jobs:
21
21
  runs-on: ubuntu-latest
22
22
  strategy:
23
23
  matrix:
24
- python-version: ['3.11', '3.12', '3.13']
24
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
25
+ pandas-version: [""]
25
26
  include:
26
27
  # For one of the Python versions we
27
28
  # install the extra dependency ert
28
29
  # (in order to not double the job matrix)
29
- - python-version: '3.11'
30
+ - python-version: "3.11"
30
31
  install-ert: true
32
+ - python-version: "3.13"
33
+ pandas-version: ">=2,<3"
34
+ - python-version: "3.13"
35
+ pandas-version: ">=3.0.0"
36
+ exclude:
37
+ - python-version: "3.13"
38
+ pandas-version: ""
31
39
 
32
40
  steps:
33
-
34
41
  - name: Install Ubuntu dependencies
35
42
  run: |
36
43
  sudo apt-get update
@@ -59,11 +66,14 @@ jobs:
59
66
  run: |
60
67
  uv pip install ".[tests, docs]"
61
68
 
62
-
63
69
  - name: Install ert
64
70
  if: matrix.install-ert
65
71
  run: uv pip install ".[ert]"
66
72
 
73
+ - name: Pin pandas version
74
+ if: matrix.pandas-version
75
+ run: uv pip install "pandas${{ matrix.pandas-version }}"
76
+
67
77
  - name: List all installed packages
68
78
  run: uv pip freeze
69
79
 
@@ -84,22 +94,22 @@ jobs:
84
94
  - name: Update GitHub pages
85
95
  if: github.repository_owner == 'equinor' && github.ref == 'refs/heads/master' && matrix.python-version == '3.11'
86
96
  run: |
87
- cp -R ./build/sphinx/html ../html
97
+ cp -R ./build/sphinx/html ../html
88
98
 
89
- git config --local user.email "res2df-github-action"
90
- git config --local user.name "res2df-github-action"
91
- git fetch origin gh-pages
92
- git checkout --track origin/gh-pages
93
- git clean -f -f -d -x
94
- git rm -r *
99
+ git config --local user.email "res2df-github-action"
100
+ git config --local user.name "res2df-github-action"
101
+ git fetch origin gh-pages
102
+ git checkout --track origin/gh-pages
103
+ git clean -f -f -d -x
104
+ git rm -r *
95
105
 
96
- cp -R ../html/* .
106
+ cp -R ../html/* .
97
107
 
98
- git add .
108
+ git add .
99
109
 
100
- if git diff-index --quiet HEAD; then
101
- echo "No changes in documentation. Skip documentation deploy."
102
- else
103
- git commit -m "Update Github Pages"
104
- git push "https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" gh-pages
105
- fi
110
+ if git diff-index --quiet HEAD; then
111
+ echo "No changes in documentation. Skip documentation deploy."
112
+ else
113
+ git commit -m "Update Github Pages"
114
+ git push "https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" gh-pages
115
+ fi
@@ -20,7 +20,7 @@ jobs:
20
20
  runs-on: ubuntu-latest
21
21
  strategy:
22
22
  matrix:
23
- python-version: ['3.13']
23
+ python-version: ['3.14']
24
24
 
25
25
  steps:
26
26
  - uses: actions/checkout@v6
@@ -24,7 +24,7 @@ jobs:
24
24
  runs-on: ubuntu-latest
25
25
  strategy:
26
26
  matrix:
27
- python-version: ['3.13']
27
+ python-version: ['3.14']
28
28
 
29
29
  steps:
30
30
  - uses: actions/checkout@v6
@@ -11,7 +11,7 @@ repos:
11
11
  - id: trailing-whitespace
12
12
 
13
13
  - repo: https://github.com/astral-sh/ruff-pre-commit
14
- rev: v0.14.8
14
+ rev: v0.14.10
15
15
  hooks:
16
16
  - id: ruff-check
17
17
  args: [ --fix ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: res2df
3
- Version: 1.3.10
3
+ Version: 1.3.12
4
4
  Summary: Convert reservoir simulator input and output to DataFrames
5
5
  Author-email: Håvard Berland <havb@equinor.com>
6
6
  License-Expression: GPL-3.0-only
@@ -16,6 +16,7 @@ Classifier: Topic :: Utilities
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
19
20
  Classifier: Natural Language :: English
20
21
  Requires-Python: >=3.11
21
22
  Description-Content-Type: text/markdown
@@ -25,7 +26,7 @@ Requires-Dist: resfo
25
26
  Requires-Dist: networkx
26
27
  Requires-Dist: numpy
27
28
  Requires-Dist: opm>=2020.10.2
28
- Requires-Dist: pandas
29
+ Requires-Dist: pandas>=2
29
30
  Requires-Dist: pyarrow
30
31
  Requires-Dist: pyyaml>=5.1
31
32
  Requires-Dist: treelib
@@ -48,10 +49,10 @@ Requires-Dist: sphinx-autoapi; extra == "docs"
48
49
  Requires-Dist: ipython; extra == "docs"
49
50
  Requires-Dist: rstcheck; extra == "docs"
50
51
  Requires-Dist: setuptools; extra == "docs"
51
- Requires-Dist: sphinx; extra == "docs"
52
+ Requires-Dist: sphinx<9; extra == "docs"
52
53
  Requires-Dist: sphinx-argparse; extra == "docs"
53
54
  Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
54
- Requires-Dist: sphinx_rtd_theme; extra == "docs"
55
+ Requires-Dist: sphinx_rtd_theme>=3.1.0.rc1; extra == "docs"
55
56
  Provides-Extra: ert
56
57
  Requires-Dist: ert>=10.2.0b13; extra == "ert"
57
58
  Dynamic: license-file
@@ -59,7 +60,7 @@ Dynamic: license-file
59
60
  [![Publish to PyPI](https://github.com/equinor/res2df/actions/workflows/publish.yml/badge.svg)](https://github.com/equinor/res2df/actions/workflows/publish.yml)
60
61
  [![PyPI version](https://img.shields.io/pypi/v/res2df.svg)](https://pypi.org/project/res2df/)
61
62
  [![codecov](https://codecov.io/gh/equinor/res2df/graph/badge.svg?token=3sZBGGu5VG)](https://codecov.io/gh/equinor/res2df)
62
- [![Python 3.11-3.13](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13-blue.svg)](https://www.python.org)
63
+ [![Python 3.11-3.14](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13%20|%203.14-blue.svg)](https://www.python.org)
63
64
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
64
65
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
65
66
 
@@ -1,7 +1,7 @@
1
1
  [![Publish to PyPI](https://github.com/equinor/res2df/actions/workflows/publish.yml/badge.svg)](https://github.com/equinor/res2df/actions/workflows/publish.yml)
2
2
  [![PyPI version](https://img.shields.io/pypi/v/res2df.svg)](https://pypi.org/project/res2df/)
3
3
  [![codecov](https://codecov.io/gh/equinor/res2df/graph/badge.svg?token=3sZBGGu5VG)](https://codecov.io/gh/equinor/res2df)
4
- [![Python 3.11-3.13](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13-blue.svg)](https://www.python.org)
4
+ [![Python 3.11-3.14](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13%20|%203.14-blue.svg)](https://www.python.org)
5
5
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
6
6
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
7
7
 
@@ -28,6 +28,7 @@ classifiers = [
28
28
  "Programming Language :: Python :: 3.11",
29
29
  "Programming Language :: Python :: 3.12",
30
30
  "Programming Language :: Python :: 3.13",
31
+ "Programming Language :: Python :: 3.14",
31
32
  "Natural Language :: English",
32
33
  ]
33
34
 
@@ -39,7 +40,7 @@ dependencies= [
39
40
  "networkx",
40
41
  "numpy",
41
42
  "opm>=2020.10.2",
42
- "pandas",
43
+ "pandas >= 2",
43
44
  "pyarrow",
44
45
  "pyyaml>=5.1",
45
46
  "treelib",
@@ -66,10 +67,10 @@ docs = [
66
67
  "ipython",
67
68
  "rstcheck",
68
69
  "setuptools",
69
- "sphinx",
70
+ "sphinx < 9",
70
71
  "sphinx-argparse",
71
72
  "sphinx-autodoc-typehints",
72
- "sphinx_rtd_theme"
73
+ "sphinx_rtd_theme >= 3.1.0.rc1",
73
74
  ]
74
75
  ert = ["ert>=10.2.0b13"]
75
76
 
@@ -127,19 +128,44 @@ line-length = 88
127
128
 
128
129
  [tool.ruff.lint]
129
130
  select = [
130
- "E", # pycodestyle
131
- "W", # pycodestyle
132
- "I", # isort
131
+ "AIR", # airflow
132
+ "ANN", # flake8-annotations
133
+ "ASYNC", # flake8-async
133
134
  "B", # flake-8-bugbear
134
- "SIM", # flake-8-simplify
135
+ "C4", # flake8-comprehensions
136
+ "DJ", # django
137
+ "E", # pycodestyle
135
138
  "F", # pyflakes
136
- "PL", # pylint
139
+ "FA", # future-annotations
140
+ "FAST", # fastapi
141
+ "FIX", # fixme
142
+ "FLY", # flynt
143
+ "FURB", # refurb
144
+ "I", # isort
145
+ "ICN", # flake8-import-conventions
146
+ "INT", # gettext
147
+ "ISC", # flake8-implicit-str-concat
137
148
  "NPY", # numpy specific rules
138
- "C4", # flake8-comprehensions
139
149
  "PD", # pandas-vet
150
+ "PERF", # perflint
151
+ "PGH", # pygrep-hooks
152
+ "PIE", # flake8-pie
153
+ "PL", # pylint
154
+ "PLC", # pylint convention
155
+ "PLE", # pylint error
156
+ "PLR", # pylint refactor
157
+ "PLW", # pylint warning
158
+ "PTH", # flake8-use-pathlib
159
+ "PYI", # flake8-pyi
160
+ "Q", # quotes
161
+ "RSE", # raise
140
162
  "RUF", # ruff specific rules
163
+ "SIM", # flake-8-simplify
164
+ "SLOT", # flake8-slots
165
+ "TD", # todos
141
166
  "UP", # pyupgrade
142
- "ANN", # flake8-annotations
167
+ "W", # pycodestyle
168
+ "YTT", # year 2020
143
169
  ]
144
170
  preview = true
145
171
  ignore = [
@@ -161,7 +187,7 @@ ignore = [
161
187
 
162
188
  [tool.ruff.lint.extend-per-file-ignores]
163
189
  "src/res2df/__init__.py" = ["PLC0414"]
164
- "tests/*" = ["RUF005", "ANN"]
190
+ "tests/*" = ["RUF005", "ANN", "FURB113", "PERF"]
165
191
  "docs/*" = ["ANN"]
166
192
 
167
193
  [tool.ruff.lint.pylint]
@@ -653,7 +653,7 @@ def generic_deck_table(
653
653
 
654
654
  # Start building the string we are to return:
655
655
  string = keyword + "\n"
656
- if comment is not None and comment:
656
+ if comment:
657
657
  string += "\n".join(["-- " + line for line in comment.splitlines()]) + "\n"
658
658
 
659
659
  # Empty tables are ok with Eclipse (at least sometimes)
@@ -664,7 +664,7 @@ def generic_deck_table(
664
664
  # Pandas make a pretty txt table:
665
665
  dframe = dframe.copy()
666
666
 
667
- # Column names are pr. ec2ldf standard, redo to opm.common in order to use
667
+ # Column names are pr. res2df standard, redo to opm.common in order to use
668
668
  # sorting from that:
669
669
  if renamer is not None:
670
670
  inv_renamer = {value: key for key, value in renamer.items()}
@@ -696,11 +696,14 @@ def generic_deck_table(
696
696
  dframe = dframe.fillna(value="1*")
697
697
 
698
698
  if drop_trailing_columns:
699
+ columns_to_drop = []
699
700
  for col_name in reversed(relevant_columns):
700
- if set(dframe[col_name].to_numpy()) == {"1*"}:
701
- del dframe[col_name]
701
+ if (dframe[col_name] == "1*").all():
702
+ columns_to_drop.append(col_name)
702
703
  else:
703
704
  break
705
+ if columns_to_drop:
706
+ dframe = dframe.drop(columns=columns_to_drop)
704
707
 
705
708
  # It is critical for opm.common, maybe also E100 to have integers printed
706
709
  # as integers, for correct parsing. Ensure these are integer where the json
@@ -708,13 +711,15 @@ def generic_deck_table(
708
711
  integer_cols = {
709
712
  item["name"]
710
713
  for item in OPMKEYWORDS[keyword]["items"]
711
- if item["value_type"] == "INT" # and item["name"] in col_headers
714
+ if item["value_type"] == "INT"
712
715
  }
713
716
  for int_col in integer_cols.intersection(dframe.columns):
714
- defaulted_rows = dframe[int_col] == "1*"
715
- integer_values = dframe.loc[~defaulted_rows, int_col].astype(int)
717
+ mask = dframe[int_col] != "1*"
716
718
  dframe[int_col] = dframe[int_col].astype(str)
717
- dframe.loc[~defaulted_rows, int_col] = integer_values
719
+ if mask.any():
720
+ dframe.loc[mask, int_col] = (
721
+ dframe.loc[mask, int_col].astype(float).astype(int).astype(str)
722
+ )
718
723
 
719
724
  # Quote all string data. This is not always needed, but needed
720
725
  # for some colums, for example well-names containing a slash.
@@ -726,9 +731,8 @@ def generic_deck_table(
726
731
  for str_col in string_cols.intersection(dframe.columns):
727
732
  # Ensure 1* is not quoted.
728
733
  non_defaulted_rows = dframe[str_col] != "1*"
729
- dframe.loc[non_defaulted_rows, str_col].str.replace("'", "")
730
734
  dframe.loc[non_defaulted_rows, str_col] = (
731
- "'" + dframe.loc[non_defaulted_rows, str_col] + "'"
735
+ "'" + dframe.loc[non_defaulted_rows, str_col].str.replace("'", "") + "'"
732
736
  )
733
737
 
734
738
  # Now rename again to have prettier column names:
@@ -739,8 +743,7 @@ def generic_deck_table(
739
743
  tablestring = dframe.to_string(header=True, index=False)
740
744
  # Indent all lines with two spaces:
741
745
  tablestring = "\n".join(
742
- [" " + line.strip().replace(" /", " /") for line in tablestring.splitlines()]
743
- # The replace() in there is needed for py36/pandas==1.1.5 only.
746
+ " " + line.strip().replace(" /", " /") for line in tablestring.splitlines()
744
747
  )
745
748
  # Eclipse comment for the header line:
746
749
  tablestring = "--" + tablestring[1:]
@@ -836,7 +839,7 @@ def stack_on_colnames(
836
839
  # Drop rows stemming from the NaNs in the second tuple-element for
837
840
  # static columns:
838
841
  dframe = dframe.dropna(axis="index", subset=["DATE"])
839
- del dframe["level_0"]
842
+ dframe = dframe.drop(columns="level_0")
840
843
  dframe.index.name = ""
841
844
  return dframe
842
845
 
@@ -912,11 +915,11 @@ def parse_lyrfile(filename: str | Path) -> list[dict[str, Any]] | None:
912
915
  zonedict["to_layer"] = to_layer
913
916
  else:
914
917
  logger.error("From_layer higher than to_layer")
915
- raise ValueError()
918
+ raise ValueError
916
919
  elif len(numbers) == 1:
917
920
  zonedict["span"] = int(numbers[0])
918
921
  else:
919
- raise ValueError()
922
+ raise ValueError
920
923
  lyrlist.append(zonedict)
921
924
  except ValueError:
922
925
  logger.error("Could not parse lyr file %s", filename)
@@ -967,14 +970,11 @@ def get_wells_matching_template(template: str, wells: list[str]) -> list[str]:
967
970
  Returns:
968
971
  List of matched wells
969
972
  """
970
- if template.startswith("*") or template.startswith("?"):
973
+ if template.startswith(("*", "?")):
971
974
  raise ValueError(
972
975
  "Well template not allowed to start with a wildcard character: "
973
976
  f"Must be preceded with a \\: {template}"
974
977
  )
975
- if template.startswith("\\"):
976
- # Note that the two \\ are actually read as one and
977
- # this will return True for f.ex '\*P1'
978
- template = template[1:]
978
+ template = template.removeprefix("\\")
979
979
  regex = template.replace("*", ".*").replace("?", ".")
980
980
  return [well for well in wells if bool(re.match(regex, well))]
@@ -751,7 +751,7 @@ def expand_complump_in_welopen_df(
751
751
  exp_welopens.append(cell_row)
752
752
 
753
753
  dframe = pd.DataFrame(exp_welopens)
754
- return dframe.astype(object).where(pd.notna(dframe), None) # type: ignore[call-overload]
754
+ return dframe.astype(object).replace({np.nan: None})
755
755
 
756
756
 
757
757
  def expand_wlist_in_welopen_df(
@@ -785,7 +785,7 @@ def expand_wlist_in_welopen_df(
785
785
  # Explicit wellname was used, no expansion to happen:
786
786
  exp_welopens.append(row)
787
787
  dframe = pd.DataFrame(exp_welopens)
788
- return dframe.astype(object).where(pd.notna(dframe), None) # type: ignore[call-overload]
788
+ return dframe.astype(object).replace({np.nan: None})
789
789
 
790
790
 
791
791
  def applywelopen(
@@ -844,7 +844,7 @@ def applywelopen(
844
844
  "The WLIST dataframe must be expanded through expand_wlist()"
845
845
  )
846
846
 
847
- welopen_df = welopen_df.astype(object).where(pd.notna(welopen_df), None) # type: ignore[call-overload]
847
+ welopen_df = welopen_df.astype(object).replace({np.nan: None})
848
848
  if wlist_df is not None:
849
849
  welopen_df = expand_wlist_in_welopen_df(welopen_df, wlist_df)
850
850
  if complump_df is not None:
@@ -7,6 +7,7 @@ a DataFrame
7
7
 
8
8
  import argparse
9
9
  import logging
10
+ from itertools import product
10
11
 
11
12
  # Needed for mypy
12
13
  import opm.io
@@ -36,7 +37,7 @@ def df(deck: "ResdataFiles | opm.opmcommon_python.Deck") -> pd.DataFrame:
36
37
 
37
38
  # In[91]: list(deck['FAULTS'][0])
38
39
  # Out[91]: [[u'F1'], [36], [36], [41], [42], [1], [14], [u'I']]
39
- data = []
40
+ data: list[list[str | int]] = []
40
41
  # It is allowed in Eclipse to use the keyword FAULTS
41
42
  # as many times as needed. Thus we need to loop in some way:
42
43
  for keyword in deck:
@@ -47,10 +48,13 @@ def df(deck: "ResdataFiles | opm.opmcommon_python.Deck") -> pd.DataFrame:
47
48
  frec_dict = parse_opmio_deckrecord(rec, "FAULTS")
48
49
  faultname = frec_dict["NAME"]
49
50
  faultface = frec_dict["FACE"]
50
- for i_idx in range(frec_dict["IX1"], frec_dict["IX2"] + 1):
51
- for j_idx in range(frec_dict["IY1"], frec_dict["IY2"] + 1):
52
- for k_idx in range(frec_dict["IZ1"], frec_dict["IZ2"] + 1):
53
- data.append([faultname, i_idx, j_idx, k_idx, faultface])
51
+
52
+ indices = product(
53
+ range(frec_dict["IX1"], frec_dict["IX2"] + 1),
54
+ range(frec_dict["IY1"], frec_dict["IY2"] + 1),
55
+ range(frec_dict["IZ1"], frec_dict["IZ2"] + 1),
56
+ )
57
+ data.extend([faultname, i, j, k, faultface] for i, j, k in indices)
54
58
  dframe = pd.DataFrame(columns=COLUMNS, data=data)
55
59
  logger.info("Extracted %i faults", len(dframe["NAME"].unique()))
56
60
  return dframe
@@ -4,6 +4,7 @@ import argparse
4
4
  import datetime
5
5
  import logging
6
6
  import re
7
+ from pathlib import Path
7
8
 
8
9
  import numpy as np
9
10
  import pandas as pd
@@ -133,7 +134,7 @@ def df(prtfile: str | ResdataFiles, fipname: str = "FIPNUM") -> pd.DataFrame:
133
134
  ".+" + fipname + r"\s+REPORT\s+REGION\s+(\d+)", re.IGNORECASE
134
135
  )
135
136
 
136
- with open(prtfile, encoding="utf-8") as prt_fh:
137
+ with Path(prtfile).open(encoding="utf-8") as prt_fh:
137
138
  logger.info(
138
139
  "Parsing file %s for blocks starting with %s REPORT REGION",
139
140
  prtfile,
@@ -47,7 +47,7 @@ def get_available_rst_dates(resdatafiles: ResdataFiles) -> list[datetime.date]:
47
47
  )
48
48
  return [
49
49
  resdatafiles.get_rstfile().iget_restart_sim_time(index).date()
50
- for index in range(0, len(report_indices))
50
+ for index in range(len(report_indices))
51
51
  ]
52
52
 
53
53
 
@@ -544,7 +544,7 @@ def fill_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
544
544
  parser.add_argument(
545
545
  "DATAFILE",
546
546
  help="Name of the .DATA input file for the reservoir simulator."
547
- + " There must exist .INIT and .EGRID files with the same path and basename.",
547
+ " There must exist .INIT and .EGRID files with the same path and basename.",
548
548
  )
549
549
  parser.add_argument(
550
550
  "--vectors",
@@ -556,8 +556,8 @@ def fill_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
556
556
  "--rstdates",
557
557
  type=str,
558
558
  help="Point in time to grab restart data from, "
559
- + "either 'first' or 'last', 'all', or a date in "
560
- + "YYYY-MM-DD format",
559
+ "either 'first' or 'last', 'all', or a date in "
560
+ "YYYY-MM-DD format",
561
561
  default="",
562
562
  )
563
563
  parser.add_argument(
@@ -610,10 +610,11 @@ def drop_constant_columns(
610
610
  if dframe.empty:
611
611
  return dframe
612
612
 
613
- columnstodelete = []
614
- for col in set(dframe.columns) - set(alwayskeep):
615
- if len(dframe[col].unique()) == 1:
616
- columnstodelete.append(col)
613
+ columnstodelete = [
614
+ col
615
+ for col in (set(dframe.columns) - set(alwayskeep))
616
+ if len(dframe[col].unique()) == 1
617
+ ]
617
618
  if columnstodelete:
618
619
  logging.info("Deleting constant columns %s", columnstodelete)
619
620
  return dframe.drop(columnstodelete, axis=1)
@@ -698,11 +699,7 @@ def df2res(
698
699
 
699
700
  res2df_header = (
700
701
  "Output file printed by "
701
- + "res2df.grid "
702
- + __version__
703
- + "\n"
704
- + " at "
705
- + str(datetime.datetime.now())
702
+ "res2df.grid " + __version__ + "\n" + " at " + str(datetime.datetime.now())
706
703
  )
707
704
 
708
705
  string = ""
@@ -9,9 +9,7 @@ import warnings
9
9
  from typing import Any
10
10
 
11
11
  import numpy as np
12
-
13
- # Needed for mypy
14
- import opm.io
12
+ import opm
15
13
  import pandas as pd
16
14
  import treelib
17
15
 
@@ -63,11 +61,14 @@ def df(
63
61
  date: datetime.date | None
64
62
  date = startdate if startdate is not None else None
65
63
 
64
+ if not isinstance(deck, (ResdataFiles, opm.opmcommon_python.Deck)):
65
+ raise TypeError("Input deck must be either ResdataFiles or an opm Deck.")
66
+
66
67
  if isinstance(deck, ResdataFiles):
67
68
  deck = deck.get_deck()
68
69
 
69
70
  edgerecords = [] # list of dict of rows containing an edge.
70
- nodedatarecords = []
71
+ nodedatarecords: list[dict[str, Any]] = []
71
72
 
72
73
  # In order for the GRUPTREE/BRANPROP keywords to accumulate, we
73
74
  # store the edges as dictionaries indexed by the edge
@@ -144,10 +145,10 @@ def df(
144
145
  renamer = (
145
146
  {"PRESSURE": "TERMINAL_PRESSURE"} if kword.name == "NODEPROP" else None
146
147
  )
147
- for rec in kword:
148
- nodedatarecords.append(
149
- parse_opmio_deckrecord(rec, kword.name, renamer=renamer)
150
- )
148
+ nodedatarecords.extend(
149
+ parse_opmio_deckrecord(rec, kword.name, renamer=renamer)
150
+ for rec in kword
151
+ )
151
152
  nodedata[kword.name] = (
152
153
  pd.DataFrame(nodedatarecords)
153
154
  .drop_duplicates(subset="NAME", keep="last")
@@ -178,7 +179,6 @@ def df(
178
179
  # This happens with WELSPECS if both GRUPTREE and BRANPROP is defined
179
180
  # at the same timestep. And when a node is redirected to a new parent node
180
181
  dframe = dframe.drop_duplicates(subset=["DATE", "CHILD", "KEYWORD"], keep="last")
181
- print(dframe)
182
182
  return dframe
183
183
 
184
184
 
@@ -254,7 +254,7 @@ def _merge_edges_and_nodeinfo(
254
254
 
255
255
  # Write WELSPECS edges
256
256
  welspecs_parents = set()
257
- for (child, parent), _ in wellspecsedges.items():
257
+ for child, parent in wellspecsedges: # noqa: PLE1141
258
258
  # For BRANPROP trees, only wells with a parent in the tree are added
259
259
  if (treetype == "BRANPROP" and parent in childs) or (treetype == "GRUPTREE"):
260
260
  rec_dict = {
@@ -38,7 +38,7 @@ def guess_dim(deckstring: str, dimkeyword: str, dimitem: int = 0) -> int:
38
38
  raise ValueError("Only supports TABDIMS and EQLDIMS")
39
39
  if dimkeyword == "TABDIMS" and dimitem not in [0, 1]:
40
40
  raise ValueError("Only support item 0 and 1 in TABDIMS")
41
- if dimkeyword == "EQLDIMS" and dimitem not in [0]:
41
+ if dimkeyword == "EQLDIMS" and dimitem != 0:
42
42
  raise ValueError("Only item 0 in EQLDIMS can be estimated")
43
43
 
44
44
  # A less than res2df-standard permissive opm.io, when using
@@ -112,7 +112,7 @@ def inject_dimcount(
112
112
  raise ValueError("Only supports TABDIMS and EQLDIMS")
113
113
  if dimkeyword == "TABDIMS" and dimitem not in [0, 1]:
114
114
  raise ValueError("Only support item 0 and 1 in TABDIMS")
115
- if dimkeyword == "EQLDIMS" and dimitem not in [0]:
115
+ if dimkeyword == "EQLDIMS" and dimitem != 0:
116
116
  raise ValueError("Only item 0 in EQLDIMS can be injected")
117
117
 
118
118
  if dimkeyword in deckstr:
@@ -181,7 +181,7 @@ def fill_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
181
181
  parser.add_argument(
182
182
  "DATAFILE",
183
183
  help="Name of the .DATA input file for the reservoir simulator."
184
- + " There must exist .INIT and .EGRID files with the same path and basename.",
184
+ " There must exist .INIT and .EGRID files with the same path and basename.",
185
185
  )
186
186
  parser.add_argument(
187
187
  "-c",
@@ -242,11 +242,7 @@ def df2res_editnnc(
242
242
  string = ""
243
243
  res2df_header = (
244
244
  "Output file printed by res2df.nnc"
245
- + " "
246
- + __version__
247
- + "\n"
248
- + " at "
249
- + str(datetime.datetime.now())
245
+ " " + __version__ + "\n" + " at " + str(datetime.datetime.now())
250
246
  )
251
247
  if not nocomments:
252
248
  string += comment_formatter(res2df_header)
@@ -5,7 +5,7 @@ import json
5
5
  import logging
6
6
  import warnings
7
7
  from pathlib import Path
8
- from typing import Any
8
+ from typing import Any, cast
9
9
 
10
10
  import pandas as pd
11
11
  import yaml
@@ -47,7 +47,7 @@ def find_parameter_files(
47
47
  filebase + ".txt",
48
48
  filebase,
49
49
  ]
50
- paths_to_check: list[Path] = [Path("."), Path(".."), Path("..") / Path("..")]
50
+ paths_to_check: list[Path] = [Path(), Path(".."), Path("..") / Path("..")]
51
51
  foundfiles = []
52
52
  for path in paths_to_check:
53
53
  for fname in files_to_lookfor:
@@ -79,11 +79,12 @@ def load_parameterstxt(filename: str | Path) -> dict[str, Any]:
79
79
  engine="python",
80
80
  names=["KEY", "VALUE"],
81
81
  index_col=False,
82
+ dtype={"KEY": str},
82
83
  )
83
84
  except pd.errors.ParserWarning as txt_exc:
84
85
  raise pd.errors.ParserError(txt_exc) from txt_exc
85
86
 
86
- return dframe.set_index("KEY")["VALUE"].to_dict()
87
+ return cast(dict[str, Any], dframe.set_index("KEY")["VALUE"].to_dict())
87
88
 
88
89
 
89
90
  def load_all(
@@ -147,7 +148,7 @@ def load(filename: str | Path) -> dict[str, Any]:
147
148
  if not params_dict:
148
149
  try:
149
150
  logger.debug("Trying to parse %s with json.load()", filename)
150
- with open(filename, encoding="utf-8") as f_handle:
151
+ with Path(filename).open(encoding="utf-8") as f_handle:
151
152
  params_dict = json.load(f_handle)
152
153
  assert isinstance(params_dict, dict)
153
154
  logger.debug(" - ok, parsed as yaml")