All notable changes to this project will be documented in this file. The format is based on Keep a Changelog and this project follows Semantic Versioning.
2.1.0 - 2026-08-11
- Add support for the Gever (Geschäftsverwaltungssystem) APIs of the canton and the city of Zurich as a backend, based on goifer
- Gever backend: with a usable schema, records are now fully flattened at any depth (e.g. a
mitgliederrecord'sperson->kontaktwrapper), instead of only a curated set of hardcoded field names - Gever backend: detect repeatable fields whose schema declares
maxOccurson the wrappingchoice/sequence/allinstead of on the element itself, fixing inconsistent dict-vs-list shapes for such fields (e.g.mitglieder'sBehoerdenmandat/Parteizugehoerigkeit) - Gever backend:
GeverResponse.explode()turns a list field into its ownDataFrame, one row per item, with the parent record'sobj_guidcarried along asparent_obj_guidto join back - Gever backend:
explode()is available on the result of the module level functions andSwissParlClientas well, not only on the backend response, and resolves a nested list field by its name (e.g.behoerdenmandateforperson_kontakt_behoerdenmandate) - Gever backend:
get_glimpse()only loads the rows it was asked for, instead of paging through the whole table as soon as the result is iterated over or converted to aDataFrame
- Gever backend: string values of keyword arguments are quoted and escaped in the generated CQL query, e.g.
get_data('mitglieder', vorname='Hans Peter')searches forvorname adj "Hans Peter". Before, a value with a space was rejected by the API with an HTTP 406 - Gever backend: a record with two containers of the same element no longer fails with
ValueError: duplicated key, e.g. the city'sgeschaeft, which holds aDepartementbelow bothFederfuehrendesDepartementandMitbeteiligteDepartemente. A list field now keeps the name of its container, so those columns arefederfuehrendesdepartement_departement_*andmitbeteiligtedepartemente(BC-Break for list fields that were named after the element they hold, e.g.behoerdenmandatis nowperson_kontakt_behoerdenmandateanddokumentofsitzungendetailis nowsitzungsdokumente) - Gever backend: a nested element whose name is only a part of the name of its parent keeps that parent as a prefix, e.g.
EndofSitzungsEndeissitzungsende_endinstead of a plainendthat collided with other columns
2.0.0 - 2026-07-30
- BC-Break: Python 3.10 is now required (Python 3.9 reached its end of life)
- BC-Break: OpenParlData backend:
search_scopeandsearch_modeare no longer overridden, the API defaults (metadataandpartial) apply. Passsearch_scope="all"explicitly to search the full-text indexes (Issue #52) - OpenParlData backend: an empty
searchparameter is no longer sent for unfiltered queries (Issue #52) - Improved
__repr__ofODataResponseandOpenParlDataResponseand added more logging when parsing responses
- Add more tests for edge cases and previously uncovered code paths
- Test Python 3.13 and 3.14 in the build matrix
- Document in the README and on the website that
limitis a page size (not a cap) and thatsearch_mode="exact"is case-sensitive in practice
- OpenParlData backend: don't send
lang="en"by default, which made tables likebodiesappear empty (Issue #52) - OpenParlData backend: only warn about unknown query attributes, the documented query parameters (
limit,offset,sort_by,fields, ...) no longer produce false positives (Issue #52) - OpenParlData backend: interpolate the table name in the unknown attribute warning (Issue #52)
- OpenParlData backend:
get_variables()andget_glimpse()now use the same language parameters asget_data(), so the variables match the returned columns - Fix type errors reported by mypy 2.x and pandas-stubs 3.x
- Run the OData backend tests again: the file name did not match the pytest pattern, so they were never collected
1.0.0 - 2026-02-25
- BC-Break: Python 3.9 is now required
- BC-Break: Renamed the callable filter from
swissparlpy.filtertoswissparlpy.Filter - Switched from
flittouvto install dependencies, build and publish the package
- Added the plotting functionality from
ggswissparl(Issue #9) - Added type hints in the library
- Add to_dataframe() convenience method to SwissParlResponse to directly transform a result to a DataFrame
- Detect server timeout and raise
SwissParlTimeoutErrorif necessary - Add support for multiple backends
- Add support for OpenParlData.ch as a backend (Issue #40)
0.3.0 - 2023-08-31
- Support for server-side pagination (transparent to the user)
ResultVeryLargeWarningto warn developers about very large queries- Logging to help with debugging
- Add pre-commit configuration
- Use
blackcode style
0.2.1 - 2022-01-31
- In order to fix issue #17 a bug in pyodata had to be fixed. pyodata 1.9.0 contains the bugfix and is now specified as the minimum version.
0.2.0 - 2021-10-14
- Jupyter notebook with examples
- New examples for advanced filters
- Support for more advanced filters
- Update README with examples
0.1.1 - 2021-09-27
- Typo in publish workflow
0.1.0 - 2021-09-27
- Test with fixtures
- Linter for all code
- Usage example in README
- Fixed
get_variablescall - Make sure
get_tablesreturns a list
0.0.2 - 2021-09-27
- Added CHANGELOG file
- Use flit to manage pypi package
0.0.1 - 2021-09-26
- Initial release of swissparlpy
Addedfor new features.Changedfor changes in existing functionality.Deprecatedfor once-stable features removed in upcoming releases.Removedfor deprecated features removed in this release.Fixedfor any bug fixes.Securityto invite users to upgrade in case of vulnerabilities.