flixopt 2.1.7__tar.gz → 2.1.9__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.

Potentially problematic release.


This version of flixopt might be problematic. Click here for more details.

Files changed (108) hide show
  1. {flixopt-2.1.7 → flixopt-2.1.9}/.github/workflows/python-app.yaml +90 -59
  2. {flixopt-2.1.7 → flixopt-2.1.9}/CHANGELOG.md +46 -5
  3. {flixopt-2.1.7/flixopt.egg-info → flixopt-2.1.9}/PKG-INFO +46 -42
  4. {flixopt-2.1.7 → flixopt-2.1.9}/docs/SUMMARY.md +1 -1
  5. {flixopt-2.1.7 → flixopt-2.1.9}/docs/getting-started.md +2 -2
  6. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md +8 -8
  7. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/Flow.md +3 -3
  8. flixopt-2.1.9/docs/user-guide/Mathematical Notation/InvestParameters.md +3 -0
  9. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/LinearConverter.md +3 -3
  10. flixopt-2.1.9/docs/user-guide/Mathematical Notation/OnOffParameters.md +3 -0
  11. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/Storage.md +1 -1
  12. {flixopt-2.1.7 → flixopt-2.1.9}/examples/01_Simple/simple_example.py +0 -1
  13. {flixopt-2.1.7 → flixopt-2.1.9}/examples/02_Complex/complex_example_results.py +0 -3
  14. {flixopt-2.1.7 → flixopt-2.1.9}/examples/03_Calculation_types/example_calculation_types.py +5 -8
  15. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/aggregation.py +33 -32
  16. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/calculation.py +158 -58
  17. flixopt-2.1.9/flixopt/components.py +1279 -0
  18. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/config.py +17 -8
  19. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/core.py +59 -54
  20. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/effects.py +144 -63
  21. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/elements.py +292 -107
  22. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/features.py +61 -58
  23. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/flow_system.py +69 -48
  24. flixopt-2.1.9/flixopt/interface.py +1104 -0
  25. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/io.py +15 -10
  26. flixopt-2.1.9/flixopt/linear_converters.py +623 -0
  27. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/network_app.py +73 -39
  28. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/plotting.py +215 -87
  29. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/results.py +382 -209
  30. flixopt-2.1.9/flixopt/solvers.py +81 -0
  31. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/structure.py +41 -37
  32. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/utils.py +10 -7
  33. {flixopt-2.1.7 → flixopt-2.1.9/flixopt.egg-info}/PKG-INFO +46 -42
  34. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt.egg-info/SOURCES.txt +2 -0
  35. flixopt-2.1.9/flixopt.egg-info/requires.txt +60 -0
  36. {flixopt-2.1.7 → flixopt-2.1.9}/mkdocs.yml +0 -1
  37. {flixopt-2.1.7 → flixopt-2.1.9}/pyproject.toml +71 -46
  38. {flixopt-2.1.7 → flixopt-2.1.9}/renovate.json +8 -1
  39. {flixopt-2.1.7 → flixopt-2.1.9}/scripts/gen_ref_pages.py +1 -1
  40. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_bus.py +0 -5
  41. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_component.py +0 -2
  42. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_effect.py +0 -5
  43. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_examples.py +1 -2
  44. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_flow.py +0 -1
  45. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_integration.py +0 -3
  46. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_io.py +0 -2
  47. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_linear_converter.py +0 -2
  48. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_network_app.py +0 -5
  49. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_on_hours_computation.py +2 -2
  50. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_plots.py +4 -6
  51. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_storage.py +0 -3
  52. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_timeseries.py +1 -3
  53. flixopt-2.1.7/flixopt/components.py +0 -756
  54. flixopt-2.1.7/flixopt/interface.py +0 -265
  55. flixopt-2.1.7/flixopt/linear_converters.py +0 -331
  56. flixopt-2.1.7/flixopt/solvers.py +0 -77
  57. flixopt-2.1.7/flixopt.egg-info/requires.txt +0 -56
  58. {flixopt-2.1.7 → flixopt-2.1.9}/.github/CONTRIBUTING.md +0 -0
  59. {flixopt-2.1.7 → flixopt-2.1.9}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  60. {flixopt-2.1.7 → flixopt-2.1.9}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  61. {flixopt-2.1.7 → flixopt-2.1.9}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  62. {flixopt-2.1.7 → flixopt-2.1.9}/.github/ISSUE_TEMPLATE/general_issue.yml +0 -0
  63. {flixopt-2.1.7 → flixopt-2.1.9}/.github/pull_request_template.md +0 -0
  64. {flixopt-2.1.7 → flixopt-2.1.9}/.gitignore +0 -0
  65. {flixopt-2.1.7 → flixopt-2.1.9}/.pre-commit-config.yaml +0 -0
  66. {flixopt-2.1.7 → flixopt-2.1.9}/LICENSE +0 -0
  67. {flixopt-2.1.7 → flixopt-2.1.9}/README.md +0 -0
  68. {flixopt-2.1.7 → flixopt-2.1.9}/docs/contribute.md +0 -0
  69. {flixopt-2.1.7 → flixopt-2.1.9}/docs/examples/00-Minimal Example.md +0 -0
  70. {flixopt-2.1.7 → flixopt-2.1.9}/docs/examples/01-Basic Example.md +0 -0
  71. {flixopt-2.1.7 → flixopt-2.1.9}/docs/examples/02-Complex Example.md +0 -0
  72. {flixopt-2.1.7 → flixopt-2.1.9}/docs/examples/03-Calculation Modes.md +0 -0
  73. {flixopt-2.1.7 → flixopt-2.1.9}/docs/examples/index.md +0 -0
  74. {flixopt-2.1.7 → flixopt-2.1.9}/docs/faq/contribute.md +0 -0
  75. {flixopt-2.1.7 → flixopt-2.1.9}/docs/faq/index.md +0 -0
  76. {flixopt-2.1.7 → flixopt-2.1.9}/docs/images/architecture_flixOpt-pre2.0.0.png +0 -0
  77. {flixopt-2.1.7 → flixopt-2.1.9}/docs/images/architecture_flixOpt.png +0 -0
  78. {flixopt-2.1.7 → flixopt-2.1.9}/docs/images/flixopt-icon.svg +0 -0
  79. {flixopt-2.1.7 → flixopt-2.1.9}/docs/index.md +0 -0
  80. {flixopt-2.1.7 → flixopt-2.1.9}/docs/javascripts/mathjax.js +0 -0
  81. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/Bus.md +0 -0
  82. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/Piecewise.md +0 -0
  83. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/index.md +0 -0
  84. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/Mathematical Notation/others.md +0 -0
  85. {flixopt-2.1.7 → flixopt-2.1.9}/docs/user-guide/index.md +0 -0
  86. {flixopt-2.1.7 → flixopt-2.1.9}/examples/00_Minmal/minimal_example.py +0 -0
  87. {flixopt-2.1.7 → flixopt-2.1.9}/examples/02_Complex/complex_example.py +0 -0
  88. {flixopt-2.1.7 → flixopt-2.1.9}/examples/03_Calculation_types/Zeitreihen2020.csv +0 -0
  89. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/__init__.py +0 -0
  90. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/commons.py +0 -0
  91. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt/config.yaml +0 -0
  92. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt.egg-info/dependency_links.txt +0 -0
  93. {flixopt-2.1.7 → flixopt-2.1.9}/flixopt.egg-info/top_level.txt +0 -0
  94. {flixopt-2.1.7 → flixopt-2.1.9}/pics/architecture_flixOpt-pre2.0.0.png +0 -0
  95. {flixopt-2.1.7 → flixopt-2.1.9}/pics/architecture_flixOpt.png +0 -0
  96. {flixopt-2.1.7 → flixopt-2.1.9}/pics/flixOpt_plotting.jpg +0 -0
  97. {flixopt-2.1.7 → flixopt-2.1.9}/pics/flixopt-icon.svg +0 -0
  98. {flixopt-2.1.7 → flixopt-2.1.9}/pics/pics.pptx +0 -0
  99. {flixopt-2.1.7 → flixopt-2.1.9}/scripts/extract_release_notes.py +0 -0
  100. {flixopt-2.1.7 → flixopt-2.1.9}/setup.cfg +0 -0
  101. {flixopt-2.1.7 → flixopt-2.1.9}/tests/__init__.py +0 -0
  102. {flixopt-2.1.7 → flixopt-2.1.9}/tests/conftest.py +0 -0
  103. {flixopt-2.1.7 → flixopt-2.1.9}/tests/ressources/Zeitreihen2020.csv +0 -0
  104. {flixopt-2.1.7 → flixopt-2.1.9}/tests/run_all_tests.py +0 -0
  105. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_dataconverter.py +0 -0
  106. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_functional.py +0 -0
  107. {flixopt-2.1.7 → flixopt-2.1.9}/tests/test_results_plots.py +0 -0
  108. {flixopt-2.1.7 → flixopt-2.1.9}/tests/todos.txt +0 -0
@@ -2,12 +2,15 @@ name: Python Package CI/CD
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [main, dev] # Added develop branch
6
- tags:
7
- - 'v*.*.*' # Trigger on semantic version tags
5
+ branches: [main] # Only main branch
6
+ tags: ['v*.*.*']
8
7
  pull_request:
9
- branches: [main, dev, 'feature/*', 'hotfix/*', 'fix/*']
8
+ branches: [main, dev]
10
9
  types: [opened, synchronize, reopened]
10
+ paths-ignore:
11
+ - 'docs/**'
12
+ - '*.md'
13
+ - 'README*'
11
14
  workflow_dispatch: # Allow manual triggering
12
15
 
13
16
  # Set permissions for security
@@ -24,39 +27,40 @@ env:
24
27
 
25
28
  jobs:
26
29
  lint:
27
- runs-on: ubuntu-22.04
30
+ runs-on: ubuntu-24.04
28
31
  steps:
29
32
  - name: Check out code
30
33
  uses: actions/checkout@v5
31
34
 
35
+ - name: Set up uv
36
+ uses: astral-sh/setup-uv@v6
37
+ with:
38
+ version: "0.8.19"
39
+ enable-cache: true
40
+
32
41
  - name: Set up Python
33
42
  uses: actions/setup-python@v6
34
43
  with:
35
44
  python-version: ${{ env.PYTHON_VERSION }}
36
- cache: 'pip'
37
- cache-dependency-path: |
38
- pyproject.toml
39
45
 
40
46
  - name: Install Ruff
41
47
  run: |
42
- python -m pip install --upgrade pip
43
- pip install "ruff==0.9.*"
44
- ruff --version
48
+ uvx ruff --version
45
49
 
46
50
  - name: Run Ruff Linting
47
51
  run: |
48
52
  echo "::group::Ruff Linting"
49
- ruff check . --output-format=github
53
+ uvx ruff check . --output-format=github
50
54
  echo "::endgroup::"
51
55
 
52
56
  - name: Run Ruff Formatting Check
53
57
  run: |
54
58
  echo "::group::Ruff Formatting"
55
- ruff format --check --diff .
59
+ uvx ruff format --check --diff .
56
60
  echo "::endgroup::"
57
61
 
58
62
  test:
59
- runs-on: ubuntu-22.04
63
+ runs-on: ubuntu-24.04
60
64
  timeout-minutes: 30
61
65
  needs: lint # Run tests only after linting passes
62
66
  strategy:
@@ -68,49 +72,49 @@ jobs:
68
72
  - name: Check out code
69
73
  uses: actions/checkout@v5
70
74
 
75
+ - name: Set up uv
76
+ uses: astral-sh/setup-uv@v6
77
+ with:
78
+ version: "0.8.19"
79
+ enable-cache: true
80
+
71
81
  - name: Set up Python ${{ matrix.python-version }}
72
82
  uses: actions/setup-python@v6
73
83
  with:
74
84
  python-version: ${{ matrix.python-version }}
75
- cache: 'pip'
76
- cache-dependency-path: |
77
- pyproject.toml
78
85
 
79
86
  - name: Install dependencies
80
87
  run: |
81
- python -m pip install --upgrade pip
82
- pip install .[dev] pytest-xdist
88
+ uv pip install --system .[dev] "pytest-xdist==3.*"
83
89
 
84
90
  - name: Run tests
85
91
  run: pytest -v -p no:warnings --numprocesses=auto
86
92
 
87
93
  security:
88
94
  name: Security Scan
89
- runs-on: ubuntu-latest
95
+ runs-on: ubuntu-24.04
90
96
  needs: lint
91
97
  steps:
92
98
  - name: Check out code
93
99
  uses: actions/checkout@v5
94
100
 
101
+ - name: Set up uv
102
+ uses: astral-sh/setup-uv@v6
103
+ with:
104
+ version: "0.8.19"
105
+ enable-cache: true
106
+
95
107
  - name: Set up Python
96
108
  uses: actions/setup-python@v6
97
109
  with:
98
110
  python-version: ${{ env.PYTHON_VERSION }}
99
- cache: 'pip'
100
- cache-dependency-path: |
101
- pyproject.toml
102
-
103
- - name: Install security tools
104
- run: |
105
- python -m pip install --upgrade pip
106
- pip install bandit[toml]
107
111
 
108
112
  - name: Run Bandit security scan
109
113
  run: |
110
114
  # Gate on HIGH severity & MEDIUM confidence; produce JSON artifact
111
- bandit -r flixopt/ -c pyproject.toml -f json -o bandit-report.json -q -lll -ii
115
+ uvx bandit -r flixopt/ -c pyproject.toml -f json -o bandit-report.json -q --severity-level high --confidence-level medium
112
116
  # Human-readable output without affecting job status
113
- bandit -r flixopt/ -c pyproject.toml -q --exit-zero
117
+ uvx bandit -r flixopt/ -c pyproject.toml -q --exit-zero
114
118
 
115
119
  - name: Upload security reports
116
120
  uses: actions/upload-artifact@v4
@@ -122,7 +126,7 @@ jobs:
122
126
 
123
127
  create-release:
124
128
  name: Create GitHub Release
125
- runs-on: ubuntu-latest
129
+ runs-on: ubuntu-24.04
126
130
  permissions:
127
131
  contents: write
128
132
  needs: [lint, test, security]
@@ -134,6 +138,12 @@ jobs:
134
138
  with:
135
139
  fetch-depth: 0
136
140
 
141
+ - name: Set up uv
142
+ uses: astral-sh/setup-uv@v6
143
+ with:
144
+ version: "0.8.19"
145
+ enable-cache: true
146
+
137
147
  - name: Set up Python
138
148
  uses: actions/setup-python@v6
139
149
  with:
@@ -157,46 +167,54 @@ jobs:
157
167
 
158
168
  publish-testpypi:
159
169
  name: Publish to TestPyPI
160
- runs-on: ubuntu-22.04
170
+ runs-on: ubuntu-24.04
161
171
  needs: [test, create-release] # Run after tests and release creation
162
172
  if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # Only on tag push
163
173
  environment:
164
174
  name: testpypi
165
175
  url: https://test.pypi.org/p/flixopt
176
+ env:
177
+ SKIP_TESTPYPI_UPLOAD: "false"
166
178
 
167
179
  steps:
168
180
  - name: Checkout repository
169
181
  uses: actions/checkout@v5
170
182
 
183
+ - name: Set up uv
184
+ uses: astral-sh/setup-uv@v6
185
+ with:
186
+ version: "0.8.19"
187
+ enable-cache: true
188
+
171
189
  - name: Set up Python
172
190
  uses: actions/setup-python@v6
173
191
  with:
174
192
  python-version: ${{ env.PYTHON_VERSION }}
175
- cache: 'pip'
176
- cache-dependency-path: |
177
- pyproject.toml
178
193
 
179
194
  - name: Install dependencies
180
195
  run: |
181
- python -m pip install --upgrade pip
182
- pip install build setuptools wheel twine
196
+ uv pip install --system twine
183
197
 
184
198
  - name: Build the distribution
185
199
  run: |
186
- python -m build
200
+ uv build
187
201
 
188
202
  - name: Upload to TestPyPI
189
203
  run: |
190
- twine upload --repository-url https://test.pypi.org/legacy/ dist/* --verbose
204
+ twine upload --repository-url https://test.pypi.org/legacy/ dist/* --verbose --skip-existing
191
205
  env:
192
206
  TWINE_USERNAME: __token__
193
207
  TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
208
+ TWINE_NON_INTERACTIVE: "1"
194
209
 
195
210
  - name: Test install from TestPyPI
211
+ if: env.SKIP_TESTPYPI_UPLOAD != 'true'
196
212
  run: |
213
+ set -Eeuo pipefail
197
214
  # Create a temporary environment to test installation
198
- python -m venv test_env
215
+ uv venv test_env
199
216
  source test_env/bin/activate
217
+
200
218
  # Get project name from pyproject.toml (PEP 621)
201
219
  PACKAGE_NAME=$(python - <<'PY'
202
220
  import sys, tomllib, pathlib
@@ -204,15 +222,18 @@ jobs:
204
222
  print(data["project"]["name"])
205
223
  PY
206
224
  )
225
+
207
226
  # Extract version from git tag
208
227
  VERSION=${GITHUB_REF#refs/tags/v}
228
+
209
229
  # Wait and retry while TestPyPI indexes the package
210
230
  INSTALL_SUCCESS=false
211
- for d in 15 30 60 120 180 360 720 1080; do
231
+ for d in 10 20 40 80 120; do
212
232
  sleep "$d"
213
233
  echo "Attempting to install $PACKAGE_NAME==$VERSION from TestPyPI (retry after ${d}s)..."
234
+
214
235
  # Install specific version and verify it matches
215
- if pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "$PACKAGE_NAME==$VERSION" && \
236
+ if uv pip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "$PACKAGE_NAME==$VERSION" && \
216
237
  python -c "from importlib.metadata import version; installed = version('$PACKAGE_NAME'); print(f'Installed: {installed}'); assert '$VERSION' == installed"; then
217
238
  INSTALL_SUCCESS=true
218
239
  break
@@ -234,7 +255,7 @@ jobs:
234
255
 
235
256
  publish-pypi:
236
257
  name: Publish to PyPI
237
- runs-on: ubuntu-22.04
258
+ runs-on: ubuntu-24.04
238
259
  needs: [publish-testpypi] # Only run after TestPyPI publish succeeds
239
260
  if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # Only on tag push
240
261
  environment:
@@ -245,35 +266,40 @@ jobs:
245
266
  - name: Checkout repository
246
267
  uses: actions/checkout@v5
247
268
 
269
+ - name: Set up uv
270
+ uses: astral-sh/setup-uv@v6
271
+ with:
272
+ version: "0.8.19"
273
+ enable-cache: true
274
+
248
275
  - name: Set up Python
249
276
  uses: actions/setup-python@v6
250
277
  with:
251
278
  python-version: ${{ env.PYTHON_VERSION }}
252
- cache: 'pip'
253
- cache-dependency-path: |
254
- pyproject.toml
255
279
 
256
280
  - name: Install dependencies
257
281
  run: |
258
- python -m pip install --upgrade pip
259
- pip install build setuptools wheel twine
282
+ uv pip install --system twine
260
283
 
261
284
  - name: Build the distribution
262
285
  run: |
263
- python -m build
286
+ uv build
264
287
 
265
288
  - name: Upload to PyPI
266
289
  run: |
267
- twine upload dist/* --verbose
290
+ twine upload dist/* --verbose --skip-existing
268
291
  env:
269
292
  TWINE_USERNAME: __token__
270
293
  TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
294
+ TWINE_NON_INTERACTIVE: "1"
271
295
 
272
296
  - name: Verify PyPI installation
273
297
  run: |
298
+ set -Eeuo pipefail
274
299
  # Create a temporary environment to test installation
275
- python -m venv prod_test_env
300
+ uv venv prod_test_env
276
301
  source prod_test_env/bin/activate
302
+
277
303
  # Get project name from pyproject.toml (PEP 621)
278
304
  PACKAGE_NAME=$(python - <<'PY'
279
305
  import sys, tomllib, pathlib
@@ -281,15 +307,18 @@ jobs:
281
307
  print(data["project"]["name"])
282
308
  PY
283
309
  )
310
+
284
311
  # Extract version from git tag
285
312
  VERSION=${GITHUB_REF#refs/tags/v}
313
+
286
314
  # Wait and retry while PyPI indexes the package
287
315
  INSTALL_SUCCESS=false
288
- for d in 5 10 15 30 60 120 180 360 720 1080; do
316
+ for d in 10 20 40 80 120; do
289
317
  sleep "$d"
290
318
  echo "Attempting to install $PACKAGE_NAME==$VERSION from PyPI (retry after ${d}s)..."
319
+
291
320
  # Install specific version and verify it matches
292
- if pip install "$PACKAGE_NAME==$VERSION" && \
321
+ if uv pip install "$PACKAGE_NAME==$VERSION" && \
293
322
  python -c "from importlib.metadata import version; installed = version('$PACKAGE_NAME'); print(f'Installed: {installed}'); assert '$VERSION' == installed"; then
294
323
  INSTALL_SUCCESS=true
295
324
  break
@@ -311,7 +340,7 @@ jobs:
311
340
 
312
341
  deploy-docs:
313
342
  name: Deploy Documentation
314
- runs-on: ubuntu-22.04
343
+ runs-on: ubuntu-24.04
315
344
  permissions:
316
345
  contents: write
317
346
  needs: [publish-pypi] # Deploy docs after successful PyPI publishing
@@ -323,13 +352,16 @@ jobs:
323
352
  with:
324
353
  fetch-depth: 0 # Fetch all history for proper versioning
325
354
 
355
+ - name: Set up uv
356
+ uses: astral-sh/setup-uv@v6
357
+ with:
358
+ version: "0.8.19"
359
+ enable-cache: true
360
+
326
361
  - name: Set up Python
327
362
  uses: actions/setup-python@v6
328
363
  with:
329
364
  python-version: ${{ env.PYTHON_VERSION }}
330
- cache: 'pip'
331
- cache-dependency-path: |
332
- pyproject.toml
333
365
 
334
366
  - name: Sync changelog to docs
335
367
  run: |
@@ -338,8 +370,7 @@ jobs:
338
370
 
339
371
  - name: Install documentation dependencies
340
372
  run: |
341
- python -m pip install --upgrade pip
342
- pip install -e ".[docs]"
373
+ uv pip install --system ".[docs]"
343
374
 
344
375
  - name: Configure Git Credentials
345
376
  run: |
@@ -6,23 +6,64 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  <!-- This text won't be rendered
9
+ Note: The CI will automatically append a "What's Changed" section to the changelog.
10
+ This contains all commits, PRs, and contributors.
11
+ Therefore, the Changelog should focus on the user-facing changes.
12
+ Please remove all irrelevant sections before releasing.
9
13
 
10
- ## [Unreleased]
11
-
12
- ### Changed
14
+ ## [Unreleased] - ????-??-??
13
15
 
14
16
  ### Added
15
17
 
18
+ ### Changed
19
+
16
20
  ### Deprecated
17
21
 
22
+ ### Removed
23
+
18
24
  ### Fixed
19
25
 
20
26
  ### Known issues
21
27
 
22
- ### Development
28
+ ### *Development*
23
29
 
24
30
  Until here -->
25
31
 
32
+ ## [2.1.9] - 2025-09-23
33
+ Small Bugfix which was supposed to be fixed in 2.1.8
34
+
35
+ ### Fixed
36
+ - Fix error handling in network visualization if networkx is not installed.
37
+
38
+
39
+ ## [2.1.8] - 2025-09-22
40
+ This release focuses on code quality improvements, enhanced documentation, and bug fixes for heat pump components and visualization features.
41
+
42
+ ### Added
43
+ - Extra Check for HeatPumpWithSource.COP to be strictly > 1 to avoid division by zero
44
+ - Apply deterministic color assignment by using sorted() in `plotting.py`
45
+ - Add missing args in docstrings in `plotting.py`, `solvers.py`, and `core.py`.
46
+
47
+ ### Changed
48
+ - Greatly improved docstrings and documentation of all public classes
49
+ - Make path handling to be gentle about missing .html suffix in `plotting.py`
50
+ - Default for `relative_losses` in `Transmission` is now 0 instead of None
51
+ - Setter of COP in `HeatPumpWithSource` now completely overwrites the conversion factors, which is safer.
52
+ - Fix some docstrings in plotting.py
53
+ - Change assertions to raise Exceptions in `plotting.py`
54
+
55
+ ### Fixed
56
+ - Fix color scheme selection in network_app; color pickers now update when a scheme is selected.
57
+ - Fix error handling in network visualization if networkx is not installed.
58
+ - Fix broken links in docs.
59
+ - Fix COP getter and setter of `HeatPumpWithSource` returning and setting wrong conversion factors.
60
+ - Fix custom compression levels in `io.save_dataset_to_netcdf`
61
+ - Fix `total_max` did not work when total min was not used.
62
+
63
+ ### *Development*
64
+ - Pin dev dependencies to specific versions
65
+ - Improve CI workflows to run faster and smarter
66
+
26
67
  ## [2.1.7] - 2025-09-13
27
68
 
28
69
  This update is a maintenance release to improve Code Quality, CI and update the dependencies.
@@ -31,7 +72,7 @@ There are no changes or new features.
31
72
  ### Added
32
73
  - Added __version__ to flixopt
33
74
 
34
- ### Development
75
+ ### *Development*
35
76
  - ruff format the whole Codebase
36
77
  - Added renovate config
37
78
  - Added pre-commit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flixopt
3
- Version: 2.1.7
3
+ Version: 2.1.9
4
4
  Summary: Vector based energy and material flow optimization framework in Python.
5
5
  Author-email: "Chair of Building Energy Systems and Heat Supply, TU Dresden" <peter.stange@tu-dresden.de>, Felix Bumann <felixbumann387@gmail.com>, Felix Panitz <baumbude@googlemail.com>, Peter Stange <peter.stange@tu-dresden.de>
6
6
  Maintainer-email: Felix Bumann <felixbumann387@gmail.com>, Peter Stange <peter.stange@tu-dresden.de>
@@ -24,54 +24,58 @@ Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: numpy<3,>=1.21.5
26
26
  Requires-Dist: pandas<3,>=2.0.0
27
- Requires-Dist: linopy<0.5.8,>=0.5.7
27
+ Requires-Dist: xarray<2026.0,>=2024.2.0
28
+ Requires-Dist: linopy<0.6,>=0.5.1
28
29
  Requires-Dist: netcdf4<2,>=1.6.1
29
- Requires-Dist: PyYAML<7,>=6.0.0
30
- Requires-Dist: rich>=13.0.0
31
- Requires-Dist: tomli>=2.0.1; python_version < "3.11"
32
- Requires-Dist: highspy>=1.5.3
33
- Requires-Dist: matplotlib<4.0.0,>=3.5.2
34
- Requires-Dist: plotly<6.0.0,>=5.15.0
30
+ Requires-Dist: pyyaml<7,>=6.0.0
31
+ Requires-Dist: rich<15,>=13.0.0
32
+ Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
33
+ Requires-Dist: highspy<2,>=1.5.3
34
+ Requires-Dist: matplotlib<4,>=3.5.2
35
+ Requires-Dist: plotly<7,>=5.15.0
35
36
  Provides-Extra: network-viz
36
- Requires-Dist: dash>=3.0.0; extra == "network-viz"
37
- Requires-Dist: dash-cytoscape>=1.0.0; extra == "network-viz"
38
- Requires-Dist: dash-daq>=0.6.0; extra == "network-viz"
39
- Requires-Dist: networkx>=3.0.0; extra == "network-viz"
40
- Requires-Dist: werkzeug>=3.0.0; extra == "network-viz"
37
+ Requires-Dist: dash<4,>=3.0.0; extra == "network-viz"
38
+ Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "network-viz"
39
+ Requires-Dist: dash-daq<1,>=0.6.0; extra == "network-viz"
40
+ Requires-Dist: networkx<4,>=3.0.0; extra == "network-viz"
41
+ Requires-Dist: werkzeug<4,>=3.0.0; extra == "network-viz"
42
+ Requires-Dist: flask<4,>=3.0.0; extra == "network-viz"
41
43
  Provides-Extra: full
42
44
  Requires-Dist: pyvis==0.3.2; extra == "full"
43
- Requires-Dist: tsam<3.0.0,>=2.3.1; extra == "full"
44
- Requires-Dist: scipy<2.0.0,>=1.15.1; extra == "full"
45
- Requires-Dist: gurobipy>=10.0.0; extra == "full"
46
- Requires-Dist: dash>=3.0.0; extra == "full"
47
- Requires-Dist: dash-cytoscape>=1.0.0; extra == "full"
48
- Requires-Dist: dash-daq>=0.6.0; extra == "full"
49
- Requires-Dist: networkx>=3.0.0; extra == "full"
50
- Requires-Dist: werkzeug>=3.0.0; extra == "full"
45
+ Requires-Dist: tsam<3,>=2.3.1; extra == "full"
46
+ Requires-Dist: scipy<2,>=1.15.1; extra == "full"
47
+ Requires-Dist: gurobipy<13,>=10.0.0; extra == "full"
48
+ Requires-Dist: dash<4,>=3.0.0; extra == "full"
49
+ Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "full"
50
+ Requires-Dist: dash-daq<1,>=0.6.0; extra == "full"
51
+ Requires-Dist: networkx<4,>=3.0.0; extra == "full"
52
+ Requires-Dist: werkzeug<4,>=3.0.0; extra == "full"
53
+ Requires-Dist: flask<4,>=3.0.0; extra == "full"
51
54
  Provides-Extra: dev
52
- Requires-Dist: pytest>=7.0.0; extra == "dev"
53
- Requires-Dist: ruff>=0.9.0; extra == "dev"
54
- Requires-Dist: pre-commit>=4.0.0; extra == "dev"
55
+ Requires-Dist: pytest==8.4.2; extra == "dev"
56
+ Requires-Dist: nbformat==5.10.4; extra == "dev"
57
+ Requires-Dist: ruff==0.13.0; extra == "dev"
58
+ Requires-Dist: pre-commit==4.3.0; extra == "dev"
55
59
  Requires-Dist: pyvis==0.3.2; extra == "dev"
56
- Requires-Dist: tsam<3.0.0,>=2.3.1; extra == "dev"
57
- Requires-Dist: scipy<2.0.0,>=1.15.1; extra == "dev"
58
- Requires-Dist: gurobipy>=10.0.0; extra == "dev"
59
- Requires-Dist: dash>=3.0.0; extra == "dev"
60
- Requires-Dist: dash-cytoscape>=1.0.0; extra == "dev"
61
- Requires-Dist: dash-daq>=0.6.0; extra == "dev"
62
- Requires-Dist: networkx>=3.0.0; extra == "dev"
63
- Requires-Dist: werkzeug>=3.0.0; extra == "dev"
60
+ Requires-Dist: tsam==2.3.1; extra == "dev"
61
+ Requires-Dist: scipy==1.15.1; extra == "dev"
62
+ Requires-Dist: gurobipy==12.0.3; extra == "dev"
63
+ Requires-Dist: dash==3.0.0; extra == "dev"
64
+ Requires-Dist: dash-cytoscape==1.0.2; extra == "dev"
65
+ Requires-Dist: dash-daq==0.6.0; extra == "dev"
66
+ Requires-Dist: networkx==3.0.0; extra == "dev"
67
+ Requires-Dist: werkzeug==3.0.0; extra == "dev"
64
68
  Provides-Extra: docs
65
- Requires-Dist: mkdocs-material<10,>=9.0.0; extra == "docs"
66
- Requires-Dist: mkdocstrings-python>=1.0.0; extra == "docs"
67
- Requires-Dist: mkdocs-table-reader-plugin>=2.0.0; extra == "docs"
68
- Requires-Dist: mkdocs-gen-files>=0.4.0; extra == "docs"
69
- Requires-Dist: mkdocs-include-markdown-plugin>=6.0.0; extra == "docs"
70
- Requires-Dist: mkdocs-literate-nav>=0.6.0; extra == "docs"
71
- Requires-Dist: markdown-include>=0.8.0; extra == "docs"
72
- Requires-Dist: pymdown-extensions>=10.0.0; extra == "docs"
73
- Requires-Dist: pygments>=2.14.0; extra == "docs"
74
- Requires-Dist: mike>=2.0.0; extra == "docs"
69
+ Requires-Dist: mkdocs-material==9.6.19; extra == "docs"
70
+ Requires-Dist: mkdocstrings-python==1.18.2; extra == "docs"
71
+ Requires-Dist: mkdocs-table-reader-plugin==3.1.0; extra == "docs"
72
+ Requires-Dist: mkdocs-gen-files==0.5.0; extra == "docs"
73
+ Requires-Dist: mkdocs-include-markdown-plugin==7.1.7; extra == "docs"
74
+ Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "docs"
75
+ Requires-Dist: markdown-include==0.8.1; extra == "docs"
76
+ Requires-Dist: pymdown-extensions==10.16.1; extra == "docs"
77
+ Requires-Dist: pygments==2.19.2; extra == "docs"
78
+ Requires-Dist: mike==2.1.3; extra == "docs"
75
79
  Dynamic: license-file
76
80
 
77
81
  # FlixOpt: Energy and Material Flow Optimization Framework
@@ -3,5 +3,5 @@
3
3
  - [User Guide](user-guide/)
4
4
  - [Examples](examples/)
5
5
  - [Contribute](contribute.md)
6
- - [API-Reference](api-reference/)
6
+ - [API Reference](api-reference/)
7
7
  - [Release Notes](changelog.md)
@@ -19,7 +19,7 @@ This provides the core functionality with the HiGHS solver included.
19
19
  For all features including interactive network visualizations and time series aggregation:
20
20
 
21
21
  ```bash
22
- pip install "flixopt[full]""
22
+ pip install "flixopt[full]"
23
23
  ```
24
24
 
25
25
  ## Basic Workflow
@@ -38,5 +38,5 @@ Working with FlixOpt follows a general pattern:
38
38
  Now that you've installed FlixOpt and understand the basic workflow, you can:
39
39
 
40
40
  - Learn about the [core concepts of FlixOpt](user-guide/index.md)
41
- - Explore some [examples](examples/)
41
+ - Explore some [examples](examples/index.md)
42
42
  - Check the [API reference](api-reference/index.md) for detailed documentation
@@ -1,15 +1,15 @@
1
1
  ## Effects
2
- [`Effects`][flixopt.effects.Effect] are used to allocate things like costs, emissions, or other "effects" occuring in the system.
2
+ [`Effects`][flixopt.effects.Effect] are used to allocate things like costs, emissions, or other "effects" occurring in the system.
3
3
  These arise from so called **Shares**, which originate from **Elements** like [Flows](Flow.md).
4
4
 
5
5
  **Example:**
6
6
 
7
7
  [`Flows`][flixopt.elements.Flow] have an attribute called `effects_per_flow_hour`, defining the effect amount of per flow hour.
8
- Assiziated effects could be:
8
+ Associated effects could be:
9
9
  - costs - given in [€/kWh]...
10
10
  - ...or emissions - given in [kg/kWh].
11
11
  -
12
- Effects are allocated seperatly for investments and operation.
12
+ Effects are allocated separately for investments and operation.
13
13
 
14
14
  ### Shares to Effects
15
15
 
@@ -43,7 +43,7 @@ For example, the Effect "CO$_2$ emissions" (unit: kg)
43
43
  can cause an additional share to Effect "monetary costs" (unit: €).
44
44
  In this case, the factor $\text a_{x \rightarrow e}$ is the specific CO$_2$ price in €/kg. However, circular references have to be avoided.
45
45
 
46
- The overall sum of investment shares of an Effect $e$ is given by $\eqref{Effect_invest}$
46
+ The overall sum of investment shares of an Effect $e$ is given by $\eqref{eq:Effect_invest}$
47
47
 
48
48
  $$ \label{eq:Effect_invest}
49
49
  E_{e, \text{inv}} =
@@ -68,8 +68,8 @@ With:
68
68
 
69
69
  - $\mathcal{L}$ being the set of all elements in the FlowSystem
70
70
  - $\mathcal{E}$ being the set of all effects in the FlowSystem
71
- - $\text r_{x \rightarrow e, \text{inv}}$ being the factor between the operation part of Effect $x$ and Effect $e$
72
- - $\text r_{x \rightarrow e, \text{op}}(\text{t}_i)$ being the factor between the invest part of Effect $x$ and Effect $e$
71
+ - $\text r_{x \rightarrow e, \text{inv}}$ being the factor between the invest part of Effect $x$ and Effect $e$
72
+ - $\text r_{x \rightarrow e, \text{op}}(\text{t}_i)$ being the factor between the operation part of Effect $x$ and Effect $e$
73
73
 
74
74
  - $\text{t}_i$ being the time step
75
75
  - $s_{l \rightarrow e, \text{inv}}$ being the share of element $l$ to the investment part of effect $e$
@@ -113,7 +113,7 @@ With:
113
113
  - $\mathcal{T}$ being the set of all timesteps
114
114
  - $s_{l \rightarrow \Phi}$ being the share of element $l$ to the penalty
115
115
 
116
- At the moment, penalties only occur in [Buses](#buses)
116
+ At the moment, penalties only occur in [Buses](Bus.md)
117
117
 
118
118
  ## Objective
119
119
 
@@ -128,5 +128,5 @@ With:
128
128
  - $\Phi$ being the [Penalty](#penalty)
129
129
 
130
130
  This approach allows for a multi-criteria optimization using both...
131
- - ... the **Weigted Sum**Method, as the chosen **Objective Effect** can incorporate other Effects.
131
+ - ... the **Weighted Sum** method, as the chosen **Objective Effect** can incorporate other Effects.
132
132
  - ... the ($\epsilon$-constraint method) by constraining effects.
@@ -21,6 +21,6 @@ $$
21
21
  $$
22
22
 
23
23
 
24
- This mathematical Formulation can be extended or changed when using [OnOffParameters](#onoffparameters)
25
- to define the On/Off state of the Flow, or [InvestParameters](#investments),
26
- which changes the size of the Flow from a constant to an optimization variable.
24
+ This mathematical formulation can be extended by using [OnOffParameters](./OnOffParameters.md)
25
+ to define the on/off state of the Flow, or by using [InvestParameters](./InvestParameters.md)
26
+ to change the size of the Flow from a constant to an optimization variable.
@@ -0,0 +1,3 @@
1
+ # InvestParameters
2
+
3
+ This is a work in progress.
@@ -1,4 +1,4 @@
1
- [`LinearConverters`][flixopt.components.LinearConverter] define a ratio between incoming and outgoing [Flows](#flows).
1
+ [`LinearConverters`][flixopt.components.LinearConverter] define a ratio between incoming and outgoing [Flows](Flow.md).
2
2
 
3
3
  $$ \label{eq:Linear-Transformer-Ratio}
4
4
  \sum_{f_{\text{in}} \in \mathcal F_{in}} \text a_{f_{\text{in}}}(\text{t}_i) \cdot p_{f_\text{in}}(\text{t}_i) = \sum_{f_{\text{out}} \in \mathcal F_{out}} \text b_{f_\text{out}}(\text{t}_i) \cdot p_{f_\text{out}}(\text{t}_i)
@@ -16,6 +16,6 @@ $$ \label{eq:Linear-Transformer-Ratio-simple}
16
16
  \text a(\text{t}_i) \cdot p_{f_\text{in}}(\text{t}_i) = p_{f_\text{out}}(\text{t}_i)
17
17
  $$
18
18
 
19
- where $\text a$ can be interpreted as the conversion efficiency of the **LinearTransformer**.
20
- #### Piecewise Concersion factors
19
+ where $\text a$ can be interpreted as the conversion efficiency of the **LinearConverter**.
20
+ #### Piecewise Conversion factors
21
21
  The conversion efficiency can be defined as a piecewise linear approximation. See [Piecewise](Piecewise.md) for more details.
@@ -0,0 +1,3 @@
1
+ # OnOffParameters
2
+
3
+ This is a work in progress.
@@ -1,5 +1,5 @@
1
1
  # Storages
2
- **Storages** have one incoming and one outgoing **[Flow](#flows)** with a charging and discharging efficiency.
2
+ **Storages** have one incoming and one outgoing **[Flow](Flow.md)** with a charging and discharging efficiency.
3
3
  A storage has a state of charge $c(\text{t}_i)$ which is limited by its `size` $\text C$ and relative bounds $\eqref{eq:Storage_Bounds}$.
4
4
 
5
5
  $$ \label{eq:Storage_Bounds}