flextool 4.0.2__tar.gz → 4.1.0__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 (410) hide show
  1. {flextool-4.0.2 → flextool-4.1.0}/PKG-INFO +6 -6
  2. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_open_results_db.py +4 -9
  3. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_axis_enums.py +3 -0
  4. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_benders.py +16 -0
  5. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_cumulative_invest.py +75 -20
  6. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_delay.py +118 -8
  7. flextool-4.1.0/flextool/engine_polars/_derived_branch.py +1804 -0
  8. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_derived_existing.py +342 -11
  9. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_derived_npv.py +120 -23
  10. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_derived_params.py +1284 -158
  11. flextool-4.1.0/flextool/engine_polars/_derived_walks.py +487 -0
  12. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_direct_params.py +132 -65
  13. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_dump_csvs.py +10 -3
  14. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_arc_unions.py +67 -31
  15. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_chain_params.py +28 -2
  16. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_mid_sets.py +6 -3
  17. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_per_solve.py +71 -8
  18. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_period_calc.py +24 -0
  19. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_solve_time.py +14 -1
  20. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_solve_writers.py +23 -2
  21. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_flex_data_accumulator.py +1 -0
  22. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_inmemory_reader.py +37 -0
  23. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_input_source.py +22 -0
  24. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_native_run_model.py +193 -4
  25. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_orchestration.py +340 -0
  26. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_output_writer.py +5 -2
  27. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_param_shapes.py +225 -14
  28. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_pdt_join.py +25 -6
  29. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_projection_params.py +5 -4
  30. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_provider_keys.py +8 -0
  31. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_provider_translators.py +35 -0
  32. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_recursive_solve.py +74 -0
  33. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_region_filter.py +6 -0
  34. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_reserve.py +437 -13
  35. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solve_config.py +309 -6
  36. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solve_context.py +54 -0
  37. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solve_handoff.py +54 -1
  38. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solve_state.py +41 -0
  39. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solver_dispatch.py +52 -2
  40. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_spinedb_reader.py +531 -21
  41. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_stochastic.py +299 -46
  42. flextool-4.1.0/flextool/engine_polars/_stochastic_detect.py +85 -0
  43. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_timeline.py +148 -78
  44. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_warm.py +26 -4
  45. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/autoscale/_layer2.py +26 -9
  46. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/autoscale/_layer2_types.py +57 -1
  47. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/autoscale/_quantity_types.py +30 -4
  48. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/input.py +678 -14
  49. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/model.py +1933 -394
  50. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/export_settings.yaml +9 -2
  51. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/db_editor_integration.py +30 -17
  52. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/main_window.py +14 -11
  53. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/platform_utils.py +40 -12
  54. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/__init__.py +8 -0
  55. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_process_method.py +4 -1
  56. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_specs.py +10 -8
  57. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_validators.py +259 -0
  58. flextool-4.1.0/flextool/process_outputs/_branch_weight.py +48 -0
  59. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/calc_costs.py +50 -0
  60. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/calc_slacks.py +27 -3
  61. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/calc_storage_vre.py +22 -1
  62. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/drop_levels.py +7 -1
  63. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_costs.py +12 -2
  64. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/read_highs_solution.py +82 -0
  65. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/read_parameters.py +38 -4
  66. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_aggregate_output.json +235 -28
  67. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_connections.json +235 -28
  68. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_demand.json +235 -28
  69. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_hydro_reservoir.json +235 -28
  70. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_hydro_reservoir_with_pump.json +242 -48
  71. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_non_sync_and_curtailment.json +235 -28
  72. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_ramp_and_start_up.json +235 -28
  73. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/howto_stochastics.json +236 -29
  74. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/templates_examples.json +242 -35
  75. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/canonical_databases/templates_time_settings_only.json +235 -28
  76. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/flextool_axis_contract.json +1 -2
  77. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/spinedb_schema.json +213 -33
  78. {flextool-4.0.2 → flextool-4.1.0}/flextool/solver_config/highs.opt.template +0 -3
  79. {flextool-4.0.2 → flextool-4.1.0}/flextool/spinedb_backend/_axis_enums.py +44 -0
  80. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/__init__.py +1 -1
  81. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/db_migration.py +813 -0
  82. {flextool-4.0.2 → flextool-4.1.0}/flextool.egg-info/PKG-INFO +6 -6
  83. {flextool-4.0.2 → flextool-4.1.0}/flextool.egg-info/SOURCES.txt +7 -0
  84. {flextool-4.0.2 → flextool-4.1.0}/flextool.egg-info/requires.txt +5 -5
  85. {flextool-4.0.2 → flextool-4.1.0}/pyproject.toml +31 -11
  86. {flextool-4.0.2 → flextool-4.1.0}/tests/test_branch_weights.py +64 -37
  87. {flextool-4.0.2 → flextool-4.1.0}/tests/test_cost_aggregation_semantics.py +59 -47
  88. {flextool-4.0.2 → flextool-4.1.0}/tests/test_handoff_writers.py +19 -6
  89. {flextool-4.0.2 → flextool-4.1.0}/tests/test_min_load_rolling.py +19 -0
  90. {flextool-4.0.2 → flextool-4.1.0}/tests/test_non_anticipativity.py +46 -38
  91. {flextool-4.0.2 → flextool-4.1.0}/tests/test_parameter_group_coverage.py +6 -13
  92. flextool-4.1.0/tests/test_recourse_cost_reconciliation.py +111 -0
  93. flextool-4.1.0/tests/test_rolling_online_carry.py +247 -0
  94. flextool-4.1.0/tests/test_rolling_online_mintime_carry.py +353 -0
  95. flextool-4.1.0/tests/test_rolling_online_minuptime.py +204 -0
  96. flextool-4.1.0/tests/test_v70_migration.py +392 -0
  97. flextool-4.0.2/flextool/engine_polars/_derived_branch.py +0 -769
  98. flextool-4.0.2/flextool/engine_polars/_derived_walks.py +0 -276
  99. {flextool-4.0.2 → flextool-4.1.0}/LICENSE.txt +0 -0
  100. {flextool-4.0.2 → flextool-4.1.0}/README.md +0 -0
  101. {flextool-4.0.2 → flextool-4.1.0}/flextool/__init__.py +0 -0
  102. {flextool-4.0.2 → flextool-4.1.0}/flextool/_mem_sampler.py +0 -0
  103. {flextool-4.0.2 → flextool-4.1.0}/flextool/_resources.py +0 -0
  104. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/__init__.py +0 -0
  105. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/__main__.py +0 -0
  106. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_cli.py +0 -0
  107. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_db_alt.py +0 -0
  108. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_final_outputs.py +0 -0
  109. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_guard.py +0 -0
  110. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_loop.py +0 -0
  111. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_readers.py +0 -0
  112. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_report.py +0 -0
  113. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_sizing.py +0 -0
  114. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_solve.py +0 -0
  115. {flextool-4.0.2 → flextool-4.1.0}/flextool/calibrate/_solve_status.py +0 -0
  116. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/__init__.py +0 -0
  117. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/_console.py +0 -0
  118. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/_timing.py +0 -0
  119. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_execute_flextool_workflow.py +0 -0
  120. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_export_to_tabular.py +0 -0
  121. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_import_sensitivities.py +0 -0
  122. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_migrate_database.py +0 -0
  123. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_read_matpower.py +0 -0
  124. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_read_old_flextool.py +0 -0
  125. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_read_self_describing_tabular_input.py +0 -0
  126. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_read_tabular_input.py +0 -0
  127. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_run_flextool.py +0 -0
  128. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_scenario_results.py +0 -0
  129. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_solve_mps.py +0 -0
  130. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_update_flextool.py +0 -0
  131. {flextool-4.0.2 → flextool-4.1.0}/flextool/cli/cmd_write_outputs.py +0 -0
  132. {flextool-4.0.2 → flextool-4.1.0}/flextool/common_utils/__init__.py +0 -0
  133. {flextool-4.0.2 → flextool-4.1.0}/flextool/common_utils/plot_mem_shape.py +0 -0
  134. {flextool-4.0.2 → flextool-4.1.0}/flextool/common_utils/precision.py +0 -0
  135. {flextool-4.0.2 → flextool-4.1.0}/flextool/decomposition/__init__.py +0 -0
  136. {flextool-4.0.2 → flextool-4.1.0}/flextool/decomposition/region_decomposition.py +0 -0
  137. {flextool-4.0.2 → flextool-4.1.0}/flextool/decomposition/region_filter.py +0 -0
  138. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/__init__.py +0 -0
  139. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_block_layout.py +0 -0
  140. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_blocks.py +0 -0
  141. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_commodity_ladder.py +0 -0
  142. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_db_loader.py +0 -0
  143. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_db_reader.py +0 -0
  144. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_dc_power_flow.py +0 -0
  145. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_derived_arithmetic.py +0 -0
  146. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_derived_block.py +0 -0
  147. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_derived_profile.py +0 -0
  148. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_determinism.py +0 -0
  149. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_calc_params.py +0 -0
  150. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_co2_accumulators.py +0 -0
  151. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_dispatchers.py +0 -0
  152. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_energy_margin.py +0 -0
  153. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_energy_margin_adder.py +0 -0
  154. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_entity_annual.py +0 -0
  155. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_inflow_scaling.py +0 -0
  156. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_leaf_sets.py +0 -0
  157. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_lp_scaling.py +0 -0
  158. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_pdt_params.py +0 -0
  159. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_period_params.py +0 -0
  160. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_provider_io.py +0 -0
  161. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_emit_reserve.py +0 -0
  162. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_flex_data_provider.py +0 -0
  163. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_group_slack.py +0 -0
  164. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_invest_seeds.py +0 -0
  165. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_native_input_writer.py +0 -0
  166. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_parquet_bundle.py +0 -0
  167. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_pdt_lookup.py +0 -0
  168. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_per_solve_sets.py +0 -0
  169. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solve_acceptance.py +0 -0
  170. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_solver_base.py +0 -0
  171. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_subprocess_solve.py +0 -0
  172. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/_vectorize.py +0 -0
  173. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/autoscale/__init__.py +0 -0
  174. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/autoscale/_config.py +0 -0
  175. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/autoscale/_report.py +0 -0
  176. {flextool-4.0.2 → flextool-4.1.0}/flextool/engine_polars/chain.py +0 -0
  177. {flextool-4.0.2 → flextool-4.1.0}/flextool/env_check.py +0 -0
  178. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/__init__.py +0 -0
  179. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/db_reader.py +0 -0
  180. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/excel_writer.py +0 -0
  181. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/export_to_excel.py +0 -0
  182. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/formatting.py +0 -0
  183. {flextool-4.0.2 → flextool-4.1.0}/flextool/export_to_tabular/sheet_config.py +0 -0
  184. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/__init__.py +0 -0
  185. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/__main__.py +0 -0
  186. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/calibrate_commands.py +0 -0
  187. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/calibrate_jobs.py +0 -0
  188. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/check_tree.py +0 -0
  189. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/cli_format.py +0 -0
  190. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/config_parser.py +0 -0
  191. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/data_models.py +0 -0
  192. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/db_version_check.py +0 -0
  193. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/__init__.py +0 -0
  194. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/add_dialog.py +0 -0
  195. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/calibrate_dialog.py +0 -0
  196. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/file_picker.py +0 -0
  197. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/group_picker.py +0 -0
  198. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/migration_consent_dialog.py +0 -0
  199. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/migration_progress_dialog.py +0 -0
  200. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/plot_dialog.py +0 -0
  201. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/plot_settings_picker.py +0 -0
  202. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/project_dialog.py +0 -0
  203. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/dialogs/update_dialog.py +0 -0
  204. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/downsampling.py +0 -0
  205. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/error_handling.py +0 -0
  206. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/execution_manager.py +0 -0
  207. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/execution_window.py +0 -0
  208. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/hover_tooltip.py +0 -0
  209. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/input_sources.py +0 -0
  210. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/network_graph.py +0 -0
  211. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/output_actions.py +0 -0
  212. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/output_log_window.py +0 -0
  213. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/plot_cache.py +0 -0
  214. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/plot_canvas.py +0 -0
  215. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/plot_config_reader.py +0 -0
  216. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/project_utils.py +0 -0
  217. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/result_viewer.py +0 -0
  218. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/scenario_key.py +0 -0
  219. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/scenario_lists.py +0 -0
  220. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/settings_io.py +0 -0
  221. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/solve_reader.py +0 -0
  222. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/tree_reorder.py +0 -0
  223. {flextool-4.0.2 → flextool-4.1.0}/flextool/gui/ui_metrics.py +0 -0
  224. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_commodity_ladder.py +0 -0
  225. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_commodity_ladder_sets.py +0 -0
  226. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_dc_power_flow.py +0 -0
  227. {flextool-4.0.2 → flextool-4.1.0}/flextool/input_derivation/_method_constants.py +0 -0
  228. {flextool-4.0.2 → flextool-4.1.0}/flextool/lean_parquet.py +0 -0
  229. {flextool-4.0.2 → flextool-4.1.0}/flextool/model_builder/__init__.py +0 -0
  230. {flextool-4.0.2 → flextool-4.1.0}/flextool/model_builder/build_model.py +0 -0
  231. {flextool-4.0.2 → flextool-4.1.0}/flextool/model_builder/encoding.py +0 -0
  232. {flextool-4.0.2 → flextool-4.1.0}/flextool/model_builder/names.py +0 -0
  233. {flextool-4.0.2 → flextool-4.1.0}/flextool/model_builder/profiles.py +0 -0
  234. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/__init__.py +0 -0
  235. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/axis_helpers.py +0 -0
  236. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/color_template.py +0 -0
  237. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/config.py +0 -0
  238. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/format_helpers.py +0 -0
  239. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/legend_helpers.py +0 -0
  240. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/orchestrator.py +0 -0
  241. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/perf.py +0 -0
  242. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/plan.py +0 -0
  243. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/plot_bars.py +0 -0
  244. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/plot_bars_detail.py +0 -0
  245. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/plot_lines.py +0 -0
  246. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/shared_manifest.py +0 -0
  247. {flextool-4.0.2 → flextool-4.1.0}/flextool/plot_outputs/subplot_helpers.py +0 -0
  248. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/__init__.py +0 -0
  249. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/import_old_excel_input.json +0 -0
  250. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/read_matpower.py +0 -0
  251. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/read_old_flextool.py +0 -0
  252. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/read_self_describing_excel.py +0 -0
  253. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/read_tabular_with_specification.py +0 -0
  254. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/write_old_flextool_to_db.py +0 -0
  255. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/write_self_describing_to_db.py +0 -0
  256. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_inputs/write_to_input_db.py +0 -0
  257. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/__init__.py +0 -0
  258. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/_annualize.py +0 -0
  259. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/_inmemory_helpers.py +0 -0
  260. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/_output_meta.py +0 -0
  261. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/calc_capacity_flows.py +0 -0
  262. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/calc_connections.py +0 -0
  263. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/calc_group_flows.py +0 -0
  264. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/handoff_writers.py +0 -0
  265. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_ancillary.py +0 -0
  266. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_capacity.py +0 -0
  267. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_flowgroup.py +0 -0
  268. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_flows.py +0 -0
  269. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_group.py +0 -0
  270. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/out_node.py +0 -0
  271. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/persist_realized_slice.py +0 -0
  272. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/process_results.py +0 -0
  273. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/read_sets.py +0 -0
  274. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/read_variables.py +0 -0
  275. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/solve_order.py +0 -0
  276. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/spinedb_replay.py +0 -0
  277. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/union_realized_slice.py +0 -0
  278. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/write_outputs.py +0 -0
  279. {flextool-4.0.2 → flextool-4.1.0}/flextool/process_outputs/write_spinedb.py +0 -0
  280. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/__init__.py +0 -0
  281. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/clustering.py +0 -0
  282. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/force_include.py +0 -0
  283. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/netload.py +0 -0
  284. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/netload_inputs.py +0 -0
  285. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/netload_iterate.py +0 -0
  286. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/preprocess.py +0 -0
  287. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/scenario_stack.py +0 -0
  288. {flextool-4.0.2 → flextool-4.1.0}/flextool/representative_periods/weights.py +0 -0
  289. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/__init__.py +0 -0
  290. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/config_builder.py +0 -0
  291. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/constants.py +0 -0
  292. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/data_models.py +0 -0
  293. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/db_reader.py +0 -0
  294. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/dispatch_data.py +0 -0
  295. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/dispatch_mappings.py +0 -0
  296. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/dispatch_plots.py +0 -0
  297. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/input_entity_colors.py +0 -0
  298. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/orchestrator.py +0 -0
  299. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/plan_union.py +0 -0
  300. {flextool-4.0.2 → flextool-4.1.0}/flextool/scenario_comparison/plot_settings_seed.py +0 -0
  301. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/AXIS_CONTRACT.md +0 -0
  302. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/comparison_settings_template.json +0 -0
  303. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/default_plot_settings.yaml +0 -0
  304. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/default_plots.yaml +0 -0
  305. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/flextool_axis_contract.schema.json +0 -0
  306. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/old_flextool_import_template.json +0 -0
  307. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/output_info_template.json +0 -0
  308. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/output_settings_template.json +0 -0
  309. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_constant_default.json +0 -0
  310. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_default_optional_output.json +0 -0
  311. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_default_value.json +0 -0
  312. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_drop_down.json +0 -0
  313. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_lifetime_method.json +0 -0
  314. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_optional_outputs.json +0 -0
  315. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_output_node_flows.json +0 -0
  316. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_results_master.json +0 -0
  317. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_rolling_start_remove.json +0 -0
  318. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_rolling_window.json +0 -0
  319. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_storage_binding_defaults.json +0 -0
  320. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_v2.json +0 -0
  321. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/pre_v26/flextool_template_v25.json +0 -0
  322. {flextool-4.0.2 → flextool-4.1.0}/flextool/schemas/spinedb_results_schema.json +0 -0
  323. {flextool-4.0.2 → flextool-4.1.0}/flextool/solver_config/copt.opt.template +0 -0
  324. {flextool-4.0.2 → flextool-4.1.0}/flextool/solver_config/cplex.opt.template +0 -0
  325. {flextool-4.0.2 → flextool-4.1.0}/flextool/solver_config/gurobi.opt.template +0 -0
  326. {flextool-4.0.2 → flextool-4.1.0}/flextool/solver_config/xpress.opt.template +0 -0
  327. {flextool-4.0.2 → flextool-4.1.0}/flextool/spinedb_backend/__init__.py +0 -0
  328. {flextool-4.0.2 → flextool-4.1.0}/flextool/spinedb_backend/_backend.py +0 -0
  329. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/canonical_databases.py +0 -0
  330. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/ensure_settings_db.py +0 -0
  331. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/export_database.py +0 -0
  332. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/extend_tests_fixture.py +0 -0
  333. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/generate_canonical.py +0 -0
  334. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/initialize_database.py +0 -0
  335. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/install_info.py +0 -0
  336. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/self_update.py +0 -0
  337. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/sync_master_json_template.py +0 -0
  338. {flextool-4.0.2 → flextool-4.1.0}/flextool/update_flextool/test_fixtures.py +0 -0
  339. {flextool-4.0.2 → flextool-4.1.0}/flextool.egg-info/dependency_links.txt +0 -0
  340. {flextool-4.0.2 → flextool-4.1.0}/flextool.egg-info/entry_points.txt +0 -0
  341. {flextool-4.0.2 → flextool-4.1.0}/flextool.egg-info/top_level.txt +0 -0
  342. {flextool-4.0.2 → flextool-4.1.0}/setup.cfg +0 -0
  343. {flextool-4.0.2 → flextool-4.1.0}/tests/test_bar_layout.py +0 -0
  344. {flextool-4.0.2 → flextool-4.1.0}/tests/test_bar_sub_pixel_labels.py +0 -0
  345. {flextool-4.0.2 → flextool-4.1.0}/tests/test_blocks.py +0 -0
  346. {flextool-4.0.2 → flextool-4.1.0}/tests/test_color_template.py +0 -0
  347. {flextool-4.0.2 → flextool-4.1.0}/tests/test_commodity_ladder_rolling.py +0 -0
  348. {flextool-4.0.2 → flextool-4.1.0}/tests/test_comparison_excel.py +0 -0
  349. {flextool-4.0.2 → flextool-4.1.0}/tests/test_comparison_project_root.py +0 -0
  350. {flextool-4.0.2 → flextool-4.1.0}/tests/test_complete_period_share_reduction.py +0 -0
  351. {flextool-4.0.2 → flextool-4.1.0}/tests/test_connection_node_warnings.py +0 -0
  352. {flextool-4.0.2 → flextool-4.1.0}/tests/test_console_run_tool.py +0 -0
  353. {flextool-4.0.2 → flextool-4.1.0}/tests/test_cost_breakdown_by_entity.py +0 -0
  354. {flextool-4.0.2 → flextool-4.1.0}/tests/test_csv_dump_roundtrip.py +0 -0
  355. {flextool-4.0.2 → flextool-4.1.0}/tests/test_dc_power_flow.py +0 -0
  356. {flextool-4.0.2 → flextool-4.1.0}/tests/test_dispatch_consumer_and_connection_signs.py +0 -0
  357. {flextool-4.0.2 → flextool-4.1.0}/tests/test_dispatch_node_debug_and_tree.py +0 -0
  358. {flextool-4.0.2 → flextool-4.1.0}/tests/test_dispatch_order_specials.py +0 -0
  359. {flextool-4.0.2 → flextool-4.1.0}/tests/test_dispatch_scenario_tag.py +0 -0
  360. {flextool-4.0.2 → flextool-4.1.0}/tests/test_ensure_settings_db.py +0 -0
  361. {flextool-4.0.2 → flextool-4.1.0}/tests/test_entity_unitsize_invariant.py +0 -0
  362. {flextool-4.0.2 → flextool-4.1.0}/tests/test_entity_universe_carrier.py +0 -0
  363. {flextool-4.0.2 → flextool-4.1.0}/tests/test_env_check.py +0 -0
  364. {flextool-4.0.2 → flextool-4.1.0}/tests/test_export_to_tabular.py +0 -0
  365. {flextool-4.0.2 → flextool-4.1.0}/tests/test_extend_tests_fixture.py +0 -0
  366. {flextool-4.0.2 → flextool-4.1.0}/tests/test_flowgroup_indicators.py +0 -0
  367. {flextool-4.0.2 → flextool-4.1.0}/tests/test_force_include.py +0 -0
  368. {flextool-4.0.2 → flextool-4.1.0}/tests/test_group_output_warnings.py +0 -0
  369. {flextool-4.0.2 → flextool-4.1.0}/tests/test_input_entity_colors.py +0 -0
  370. {flextool-4.0.2 → flextool-4.1.0}/tests/test_lh2_three_region.py +0 -0
  371. {flextool-4.0.2 → flextool-4.1.0}/tests/test_old_flextool_importer_schema_drift.py +0 -0
  372. {flextool-4.0.2 → flextool-4.1.0}/tests/test_open_results_db.py +0 -0
  373. {flextool-4.0.2 → flextool-4.1.0}/tests/test_output_column_metadata.py +0 -0
  374. {flextool-4.0.2 → flextool-4.1.0}/tests/test_output_metadata_renderers.py +0 -0
  375. {flextool-4.0.2 → flextool-4.1.0}/tests/test_plan_union.py +0 -0
  376. {flextool-4.0.2 → flextool-4.1.0}/tests/test_plot_draw_order.py +0 -0
  377. {flextool-4.0.2 → flextool-4.1.0}/tests/test_plot_pipeline.py +0 -0
  378. {flextool-4.0.2 → flextool-4.1.0}/tests/test_plot_plan_chunk_reconstruction.py +0 -0
  379. {flextool-4.0.2 → flextool-4.1.0}/tests/test_plot_plan_time_labels_roundtrip.py +0 -0
  380. {flextool-4.0.2 → flextool-4.1.0}/tests/test_plot_settings_seed.py +0 -0
  381. {flextool-4.0.2 → flextool-4.1.0}/tests/test_precision.py +0 -0
  382. {flextool-4.0.2 → flextool-4.1.0}/tests/test_read_highs_solution.py +0 -0
  383. {flextool-4.0.2 → flextool-4.1.0}/tests/test_regional_filter.py +0 -0
  384. {flextool-4.0.2 → flextool-4.1.0}/tests/test_representative_periods.py +0 -0
  385. {flextool-4.0.2 → flextool-4.1.0}/tests/test_rp_alternative_name.py +0 -0
  386. {flextool-4.0.2 → flextool-4.1.0}/tests/test_rp_force_include_wiring.py +0 -0
  387. {flextool-4.0.2 → flextool-4.1.0}/tests/test_rp_solves_filter.py +0 -0
  388. {flextool-4.0.2 → flextool-4.1.0}/tests/test_scenario_colors.py +0 -0
  389. {flextool-4.0.2 → flextool-4.1.0}/tests/test_scenario_stack.py +0 -0
  390. {flextool-4.0.2 → flextool-4.1.0}/tests/test_scenarios.py +0 -0
  391. {flextool-4.0.2 → flextool-4.1.0}/tests/test_self_describing_reader.py +0 -0
  392. {flextool-4.0.2 → flextool-4.1.0}/tests/test_shared_axis_manifest.py +0 -0
  393. {flextool-4.0.2 → flextool-4.1.0}/tests/test_simple_bar_entity_color.py +0 -0
  394. {flextool-4.0.2 → flextool-4.1.0}/tests/test_solve_config.py +0 -0
  395. {flextool-4.0.2 → flextool-4.1.0}/tests/test_solve_reader.py +0 -0
  396. {flextool-4.0.2 → flextool-4.1.0}/tests/test_synthesize_invest_dual.py +0 -0
  397. {flextool-4.0.2 → flextool-4.1.0}/tests/test_timings_csv.py +0 -0
  398. {flextool-4.0.2 → flextool-4.1.0}/tests/test_unidirectional_connection.py +0 -0
  399. {flextool-4.0.2 → flextool-4.1.0}/tests/test_unit_online_dt_columns.py +0 -0
  400. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v52_migration.py +0 -0
  401. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v63_migration.py +0 -0
  402. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v64_migration.py +0 -0
  403. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v65_migration.py +0 -0
  404. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v66_migration.py +0 -0
  405. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v67_migration.py +0 -0
  406. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v68_migration.py +0 -0
  407. {flextool-4.0.2 → flextool-4.1.0}/tests/test_v69_migration.py +0 -0
  408. {flextool-4.0.2 → flextool-4.1.0}/tests/test_workdir_empty_default.py +0 -0
  409. {flextool-4.0.2 → flextool-4.1.0}/tests/test_xlsx_workflow.py +0 -0
  410. {flextool-4.0.2 → flextool-4.1.0}/tests/test_years_represented.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flextool
3
- Version: 4.0.2
3
+ Version: 4.1.0
4
4
  Summary: IRENA FlexTool is an energy and power systems model for understanding the role of variable power generation in future energy systems.
5
5
  Author: IRENA FlexTool contributors
6
6
  License: © International Renewable Energy Agency 2018-2022
@@ -38,11 +38,11 @@ Classifier: Topic :: Scientific/Engineering
38
38
  Requires-Python: >=3.11
39
39
  Description-Content-Type: text/markdown
40
40
  License-File: LICENSE.txt
41
- Requires-Dist: polar-high>=3.7.0
42
- Requires-Dist: highspy<=1.14.0
43
- Requires-Dist: polars>=1.40
44
- Requires-Dist: pandas
45
- Requires-Dist: spinedb-api
41
+ Requires-Dist: polar-high>=3.8.0
42
+ Requires-Dist: highspy<1.15,>=1.14.0
43
+ Requires-Dist: polars<3,>=1.40
44
+ Requires-Dist: pandas<4,>=2.2.3
45
+ Requires-Dist: spinedb-api<0.37,>=0.36.5
46
46
  Requires-Dist: openpyxl
47
47
  Requires-Dist: odfpy
48
48
  Requires-Dist: python-calamine
@@ -33,6 +33,7 @@ from pathlib import Path
33
33
 
34
34
  from flextool.cli._console import run_tool
35
35
  from flextool.cli.cmd_run_flextool import resolve_output_path
36
+ from flextool.gui.platform_utils import spine_db_editor_argv
36
37
 
37
38
 
38
39
  def resolve_results_db_path(project_folder_file, output_location=None):
@@ -100,16 +101,10 @@ def _build_launch_argv(db_urls):
100
101
  ``db_urls`` may be a single URL string or a list of URLs (each becomes a
101
102
  tab). The supported standalone entry point is
102
103
  ``spinetoolbox.spine_db_editor.main:main``, whose ``main()`` reads
103
- positional ``url`` args.
104
+ positional ``url`` args. Shared with the GUI launchers
105
+ (:func:`flextool.gui.platform_utils.spine_db_editor_argv`).
104
106
  """
105
- if isinstance(db_urls, str):
106
- db_urls = [db_urls]
107
- return [
108
- sys.executable,
109
- "-m",
110
- "spinetoolbox.spine_db_editor.main",
111
- *db_urls,
112
- ]
107
+ return spine_db_editor_argv(db_urls)
113
108
 
114
109
 
115
110
  def launch_db_editor(db_urls, _popen=subprocess.Popen):
@@ -105,6 +105,9 @@ _AXIS_SYNONYMS: dict[str, str] = {
105
105
  "b_f": "block",
106
106
  # Period history column — holds period tokens (subset of d).
107
107
  "d_h": "d",
108
+ # Scenario-lineage pair column (``dd_same_scenario``, recourse plan
109
+ # §6b Slice A) — holds period tokens (subset of d).
110
+ "d_other": "d",
108
111
  # ``d_first`` — column holding period tokens of "first" periods
109
112
  # (e.g. in ``_lifetime_expired_pairs_lf`` cascade). Subset of d.
110
113
  "d_first": "d",
@@ -114,6 +114,10 @@ from flextool.engine_polars.autoscale import (
114
114
  unscale_solution,
115
115
  )
116
116
  from flextool.engine_polars._region_filter import HalfFlow, RegionSplit
117
+ from flextool.engine_polars._solve_state import FlexToolConfigError
118
+ from flextool.engine_polars._stochastic_detect import (
119
+ is_genuinely_stochastic as _is_genuinely_stochastic,
120
+ )
117
121
  from flextool.engine_polars.input import FlexData
118
122
 
119
123
  _logger = logging.getLogger(__name__)
@@ -2043,6 +2047,18 @@ def solve_benders(
2043
2047
  -------
2044
2048
  BendersResult
2045
2049
  """
2050
+ # Slice C Guard 2 (defensive): a caller reaching solve_benders while
2051
+ # bypassing _run_benders_solve (the primary guard site) still fails
2052
+ # loudly on a stochastic model. Same shared detector on the master
2053
+ # ``data``. Benders x stochastics is not supported (recourse plan §4).
2054
+ if _is_genuinely_stochastic(data):
2055
+ raise FlexToolConfigError(
2056
+ "solve_benders called on a stochastic model "
2057
+ "(period__branch has non-realized branch periods with active "
2058
+ "time); Benders x stochastics is not supported "
2059
+ "(recourse plan §4)."
2060
+ )
2061
+
2046
2062
  if build_problem is None:
2047
2063
  def build_problem(pb, d):
2048
2064
  _build_flextool(pb, d, scale_the_objective=scale_the_objective)
@@ -722,6 +722,57 @@ def _emit_group_invest_period(m, d, vars: dict,
722
722
  # ---------------------------------------------------------------------------
723
723
  # Group invest / divest — total scope
724
724
 
725
+ def _emit_group_total_divest_cap(
726
+ m, *, legacy_name: str, path_name: str, outer: pl.DataFrame,
727
+ ge: pl.DataFrame, axis: str, var, unitsize, cap_param,
728
+ sense: str, d_leaf,
729
+ ) -> None:
730
+ """Per-path divest-group total cap (design §7.2 (G) item 4).
731
+
732
+ The divest group total sums ``v_divest * unitsize`` over ALL ``d``
733
+ (``edd_set`` is None on the divest side) grouped by ``g`` — under
734
+ recourse that cross-scenario double-counts one cap. When more than
735
+ one scenario leaf covers the divest periods (recourse, sense
736
+ ``"<="``), emit ``path_name`` indexed by ``(g, leaf)`` with the
737
+ inner sum masked to each leaf's periods. Single leaf — deterministic
738
+ / flag-off — or the ``">="`` floor keeps the legacy ``over=g`` shape
739
+ and NAME (byte-parity; the design registers only the ``max`` path
740
+ cap).
741
+ """
742
+ dl = None
743
+ if (sense == "<=" and d_leaf is not None
744
+ and getattr(d_leaf, "height", 0) > 0):
745
+ inv_periods = var.frame.select("d").unique()
746
+ _d_dt = var.frame.schema["d"]
747
+ dlx = d_leaf
748
+ if dlx.schema["d"] != _d_dt:
749
+ dlx = dlx.with_columns(pl.col("d").cast(_d_dt, strict=False))
750
+ dl = dlx.join(inv_periods, on="d", how="semi")
751
+ n_leaves = (dl["leaf"].n_unique()
752
+ if dl is not None and dl.height > 0 else 1)
753
+ if n_leaves <= 1:
754
+ m.add_cstr(
755
+ legacy_name,
756
+ over = outer,
757
+ sense = sense,
758
+ lhs_terms = {"divest_grp": Sum(Where(var * unitsize, ge),
759
+ over=(axis, "d"))},
760
+ rhs_terms = {"cap": cap_param},
761
+ )
762
+ return
763
+ mask = ge.join(dl, how="cross")
764
+ over_path = outer.join(dl.select("leaf").unique().sort("leaf"),
765
+ how="cross")
766
+ m.add_cstr(
767
+ path_name,
768
+ over = over_path,
769
+ sense = sense,
770
+ lhs_terms = {"divest_grp": Sum(Where(var * unitsize, mask),
771
+ over=(axis, "d"))},
772
+ rhs_terms = {"cap": cap_param},
773
+ )
774
+
775
+
725
776
  def _emit_group_invest_total(m, d, vars: dict,
726
777
  kind: str, sense: str) -> None:
727
778
  """Mod:
@@ -852,16 +903,18 @@ def _emit_group_invest_total(m, d, vars: dict,
852
903
  pl.col("p").is_in(v_p.frame["p"].unique())) \
853
904
  .filter(pl.col("g").is_in(g_set["g"].unique()))
854
905
  if ge_p.height > 0:
855
- lhs = Sum(
856
- Where(v_p * d.p_unitsize, ge_p),
857
- over=("p", "d"),
858
- )
859
- m.add_cstr(
860
- f"{name}_p",
861
- over = outer,
862
- sense = sense,
863
- lhs_terms = {"divest_grp": lhs},
864
- rhs_terms = {"cap": cap_param},
906
+ _emit_group_total_divest_cap(
907
+ m,
908
+ legacy_name = f"{name}_p",
909
+ path_name = f"{name}_path_p",
910
+ outer = outer,
911
+ ge = ge_p,
912
+ axis = "p",
913
+ var = v_p,
914
+ unitsize = d.p_unitsize,
915
+ cap_param = cap_param,
916
+ sense = sense,
917
+ d_leaf = getattr(d, "d_leaf", None),
865
918
  )
866
919
  # Node branch
867
920
  if v_n is not None and d.p_state_unitsize is not None:
@@ -876,16 +929,18 @@ def _emit_group_invest_total(m, d, vars: dict,
876
929
  pl.col("n").is_in(v_n.frame["n"].unique())) \
877
930
  .filter(pl.col("g").is_in(g_set["g"].unique()))
878
931
  if ge_n.height > 0:
879
- lhs = Sum(
880
- Where(v_n * us_n, ge_n),
881
- over=("n", "d"),
882
- )
883
- m.add_cstr(
884
- f"{name}_n",
885
- over = outer,
886
- sense = sense,
887
- lhs_terms = {"divest_grp": lhs},
888
- rhs_terms = {"cap": cap_param},
932
+ _emit_group_total_divest_cap(
933
+ m,
934
+ legacy_name = f"{name}_n",
935
+ path_name = f"{name}_path_n",
936
+ outer = outer,
937
+ ge = ge_n,
938
+ axis = "n",
939
+ var = v_n,
940
+ unitsize = us_n,
941
+ cap_param = cap_param,
942
+ sense = sense,
943
+ d_leaf = getattr(d, "d_leaf", None),
889
944
  )
890
945
 
891
946
 
@@ -98,6 +98,7 @@ from polar_high import Sum, Where, Param
98
98
  # Engine imports kept light — we don't introduce new variable types.
99
99
 
100
100
  from ._axis_enums import cast_dim
101
+ from ._derived_params import process_delayed__duration_from_weight
101
102
  from ._emit_provider_io import _provider_key
102
103
 
103
104
 
@@ -176,11 +177,10 @@ def load_data(inp_dir: str | Path, sd_dir: str | Path, *,
176
177
 
177
178
  pd_df = pd_df.rename({"process": "p"}) if "process" in pd_df.columns else pd_df
178
179
 
179
- # Δ.12-drop: ``process_delayed__duration`` (set frame, not Param)
180
- # produced authoritatively by
181
- # ``apply_direct_params.process_delayed__duration_from_source``.
182
- # Seed dropped.
183
- pdd_df = None
180
+ # ``process_delayed__duration`` is derived from the delay-weight
181
+ # keys below (``_derived_params.process_delayed__duration_from_weight``,
182
+ # the same producer the DB path uses), so its ``td`` labels match
183
+ # ``dtt__delay_duration`` and ``p_process_delay_weight`` exactly.
184
184
 
185
185
  # process_source_(un)delayed: (process, source) frames
186
186
  def _read_pse(name: str) -> pl.DataFrame | None:
@@ -255,7 +255,12 @@ def load_data(inp_dir: str | Path, sd_dir: str | Path, *,
255
255
  rename_map["time_sink"] = "t_sink"
256
256
  if "delay_duration" in raw.columns:
257
257
  rename_map["delay_duration"] = "td"
258
- dtt_df = raw.rename(rename_map).select("d", "t_source", "t_sink", "td")
258
+ # ``td`` is a duration in hours: Float64, as on the DB path
259
+ # (``dtt__delay_duration_from_source``). The CSV carries it as
260
+ # text whose formatting may differ between writers ("1" / "1.0").
261
+ dtt_df = (raw.rename(rename_map)
262
+ .select("d", "t_source", "t_sink",
263
+ pl.col("td").cast(pl.Float64)))
259
264
 
260
265
  pw_path = sd / "p_process_delay_weight.csv"
261
266
  pw_param = None
@@ -266,8 +271,11 @@ def load_data(inp_dir: str | Path, sd_dir: str | Path, *,
266
271
  rename_map["process"] = "p"
267
272
  if "delay_duration" in raw.columns:
268
273
  rename_map["delay_duration"] = "td"
269
- pw_long = raw.rename(rename_map).select("p", "td", "value")
274
+ pw_long = raw.rename(rename_map).select(
275
+ "p", pl.col("td").cast(pl.Float64),
276
+ pl.col("value").cast(pl.Float64))
270
277
  pw_param = Param(("p", "td"), pw_long)
278
+ pdd_df = process_delayed__duration_from_weight(pw_param)
271
279
 
272
280
  return dict(
273
281
  process_delayed = pd_df.select("p"),
@@ -281,6 +289,106 @@ def load_data(inp_dir: str | Path, sd_dir: str | Path, *,
281
289
  )
282
290
 
283
291
 
292
+ # ---------------------------------------------------------------------------
293
+ # Consistency check
294
+
295
+ class DelayDataError(RuntimeError):
296
+ """The delay tables of a delayed unit do not line up.
297
+
298
+ An internal wiring error, raised instead of building a conversion
299
+ equation without the unit's input (which forces its output to zero
300
+ without any message).
301
+ """
302
+
303
+
304
+ def _p_utf8(df: pl.DataFrame, cols: tuple[str, ...]) -> pl.DataFrame:
305
+ return df.select(pl.col(c).cast(pl.Utf8) for c in cols).unique()
306
+
307
+
308
+ def check_delay_tables(d) -> None:
309
+ """Raise :class:`DelayDataError` unless every delayed indirect unit can
310
+ get its delayed input term.
311
+
312
+ ``conversion_indirect`` takes a delayed unit's inputs out of the
313
+ undelayed sum (``process_delayed``), so the delayed term must cover
314
+ them. For every unit in ``process_delayed`` that is indirect and has
315
+ inputs (``process_input_flows``):
316
+
317
+ * it has delayed input arcs (``process_source_sink_delayed``);
318
+ * it has ``process_delayed__duration`` rows;
319
+ * ``td`` has the same dtype in ``process_delayed__duration``,
320
+ ``dtt__delay_duration`` and ``p_process_delay_weight``;
321
+ * every ``(p, td)`` has ``dtt__delay_duration`` rows and a weight.
322
+
323
+ Delayed connections are not indirect and are not checked here (no
324
+ delayed term applies to them).
325
+ """
326
+ if not has_feature(d):
327
+ return
328
+ indirect = getattr(d, "process_indirect", None)
329
+ inputs = getattr(d, "process_input_flows", None)
330
+ if indirect is None or indirect.height == 0 or inputs is None:
331
+ return
332
+ units = (_p_utf8(d.process_delayed, ("p",))
333
+ .join(_p_utf8(indirect, ("p",)), on="p", how="semi")
334
+ .join(_p_utf8(inputs, ("p",)), on="p", how="semi"))
335
+ if units.height == 0:
336
+ return
337
+ names = sorted(units["p"].to_list())
338
+
339
+ def _fail(msg: str, which: list[str]) -> None:
340
+ raise DelayDataError(
341
+ f"delayed unit(s) {', '.join(which)}: {msg}. Their inputs are "
342
+ "excluded from the undelayed conversion, so the unit would "
343
+ "be forced to zero output.")
344
+
345
+ psse = getattr(d, "process_source_sink_delayed", None)
346
+ if psse is None or psse.height == 0:
347
+ _fail("no delayed input arcs (process_source_sink_delayed)", names)
348
+ arcs = (psse.select(pl.col(c).cast(pl.Utf8) for c in ("p", "sink"))
349
+ .filter(pl.col("sink") == pl.col("p")).select("p").unique())
350
+ missing = units.join(arcs, on="p", how="anti")
351
+ if missing.height > 0:
352
+ _fail("no delayed input arcs (process_source_sink_delayed)",
353
+ sorted(missing["p"].to_list()))
354
+
355
+ pdd = getattr(d, "process_delayed__duration", None)
356
+ dtt = getattr(d, "dtt__delay_duration", None)
357
+ pw = getattr(d, "p_process_delay_weight", None)
358
+ if pdd is None or pdd.height == 0:
359
+ _fail("no delay durations (process_delayed__duration)", names)
360
+ missing = units.join(_p_utf8(pdd, ("p",)), on="p", how="anti")
361
+ if missing.height > 0:
362
+ _fail("no delay durations (process_delayed__duration)",
363
+ sorted(missing["p"].to_list()))
364
+ if dtt is None or dtt.height == 0:
365
+ _fail("no time-shift rows (dtt__delay_duration)", names)
366
+ if pw is None or pw.frame.height == 0:
367
+ _fail("no delay weights (p_process_delay_weight)", names)
368
+ dtypes = {"process_delayed__duration": pdd.schema["td"],
369
+ "dtt__delay_duration": dtt.schema["td"],
370
+ "p_process_delay_weight": pw.frame.schema["td"]}
371
+ if len(set(dtypes.values())) != 1:
372
+ _fail("delay duration (td) dtypes differ: "
373
+ + ", ".join(f"{k} {v}" for k, v in dtypes.items()), names)
374
+ used = (pdd.with_columns(pl.col("p").cast(pl.Utf8))
375
+ .join(units, on="p", how="semi"))
376
+ no_shift = used.join(dtt.select("td").unique(), on="td", how="anti")
377
+ if no_shift.height > 0:
378
+ _fail("delay duration(s) without time-shift rows "
379
+ "(dtt__delay_duration): "
380
+ + ", ".join(f"{p} {td!r}" for p, td in no_shift.iter_rows()),
381
+ sorted(set(no_shift["p"].to_list())))
382
+ no_weight = used.join(
383
+ pw.frame.select(pl.col("p").cast(pl.Utf8), "td"),
384
+ on=["p", "td"], how="anti")
385
+ if no_weight.height > 0:
386
+ _fail("delay duration(s) without a weight "
387
+ "(p_process_delay_weight): "
388
+ + ", ".join(f"{p} {td!r}" for p, td in no_weight.iter_rows()),
389
+ sorted(set(no_weight["p"].to_list())))
390
+
391
+
284
392
  # ---------------------------------------------------------------------------
285
393
  # Constraint contribution
286
394
 
@@ -313,10 +421,12 @@ def delayed_input_expr(d, v_flow):
313
421
  * ``Sum`` over (source, td) leaves dims (p, d, t).
314
422
 
315
423
  Returns ``None`` when there's no delayed-process data (caller should
316
- use a no-op).
424
+ use a no-op). Raises :class:`DelayDataError` when a delayed indirect
425
+ unit's tables do not line up (:func:`check_delay_tables`).
317
426
  """
318
427
  if not has_feature(d):
319
428
  return None
429
+ check_delay_tables(d)
320
430
  if d.dtt__delay_duration is None or d.p_process_delay_weight is None:
321
431
  return None
322
432
  if d.process_source_delayed is None or d.process_delayed__duration is None: