v0.7 is a near-complete rewrite of Calliope's internals and of how models are defined, configured and solved.
Existing v0.6 models cannot be loaded in v0.7 and will need to be adapted.
All changes to model definition, configuration, parameter/decision variable names, removed features and new modelling capabilities relative to v0.6 are described in our migrating from v0.6 to v0.7 documentation.
Start there if you are coming from v0.6.
To avoid duplicating that guide, this entry covers only those changes that it does not describe.
This entry supersedes the 0.7.0.devX entries below, which are retained for reference but which include changes that were themselves superseded before this release.
User-facing changes
Python API
|changed| |backwards-incompatible| Models are loaded with calliope.read_yaml(path), calliope.read_dict(dict) and calliope.read_netcdf(path).
calliope.Model(...) takes in-memory xarray datasets, e.g. calliope.Model(inputs=input_array, attrs=attributes).
|changed| Model attributes are not stored in the input / result array attributes, but are available directly from the model object: model.definition (the loaded data definition), model.config (the loaded configuration), model.runtime (runtime attributes, including timing logs and model creation / build / solve timestamps) and model.math (initialised and applied math).
They can be dumped to a single dictionary with calliope.Model.dump_all_attrs().
|changed| Inputs and results are separate datasets (model.inputs / model.results) rather than filtered views on the same private dataset.
They are stored as separate NetCDF "groups", with model attributes stored as a further group and written to an attrs.yaml file by calliope.Model.to_csv.
|changed| kwargs in model.build() and model.solve() directly update model.config, to ensure the configuration always remains in sync with the results.
|changed| init config can be updated on re-init and on loading a model from NetCDF, e.g. to apply new subsetting, resampling, clustering or math.
|new| Backend interface methods available on calliope.Model.backend to inspect and manipulate the built optimisation problem, including get_objective / set_objective (to switch between pre-defined objectives), and shadow prices via model.backend.shadow_prices.get("constraint_name") (#716, #761).
Configuration
|new| config.init.retain_inactive (default False) keeps deactivated (active: false) components in the input arrays rather than deleting them, so that they can be re-activated after model instantiation but before building the optimisation problem.
|new| config.init.broadcast_input_data (default False) to broadcast single data entries in YAML indexed parameters along their indexed dimensions.
|new| config.init.pre_validate_math_strings (default False) to scan the math definition for parsing errors at model initialisation, i.e. before the much more expensive optimisation problem build.
|changed| config.init.datetime_format and config.init.date_format set the expected format of datetime- and date-dtype data read from file (both default to ISO8601).
|new| config.init.math_paths to name and point to additional math files, which can then be requested via config.build.extra_math or used to replace pre-defined math entries (base, milp, operate, spores, storage_inter_cluster).
|new| config.solve.shadow_prices to list constraints whose shadow prices should be added to the model results, as shadow_price_{constraint_name} arrays.
|new| config.solve.postprocess_active can be used to skip postprocessing, to save computation time or to avoid crashes if base math is made incompatible with it.
|changed| |backwards-incompatible| Updated to support Python >= 3.12, with critical dependency lower bounds of NumPy >= 2.0, pandas >= 2.1.3, xarray >= 2026.4, Pyomo >= 6.8.2 and pydantic >= 2.11.4 (#744, #889).
Dependencies are pinned on their lower bound only, to minimise clashes when using Calliope as a dependency in another project.
Math
|new| Pre-defined math is no longer hardcoded in Python.
Instead, it is split by mode and feature into separate YAML files - base.yaml, operate.yaml, spores.yaml, milp.yaml and storage_inter_cluster.yaml.
Each can be extended, or replaced entirely, by the user (#739, #749, #763).
|new| Math dictionaries can be injected when loading a model in Python, using the math_dict argument of calliope.read_yaml(...) / calliope.read_dict(...).
|new| cost_source_use parameter, for the variable cost of source_use in supply technologies.
cost_flow_in no longer applies to supply technologies (and cost_flow_out no longer applies to demand technologies); a warning is raised if they are defined (#835).
|changed| Math is accessed via model.math, with the applied math at model.math.build, e.g. model.math.build.parameters.flow_cap_max.default.
These attributes are no longer duplicated in the model array attributes.
|fixed| Technology capacity lower bound constraints, so that [cap-type]_min is not always enforced if the purchased_units variable is active (#643), and purchased_units is linked to flow_cap even if neither flow_cap_min nor flow_cap_max are defined.
|new| Gallery of user-defined math examples, including monthly peak charges (#727) and complex CHP plant operating spaces.
Backends and solvers
|changed| The backend interface is abstracted, to enable non-Pyomo solver interfaces.
|new| Direct interface to the Gurobi Python API (config.build.backend: gurobi), which reduces peak memory consumption and runtime of the combined build and solve steps by at least 30%.
Requires the gurobipy package.
|new| Direct interface to the open-source HiGHS solver (config.build.backend: highs) (#856).
Piecewise constraints are not yet available in this backend.
|changed| coin-or-cbc is available cross-platform on conda-forge and is the recommended open-source solver for access to full math functionality (#744, #891).
|new| Arbitrary updates to parameters can be passed to any solver backend and it will result in an appropriate re-build of the parts of the math that the parameter touches.
Modes
|new| Working SPORES mode, upgraded from v0.6 to include a selection of scoring algorithms (#716).
The baseline run is named 0 and the spores dimension has an integer dtype.
|new| config.solve.spores.use_latest_results allows a run to start from existing (e.g. base mode) results and to continue an existing set of SPORES.
E.g., if there are results for 4 SPORES, the run can be continued for 6 more iterations by setting spores.use_latest_results and updating spores.number to 10.
|fixed| SPORES mode models are appropriately serialised on saving to NetCDF (#751, #752).
Results and postprocessing
|new| Results contain the objective function value of solved models, in arrays named after the corresponding objective in math (e.g., model.results.min_cost_optimisation).
|changed| Cost expressions are split into the capital cost (cost_investment), its annualised equivalent (cost_investment_annualised), fixed operation costs (cost_operation_fixed) and variable operation costs (cost_operation_variable) (#645, #835).
|fixed| Levelised cost accounts for energy that is generated and exported (flow_export) (#767), timeseries capacity factor accounts for time resolution (#762), cost_om_annual_investment_fraction does not apply to depreciated costs (#645), and math for multi-carrier variable export costs is corrected (#663).
Time series handling
|changed| Time clustering is triggered by pointing config.init.time_cluster at the name of an input data array holding the date-to-representative-date mapping (e.g. loaded via data_tables).
|fixed| Time clustering handles cases where floating point errors can lead to index mismatches and dropped clusters (#826, #854).
|changed| Parameters declare how they should be aggregated when resampling the time dimension, with resample_method (one of mean, sum, first) in the math definition.
This was previously hardcoded in the source code and could not be updated by the user when supplying their own inputs.
Documentation
|changed| The documentation has been overhauled: ported to Markdown and built with MkDocs and the Material theme, with a migration guide from v0.6, an overview of Calliope terminology (including a visual depiction of how defined components connect together, #699), a dedicated section on defining your own math with its own helper function reference (#698), and clarified guidance on unit-agnosticism (#775), dimensions and broadcasting (#667) and dimension subsetting (#829).
|new| Math documentation is generated from the YAML math, including a list of pre-defined parameters, units, default values, cross-references in both directions ("uses" and "used in") (#643), and optional YAML snippet tabs when writing to Markdown.
Pre-defined operate mode math is documented alongside the other built-in math, and SPORES-specific configuration options are documented (#750, #752).
|changed| Community and help links point to Zulip (https://calliope-modelblocks.zulipchat.com/) instead of GitHub Discussions.
Internal changes
|changed| pydantic is used throughout to document and validate the model configuration, data tables, techs/nodes data, math and general model definition, replacing the JSON schema introduced earlier in the v0.7 development cycle (#704, #717, #868).
pydantic.RootModel is used for definition dictionaries with arbitrary keys (techs, nodes, etc.).
|changed| calliope.AttrDict is now only used to merge overrides and templates into the model definition dictionary, before creating the pydantic models; I/O has moved to calliope.io and attribute access to pydantic models.
AttrDict.union no longer sorts dictionary keys.
|changed| Model definition reading is defined in a single place (preprocess/model_definition.py) and pre-processed model data checks are conducted according to a YAML configuration instead of hard-coded Python functions.
|changed| Costs are backend expressions rather than decision variables.
|changed| Backend component arrays are built with numpy.frompyfunc instead of xarray.apply_ufunc, and default parameter values fill NaNs at expression evaluation time rather than when adding parameters to the backend, both reducing memory peaks.
|changed| Refactored the backend model class to separate out the logic to add different component types to the backend, and removed math conditionals where math component defaults achieve the same result.
|changed| Repository restructured to the src layout, relying on pyproject.toml for most configuration, with a py.typed marker so that mypy recognises Calliope as a typed library when imported as a dependency.
|changed| CI moved to GitHub Actions, with a stronger reliance on pre-commit (including a CI check in pull requests), Ruff for both linting (incl. pydocstyle, flake8-pytest and pyupgrade) and formatting, and a global test suite random seed to avoid randomly failing tests (#789).
|changed| Development dependency management moved to a mixture of uv and pixi (#881, #882), with rich added as a dev dependency for readable repr strings of our pydantic models.
|fixed| Removed the stderr redirect at the Pyomo backend solve stage, to avoid random infinite recursion errors in CI tests (#833).
|new| Automatic release uploads to PyPI, an accompanying pre-release pipeline, and a choice of issue templates.
Github history
- Unconcatenate sets and more by @brynpickering in #346
- Remove plotting completely (except from docs) by @sjpfenninger in #367
- Fix azure pipelines CI by @brynpickering in #383
- Rename master to main by @brynpickering in #394
- Merge in changes from v0.6.9 and v0.6.10 releases by @brynpickering in #395
- Add equation element parsing grammar by @brynpickering in #399
- Add upper bounds to all v0.7 dependencies by @brynpickering in #403
- Add arithmetic and equation comparison to equation parsing by @brynpickering in #400
- Formalise and test parsing of "foreach" by @brynpickering in #397
- Update azure pipelines config codecov upload by @brynpickering in #407
- Replace ObservedDict class with dicts in xarray attributes by @brynpickering in #406
- Add handling of constraint components and index items by @brynpickering in #405
- Update constraint "where" subsetting to strings that are parsed with pyparsing by @brynpickering in #408
- Feature yaml constraints evaluate expressions by @brynpickering in #409
- Speed up tests with session scope models on main by @brynpickering in #412
- Feature yaml constraints xarray backend by @brynpickering in #411
- Fix: Remove obsolete _datetime_to_string context manager by @jnnr in #415
- Feature: Allow to override constraint.yml with custom constraints by @jnnr in #414
- Feature: custom run mode math files by @brynpickering in #439
- Feature: Add coordinate reference to obj name strings by @brynpickering in #435
- Fix: Add objective (de)activation based on run config by @brynpickering in #438
- Fix: clearer parser errors by @brynpickering in #436
- Fix: Add method to delete empty pyomo list objects by @brynpickering in #437
- Feature: Add description and unit keys to YAML math components by @brynpickering in #440
- Update and clean docs by @brynpickering in #443
- Raise error when equations or expressions contain NaNs by @jnnr in #417
- Add LP comparison pipeline and one example by @brynpickering in #453
- Add resource_max constraint test by @sjpfenninger in #457
- Add test for constraint 'balance conversion' by @jnnr in #459
- Add test carrier production max by @FLomb in #458
- add test_storage_max by @FraSanvit in #460
- Fix: storage inter cluster custom math by @brynpickering in #434
- Feature: rename math syntax by @FraSanvit in #448
- Fix: remove old Pyomo backend code by @brynpickering in #462
- Feature: add math formulation documentation generator by @brynpickering in #442
- Remove references to
equationby @brynpickering in #464 - Model class cleanup: fix
info& remove empty method; add docstrings. by @brynpickering in #468 - Add math schema & validator; validate math files by @brynpickering in #454
- Update: reformat yaml and imports by @brynpickering in #463
- Remove use of
imaskby @brynpickering in #465 - Feature helper function classes by @brynpickering in #467
- Clean-up alongside dependency pinning updates by @brynpickering in #487
- Restructure project by @brynpickering in #488
- Feature: public methods to interface with new backend model instance by @brynpickering in #471
- Add set serialisation & check for lists in attrs by @brynpickering in #489
- Only run py39 and py310 on ubuntu by @brynpickering in #491
- Decision vars & global exprs in where strings by @brynpickering in #490
- Add ability to view constraint coords in LP files by @brynpickering in #493
- Update logging and include examples by @brynpickering in #492
- Update parameter names by @brynpickering in #494
- Remove
get_formatted_arrayby @brynpickering in #495 - Remove
_equalsand_scaleparameters by @brynpickering in #466 - No coverage by default by @brynpickering in #499
- exists -> active by @brynpickering in #500
- Update top level config params by @brynpickering in #497
- Update definition matrix by @brynpickering in #501
- Update badges and remove pdf gen from rtd by @brynpickering in #503
- Custom math examples by @brynpickering in #502
- Enable use of transmission techs in custom math by @brynpickering in #505
- Clean parsers by @brynpickering in #506
- Rip out lots of time-adjustment functionality by @brynpickering in #507
- Cleanup names and math docs by @brynpickering in #513
flow_eff->flow_in_effandflow_out_effby @brynpickering in #512- Bump to py3.12 support by @brynpickering in #519
- New model definition structure by @brynpickering in #518
- Add skeleton of mkdocs by @sjpfenninger in #526
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #516
- Add distance unit config item & default to km by @brynpickering in #529
- Add spell checking; fix spelling mistakes by @brynpickering in #530
- Update links; add link checker by @brynpickering in #527
- source_max etc. -> source_use_max etc.; merge purchased and units by @brynpickering in #533
- Add documentation for the math syntax by @brynpickering in #456
- Feature docs example notebooks by @brynpickering in #534
- Move remaining custom math examples to new docs by @sjpfenninger in #537
- Add method to load data sources into the model. by @brynpickering in #532
- Add operate mode by @brynpickering in #539
- Add shadow prices (duals) by @brynpickering in #540
- Documentation cleanup by @sjpfenninger in #538
- Fix broken markdown links in docs by @brynpickering in #545
- Add PyPI upload CI and release checklist by @brynpickering in #542
- Test different time resolutions by @brynpickering in #544
- Add per tech cyclic storage by @brynpickering in #543
- Protect PyPI upload with CI environment by @brynpickering in #547
- Clean up changelog by @brynpickering in #548
- Fix references between built backend components by @brynpickering in #549
- Make release checklist clickable by @brynpickering in #552
- Pre-release fixes by @brynpickering in #550
- Release v0.7.0.dev2 by @brynpickering in #553
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #556
- Purge
time_data_pathby @brynpickering in #561 - Documentation updates by @brynpickering in #559
- Handle different date formats in clustering by @brynpickering in #562
- Update math docs and handling of missing data by @brynpickering in #563
- Add mkdocs tabs option to math docs by @brynpickering in #564
- Force link between flow cap and purchased units in base math by @brynpickering in #566
- Minor docs fixes by @sjpfenninger in #557
- Add schema updater by @brynpickering in #568
- Release v0.7.0.dev3 by @brynpickering in #570
- Update CI action versions by @brynpickering in #571
- Add py.typed by @brynpickering in #572
- Coerce model dimension dtypes to numeric by @brynpickering in #575
- Remove sorting on attrdict key nesting by @brynpickering in #578
- Update dependencies by @brynpickering in #574
- Clean up warning capture by @brynpickering in #577
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #580
- Update PR template by @brynpickering in #589
- Attach model_creation and solve_complete timestamps to model data attrs by @sjpfenninger in #586
- Improve installation instructions by @sjpfenninger in #588
- Pin mkdocs to < 1.6 to get docs building again by @sjpfenninger in #591
- Pin to non-broken mkdocs-jupyter by @brynpickering in #595
- Shadow price configuration in YAML by @sjpfenninger in #587
- Purge spurious debug parameter by @irm-codebase in #611
- Feature better linting by @irm-codebase in #620
- Rename dimensions to dims in docs by @brynpickering in #621
- Sort ref ordering within components by @brynpickering in #623
- Update refs to
model.subset_time&run.objectiveby @brynpickering in #602 - Add
titleto math var and expr components by @brynpickering in #603 - Add record of single element attribute lists in IO by @brynpickering in #627
- Force minimum of one header row; Add to docs by @brynpickering in #596
- Fix: Update commit-ci codecov step by @brynpickering in #629
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #594
- Improved backend maintainability by @irm-codebase in #630
- Add pyupgrade to ruff config by @brynpickering in #631
- Feature: Gurobi backend interface by @brynpickering in #551
- Fix: Update operate mode and associated tests by @brynpickering in #628
- Feature: piecewise constraints by @brynpickering in #569
- Add tsam clustering example by @brynpickering in #636
- Fix rendering of 404 pages in the docs by @sjpfenninger in #647
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #649
- Fixes in docs and new data checks by @sstroemer in #644
- Remove array copy by @brynpickering in #666
- Fix multi carrier costs by @brynpickering in #664
- Fix contribution of
cost_om_annual_investment_fractionin math by @brynpickering in #657 - tech/node groups to templates by @brynpickering in #655
- Add
usescross-ref to math docs & collapsed admonitions by @brynpickering in #656 - De-boost reference docs; add search gadgets by @brynpickering in #671
- Update flow_cap_min description by @brynpickering in #672
- Fix math docs var domain by @brynpickering in #674
- Fix pr-ci pip-test environment installation by @sjpfenninger in #682
- Release v0.7.0.dev4 by @sjpfenninger in #681
- Update version to 0.7.0.dev5 by @sjpfenninger in #683
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #669
- Pin micromamba version in CI by @brynpickering in #691
data_sources->data_tables&source->databy @brynpickering in #688- Add param default and type to math docs by @brynpickering in #690
- Rework math handling by @irm-codebase in #639
- Remove pip env file; revert pipbuild env changes by @brynpickering in #689
- Update cost expression names & split out expressions by @brynpickering in #685
- Add data source dimension name mapping option by @brynpickering in #687
- Add templates for data tables by @brynpickering in #695
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #703
- Add
wherehelper function to enable reproduction of fancier group constraints by @brynpickering in #698 - Add simplistic mypy configuration by @irm-codebase in #707
- Fix pyomo breakage by @irm-codebase in #713
- Add
broadcast_param_dataconfig option and default it to False. by @brynpickering in #715 - Bump dawidd6/action-download-artifact from 3 to 6 in /.github/workflows by @dependabot[bot] in #718
- Update math lower bound capacity setting by @brynpickering in #700
- Update area units and
available_areadescription. by @brynpickering in #705 - Add missing kernel command in development instructions. by @irm-codebase in #721
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #722
- Update Calliope terminology description in docs by @brynpickering in #706
- Release v0.7.0.dev5 by @brynpickering in #724
- Feature attrdict and model definition declutter by @irm-codebase in #719
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #730
- Add config object to keep config in sync at all times by @brynpickering in #704
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #737
- Add config obj replace schemas by @irm-codebase in #717
- Update deps incl cbc by @brynpickering in #744
- Introduce SPORES in v0.7.0 by @FLomb in #716
- Release v0.7.0.dev6 by @brynpickering in #746
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #743
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #748
- Pin pydantic by @brynpickering in #755
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #757
- Unpin pydantic by @irm-codebase in #758
- Fix typos by @omahs in #760
- Fix save per SPORE & add SPORES docs by @brynpickering in #754
- Load math data during init by @irm-codebase in #756
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #765
- Docs fixes by @brynpickering in #769
- Update postprocessing funcs by @brynpickering in #774
- Add
group_datetimeandsum_next_nhelper functions by @brynpickering in #778 - Update piecewise cost expr in docs by @brynpickering in #779
- Fix gurobi expr eval by @brynpickering in #782
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #776
- Add random seed to spores tests by @brynpickering in #790
- Add
group_sumhelper function (potentially supersedesgroup_datetime) by @brynpickering in #784 - Update to inputs/results; separate attrs and store as pydantic model by @brynpickering in #771
- Refer to Calligraph docs for visualisation by @sjpfenninger in #791
- Fix
whereequality comparison operator by @irm-codebase in #795 - Add global expression order option by @brynpickering in #793
- Add spores continuation; baseline -> 0th SPORE by @brynpickering in #759
- Fix tracking set objective in the backend by @brynpickering in #799
- Fix separate milp math by @irm-codebase in #796
- Test param dim from init by @brynpickering in #783
- Add postprocess toggle by @irm-codebase in #812
- Update all YAML definitions with units and defaults by @brynpickering in #809
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #815
- Feature data definition by @irm-codebase in #816
- Postprocess: prevent exception when flow_cap lacks nodes dim by @sjpfenninger in #817
- Restructuring of docs by @sjpfenninger in #810
- Release v0.7.0.dev7 by @irm-codebase in #820
- Add hook to clean notebook pages in docs search index by @brynpickering in #828
- Remove _reentry; add runtime entries for timeseries agg/math updates by @brynpickering in #832
- Remove stderr redirect in pyomo backend by @brynpickering in #837
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #840
- Add cost source use & reorganise annual investment cost expression by @brynpickering in #835
- Simplify math conditionals by @brynpickering in #836
- Update parsing to allow math and dims in where strings by @brynpickering in #834
- Make gurobi warmstart test compatible with gurobi>=13 by @brynpickering in #846
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #841
- Postprocess yaml by @brynpickering in #839
- Add all test math lps by @brynpickering in #845
- Add tests for pre-defined math checks by @brynpickering in #847
- Restructure test directory; remove unused files and fixtures by @brynpickering in #849
- Fix/differing nodes techs in tables by @brynpickering in #848
data→tableandparameters→inputsin data table schema by @brynpickering in #855- Add monthly peak charging example; Fix example math tests by @brynpickering in #850
- Add new clustering approach & tests on long timeseries by @brynpickering in #854
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #857
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #863
- Update array default filling timing by @brynpickering in #864
- docs: load models with calliope.read_yaml in Running in Python guide by @SAY-5 in #871
- Small docstring typo fixes by @marijacveevska in #858
- Docs: restructuring by @sjpfenninger in #865
- Replace AttrDict with pydantic models in model data builder; add tests by @brynpickering in #868
- A few minor fixes for docs by @brynpickering in #872
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #875
- Update solver documentation (CPLEX) by @FLomb in #825
- Minor docs fixes by @sjpfenninger in #876
- Minor documentation fixes (part 2) by @sjpfenninger in #877
- Point to Zulip by @sjpfenninger in #878
- Consistent references to Calligraph by @sjpfenninger in #879
- All contributors by @sjpfenninger in #880
- Fix link-check false positives by @irm-codebase in #886
- Add non-code contributors to all-contributors by @sjpfenninger in #887
- pixi dependency management by @brynpickering in #882
- build: bump numpy lower bound to 2.0 by @xyf5432 in #889
- Add highs backend by @brynpickering in #856
- Refactor
activeby @brynpickering in #869 - Minor docs fixes for 0.7.0 by @sjpfenninger in #891
- Add operate mode to the docs ref page by @brynpickering in #893
- Various minor fixes in migration guide by @brynpickering in #894
- Release v0.7.0.dev8 by @irm-codebase in #895
- Release v0.7.0 by @brynpickering in #896
New Contributors
- @jnnr made their first contribution in #415
- @FraSanvit made their first contribution in #460
- @pre-commit-ci[bot] made their first contribution in #516
- @sstroemer made their first contribution in #644
- @dependabot[bot] made their first contribution in #718
- @omahs made their first contribution in #760
- @SAY-5 made their first contribution in #871
- @marijacveevska made their first contribution in #858
- @xyf5432 made their first contribution in #889
Full Changelog: v0.6.7...v0.7.0