pax_global_header 0000666 0000000 0000000 00000000064 14755342216 0014523 g ustar 00root root 0000000 0000000 52 comment=4c4ba2cfcd104fa7f319e870ea821a925996e394
tjorim-pyrail-4c4ba2c/ 0000775 0000000 0000000 00000000000 14755342216 0015011 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/.devcontainer/ 0000775 0000000 0000000 00000000000 14755342216 0017550 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/.devcontainer/devcontainer.json 0000664 0000000 0000000 00000002602 14755342216 0023124 0 ustar 00root root 0000000 0000000 // For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "Python Dev Container",
"image": "mcr.microsoft.com/devcontainers/python:3.12",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers-extra/features/poetry:2": {},
"ghcr.io/devcontainers-extra/features/ruff:1": {},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "poetry install",
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"charliermarsh.ruff",
"github.vscode-pull-request-github",
"ms-python.python"
],
"settings": {
"files.eol": "\n",
"editor.tabSize": 4,
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.formatOnType": false,
"files.trimTrailingWhitespace": true,
"python.analysis.typeCheckingMode": "basic",
"python.analysis.autoImportCompletions": true,
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
}
},
"remoteUser": "vscode"
} tjorim-pyrail-4c4ba2c/.gitattributes 0000664 0000000 0000000 00000000023 14755342216 0017677 0 ustar 00root root 0000000 0000000 * text=auto eol=lf
tjorim-pyrail-4c4ba2c/.github/ 0000775 0000000 0000000 00000000000 14755342216 0016351 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/.github/dependabot.yml 0000664 0000000 0000000 00000000315 14755342216 0021200 0 ustar 00root root 0000000 0000000 version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
tjorim-pyrail-4c4ba2c/.github/workflows/ 0000775 0000000 0000000 00000000000 14755342216 0020406 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/.github/workflows/build.yml 0000664 0000000 0000000 00000000675 14755342216 0022240 0 ustar 00root root 0000000 0000000 name: Build Package
on:
push:
branches:
- main
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install dependencies
run: |
pip install poetry
poetry install
- name: Build the package
run: poetry build
tjorim-pyrail-4c4ba2c/.github/workflows/lint.yml 0000664 0000000 0000000 00000000677 14755342216 0022111 0 ustar 00root root 0000000 0000000 name: Lint with Ruff
on:
push:
branches:
- main
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install dependencies
run: |
pip install poetry
poetry install
- name: Run Ruff
run: poetry run ruff check .
tjorim-pyrail-4c4ba2c/.github/workflows/publish.yml 0000664 0000000 0000000 00000002323 14755342216 0022577 0 ustar 00root root 0000000 0000000 name: Publish to PyPI
on:
push:
tags:
- "v*" # Trigger on tags starting with 'v' (e.g., v1.0.0, v1.2.3)
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install Poetry and dependencies
run: |
pip install poetry
poetry install
- name: Extract version from Git tag
id: version
run: |
VERSION=$(echo ${GITHUB_REF} | sed 's/refs\/tags\/v//') # Strip 'v' prefix
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Bump version in pyproject.toml
run: |
poetry version $VERSION
poetry lock
- name: Push version bump to main
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add pyproject.toml poetry.lock
git commit -m "Bump version to $VERSION"
git push origin HEAD:main # Push from detached HEAD directly to main
- name: Build the package and publish to PyPI
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
run: poetry publish --build
tjorim-pyrail-4c4ba2c/.github/workflows/test.yml 0000664 0000000 0000000 00000000665 14755342216 0022117 0 ustar 00root root 0000000 0000000 name: Run Tests
on:
push:
branches:
- main
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install dependencies
run: |
pip install poetry
poetry install
- name: Run tests
run: poetry run pytest
tjorim-pyrail-4c4ba2c/.gitignore 0000664 0000000 0000000 00000001443 14755342216 0017003 0 ustar 00root root 0000000 0000000 # Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Virtual environment
env/
.venv/
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Pytest cache
.pytest_cache/
# IDE files
.vscode/
.idea/
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
tjorim-pyrail-4c4ba2c/LICENSE 0000664 0000000 0000000 00000026135 14755342216 0016025 0 ustar 00root root 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
tjorim-pyrail-4c4ba2c/README.md 0000664 0000000 0000000 00000014420 14755342216 0016271 0 ustar 00root root 0000000 0000000 # pyRail
An async Python wrapper for the iRail API, designed to make interacting with iRail simple and efficient.
Built with aiohttp, it provides non-blocking I/O operations for optimal performance in async applications.
## Overview
pyRail is a Python library that provides a convenient interface for interacting with the iRail API. It supports various endpoints such as stations, liveboard, vehicle, connections, and disturbances. The library includes features like caching and rate limiting to optimize API usage.
## Features
- Async handling
- Retrieve real-time train information, including liveboards and vehicle details.
- Access train station data, connections, and disturbances.
- Supports API endpoints: stations, liveboard, vehicle, connections, and disturbances.
- Caching and conditional GET requests using ETags.
- Rate limiting to handle API request limits efficiently.
## Installation
To install pyRail, use pip:
```bash
pip install pyrail
```
## Usage
Here is an example of how to use pyRail asynchronously:
```python
import asyncio
from pyrail.irail import iRail
async def main():
# Sequential requests example
async with iRail() as api:
try:
# Get the total number of stations
stations = await api.get_stations()
if stations:
print(f"Total stations: {len(stations)}")
# Example output: Total stations: 691
# stations = [
# {"name": "Brussels-South", "id": "BE.NMBS.008814001", ...},
# ...
# ]
# Get the liveboard for a specific station
liveboard = await api.get_liveboard(station='Brussels-South')
if liveboard:
print(f"Liveboard for Brussels-South: {liveboard}")
except Exception as e:
print(f"Error occurred: {e}")
# Parallel requests example
async with iRail() as api:
try:
connections, vehicle_info = await asyncio.gather(
# Get connections between stations
api.get_connections(
from_station='Antwerpen-Centraal',
to_station='Brussel-Centraal'
),
# Get vehicle information
api.get_vehicle("BE.NMBS.IC1832")
)
print("Parallel results:")
print(f"Connections from Antwerpen-Centraal to Brussel-Centraal: {connections}")
print(f"Vehicle information for BE.NMBS.IC1832: {vehicle_info}")
except Exception as e:
print(f"Error occurred in parallel requests: {e}")
# Run the async code
if __name__ == "__main__":
asyncio.run(main())
```
### Language Selection
You can configure the language for the API requests:
```python
api = iRail(lang='nl')
```
Supported languages are:
- `en` (English, default)
- `fr` (French)
- `de` (German)
- `nl` (Dutch)
If no language is specified or an invalid value is provided, English (`en`) will be used as the default language.
### Session Management
You can provide an external aiohttp ClientSession:
```python
from aiohttp import ClientSession
async def main():
# Using an external session
async with ClientSession() as session:
async with iRail(session=session) as api:
stations = await api.get_stations()
print(f"Total stations: {len(stations)}")
# Or let iRail manage its own session
async with iRail() as api:
stations = await api.get_stations()
```
### Cache Management
You can clear the ETag cache when needed:
```python
async with iRail() as api:
# Clear the ETag cache
api.clear_etag_cache()
# Subsequent requests will fetch fresh data
stations = await api.get_stations()
```
### Rate Limiting
pyRail implements rate limiting to comply with iRail API's guidelines:
- Maximum of 3 requests per second per source IP address
- 5 burst requests available, allowing up to 8 requests in 1 second
The library automatically handles rate limiting:
```python
# Rate limiting is handled automatically
async with iRail() as api:
# These requests will be rate-limited if needed
for station in ['Brussels-South', 'Antwerp-Central', 'Ghent-Sint-Pieters']:
liveboard = await api.get_liveboard(station=station)
```
Exceeding the request limit will cause the server to return 429 responses. You can monitor rate limiting through debug logs.
## Development
The devcontainer setup includes all necessary dependencies and tools for development.
### Prerequisites
- Docker
- Visual Studio Code
- Remote - Containers extension
### Setup
1. Clone the repository:
```bash
git clone https://github.com/tjorim/pyrail.git
```
2. Open the project in a devcontainer:
```bash
cd pyrail
code .
```
3. Once VS Code opens, it will detect the devcontainer configuration and prompt you to reopen the project in a container. Click "Reopen in Container" to start the development environment.
### Running Tests
To run the tests, use the following command in the terminal within the devcontainer:
```bash
pytest
```
### Code Style
We use ruff for code formatting and linting. To check your code style, run:
```bash
ruff check .
```
To automatically fix style issues, run:
```bash
ruff check . --fix
```
## Logging
pyRail uses Python's built-in logging module. You can set the logging level at runtime to get detailed logs.
```python
import logging
# Set the logging level to DEBUG
logging.basicConfig(level=logging.DEBUG)
```
## Contributing
Contributions are welcome! Here's how you can contribute to pyRail:
### Issue Reporting
- Use the GitHub issue tracker to report bugs or suggest features.
- Check existing issues before opening a new one.
- Provide as much detail as possible, including steps to reproduce for bugs.
### Pull Requests
1. Fork the repository and create your branch from `main`.
2. Ensure your code adheres to the project's style guidelines (run `ruff check .`).
3. Add or update tests as necessary.
4. Update documentation to reflect your changes.
5. Submit a pull request with a clear title and description.
6. Your pull request will be automatically reviewed by CodeRabbit for code quality and consistency.
## Contributors
- @tjorim
- @jcoetsie
- @lgnap
## License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
tjorim-pyrail-4c4ba2c/examples/ 0000775 0000000 0000000 00000000000 14755342216 0016627 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/examples/composition.json 0000664 0000000 0000000 00000047224 14755342216 0022076 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736291958",
"composition": {
"segments": {
"number": "1",
"segment": [
{
"id": "0",
"origin": {
"@id": "http: //irail.be/stations/NMBS/008891702",
"id": "BE.NMBS.008891702",
"name": "Ostend",
"locationX": "2.925809",
"locationY": "51.228212",
"standardname": "Oostende"
},
"destination": {
"@id": "http://irail.be/stations/NMBS/008844628",
"id": "BE.NMBS.008844628",
"name": "Eupen",
"locationX": "6.03711",
"locationY": "50.635157",
"standardname": "Eupen"
},
"composition": {
"source": "Mistral",
"units": {
"number": "12",
"unit": [
{
"id": "0",
"materialType": {
"parent_type": "HLE18",
"sub_type": "",
"orientation": "LEFT"
},
"hasToilets": "0",
"hasSecondClassOutlets": "0",
"hasFirstClassOutlets": "0",
"hasHeating": "0",
"hasAirco": "0",
"tractionType": "HLE",
"canPassToNextUnit": "0",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "0",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "20",
"hasSemiAutomaticInteriorDoors": "0",
"tractionPosition": "1",
"hasPrmSection": "0",
"hasPriorityPlaces": "0",
"hasBikeSection": "0"
},
{
"id": "1",
"materialType": {
"parent_type": "M7",
"sub_type": "BUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "140",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "27",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "2",
"materialType": {
"parent_type": "M7",
"sub_type": "BUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "140",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "27",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "3",
"materialType": {
"parent_type": "M7",
"sub_type": "BUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "140",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "27",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "4",
"materialType": {
"parent_type": "M7",
"sub_type": "ABUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "58",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "74",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "27",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "5",
"materialType": {
"parent_type": "M7",
"sub_type": "ABUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "58",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "74",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "27",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "6",
"materialType": {
"parent_type": "M7",
"sub_type": "ABUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "58",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "74",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "27",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "7",
"materialType": {
"parent_type": "I10",
"sub_type": "BVUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "0",
"hasFirstClassOutlets": "0",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "76",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "26",
"hasSemiAutomaticInteriorDoors": "0",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "1"
},
{
"id": "8",
"materialType": {
"parent_type": "I10",
"sub_type": "BVUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "0",
"hasFirstClassOutlets": "0",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "76",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "26",
"hasSemiAutomaticInteriorDoors": "0",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "1"
},
{
"id": "9",
"materialType": {
"parent_type": "I11",
"sub_type": "BUH",
"orientation": "LEFT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "80",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "26",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "10",
"materialType": {
"parent_type": "I11",
"sub_type": "BUH",
"orientation": "RIGHT"
},
"hasToilets": "1",
"hasSecondClassOutlets": "1",
"hasFirstClassOutlets": "1",
"hasHeating": "1",
"hasAirco": "1",
"tractionType": "HV",
"canPassToNextUnit": "1",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "80",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "26",
"hasSemiAutomaticInteriorDoors": "1",
"tractionPosition": "2",
"hasPrmSection": "0",
"hasPriorityPlaces": "1",
"hasBikeSection": "0"
},
{
"id": "11",
"materialType": {
"parent_type": "HLE18",
"sub_type": "",
"orientation": "RIGHT"
},
"hasToilets": "0",
"hasSecondClassOutlets": "0",
"hasFirstClassOutlets": "0",
"hasHeating": "0",
"hasAirco": "0",
"tractionType": "HLE",
"canPassToNextUnit": "0",
"seatsFirstClass": "0",
"seatsCoupeFirstClass": "0",
"standingPlacesFirstClass": "0",
"seatsSecondClass": "0",
"seatsCoupeSecondClass": "0",
"standingPlacesSecondClass": "0",
"lengthInMeter": "20",
"hasSemiAutomaticInteriorDoors": "0",
"tractionPosition": "3",
"hasPrmSection": "0",
"hasPriorityPlaces": "0",
"hasBikeSection": "0"
}
]
}
}
}
]
}
}
} tjorim-pyrail-4c4ba2c/examples/connections.json 0000664 0000000 0000000 00000167733 14755342216 0022065 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736202453",
"connection": [
{
"id": "0",
"departure": {
"delay": "0",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736202960",
"vehicle": "BE.NMBS.IC723",
"vehicleinfo": {
"name": "BE.NMBS.IC723",
"shortname": "IC 723",
"number": "723",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC723"
},
"platform": "11",
"platforminfo": {
"name": "11",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "4",
"stop": [
{
"id": "0",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"scheduledArrivalTime": "1736203200",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736203320",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "1",
"station": "Sint-Niklaas",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
"scheduledArrivalTime": "1736204280",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736204400",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "2",
"station": "Lokeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
"scheduledArrivalTime": "1736204940",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736205000",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "3",
"station": "Ghent-Dampoort",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
"scheduledArrivalTime": "1736205720",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736205840",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8821006/20250106/IC723",
"direction": {
"name": "Ghent-Sint-Pieters"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"arrival": {
"delay": "0",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736206380",
"vehicle": "BE.NMBS.IC723",
"vehicleinfo": {
"name": "BE.NMBS.IC723",
"shortname": "IC 723",
"number": "723",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC723"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Ghent-Sint-Pieters"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8892007/20250107/IC723"
},
"duration": "3420",
"remarks": {
"number": "0",
"remark": []
},
"alerts": {
"number": "0",
"alert": []
}
},
{
"id": "1",
"departure": {
"delay": "0",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736220900",
"vehicle": "BE.NMBS.IC704",
"vehicleinfo": {
"name": "BE.NMBS.IC704",
"shortname": "IC 704",
"number": "704",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC704"
},
"platform": "2",
"platforminfo": {
"name": "2",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "4",
"stop": [
{
"id": "0",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"scheduledArrivalTime": "1736221140",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736221200",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "1",
"station": "Sint-Niklaas",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
"scheduledArrivalTime": "1736222280",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736222400",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "2",
"station": "Lokeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
"scheduledArrivalTime": "1736222940",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736223000",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "3",
"station": "Ghent-Dampoort",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
"scheduledArrivalTime": "1736223720",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736223840",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8821006/20250107/IC704",
"direction": {
"name": "Poperinge"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"arrival": {
"delay": "0",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736224320",
"vehicle": "BE.NMBS.IC704",
"vehicleinfo": {
"name": "BE.NMBS.IC704",
"shortname": "IC 704",
"number": "704",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC704"
},
"platform": "8",
"platforminfo": {
"name": "8",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Poperinge"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8892007/20250107/IC704"
},
"duration": "3420",
"remarks": {
"number": "0",
"remark": []
},
"alerts": {
"number": "0",
"alert": []
}
},
{
"id": "2",
"departure": {
"delay": "0",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736222760",
"vehicle": "BE.NMBS.IC1826",
"vehicleinfo": {
"name": "BE.NMBS.IC1826",
"shortname": "IC 1826",
"number": "1826",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1826"
},
"platform": "23",
"platforminfo": {
"name": "23",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "6",
"stop": [
{
"id": "0",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"scheduledArrivalTime": "1736223000",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736223120",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "1",
"station": "Antwerp-South",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821196",
"id": "BE.NMBS.008821196",
"name": "Antwerp-South",
"locationX": "4.390259",
"locationY": "51.197828",
"standardname": "Antwerpen-Zuid"
},
"scheduledArrivalTime": "1736223360",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736223420",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "2",
"station": "Beveren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894748",
"id": "BE.NMBS.008894748",
"name": "Beveren",
"locationX": "4.25952",
"locationY": "51.208336",
"standardname": "Beveren"
},
"scheduledArrivalTime": "1736223900",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736223960",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "3",
"station": "Sint-Niklaas",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
"scheduledArrivalTime": "1736224380",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736224560",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "4",
"station": "Lokeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
"scheduledArrivalTime": "1736225100",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736225160",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "5",
"station": "Ghent-Dampoort",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
"scheduledArrivalTime": "1736225880",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736226000",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8821006/20250107/IC1826",
"direction": {
"name": "Ostend"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"arrival": {
"delay": "0",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736226480",
"vehicle": "BE.NMBS.IC1826",
"vehicleinfo": {
"name": "BE.NMBS.IC1826",
"shortname": "IC 1826",
"number": "1826",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1826"
},
"platform": "11",
"platforminfo": {
"name": "11",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Ostend"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8892007/20250107/IC1826"
},
"duration": "3720",
"remarks": {
"number": "0",
"remark": []
},
"alerts": {
"number": "0",
"alert": []
}
},
{
"id": "3",
"departure": {
"delay": "0",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736224560",
"vehicle": "BE.NMBS.IC705",
"vehicleinfo": {
"name": "BE.NMBS.IC705",
"shortname": "IC 705",
"number": "705",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC705"
},
"platform": "2",
"platforminfo": {
"name": "2",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "4",
"stop": [
{
"id": "0",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"scheduledArrivalTime": "1736224800",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736224920",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "1",
"station": "Sint-Niklaas",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
"scheduledArrivalTime": "1736225880",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736226000",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "2",
"station": "Lokeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
"scheduledArrivalTime": "1736226540",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736226600",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "3",
"station": "Ghent-Dampoort",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
"scheduledArrivalTime": "1736227320",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736227440",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8821006/20250107/IC705",
"direction": {
"name": "Lille Flandres"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"arrival": {
"delay": "0",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736227980",
"vehicle": "BE.NMBS.IC705",
"vehicleinfo": {
"name": "BE.NMBS.IC705",
"shortname": "IC 705",
"number": "705",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC705"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Lille Flandres"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8892007/20250107/IC705"
},
"duration": "3420",
"remarks": {
"number": "0",
"remark": []
},
"alerts": {
"number": "0",
"alert": []
}
},
{
"id": "4",
"departure": {
"delay": "0",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736225280",
"vehicle": "BE.NMBS.IC2605",
"vehicleinfo": {
"name": "BE.NMBS.IC2605",
"shortname": "IC 2605",
"number": "2605",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2605"
},
"platform": "24",
"platforminfo": {
"name": "24",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "1",
"stop": [
{
"id": "0",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"scheduledArrivalTime": "1736225520",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736225580",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8821006/20250107/IC2605",
"direction": {
"name": "Hasselt"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"arrival": {
"delay": "0",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736229780",
"vehicle": "BE.NMBS.IC4127",
"vehicleinfo": {
"name": "BE.NMBS.IC4127",
"shortname": "IC 4127",
"number": "4127",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC4127"
},
"platform": "8",
"platforminfo": {
"name": "8",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Ghent-Sint-Pieters"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8892007/20250107/IC4127"
},
"vias": {
"number": "1",
"via": [
{
"id": "0",
"arrival": {
"delay": "0",
"station": "Mechelen",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008822004",
"id": "BE.NMBS.008822004",
"name": "Mechelen",
"locationX": "4.482785",
"locationY": "51.017648",
"standardname": "Mechelen"
},
"time": "1736226360",
"vehicle": "BE.NMBS.IC2605",
"vehicleinfo": {
"name": "BE.NMBS.IC2605",
"shortname": "IC 2605",
"number": "2605",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2605"
},
"platform": "12",
"platforminfo": {
"name": "12",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Hasselt"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8822004/20250107/IC2605"
},
"departure": {
"delay": "0",
"station": "Mechelen",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008822004",
"id": "BE.NMBS.008822004",
"name": "Mechelen",
"locationX": "4.482785",
"locationY": "51.017648",
"standardname": "Mechelen"
},
"time": "1736226900",
"vehicle": "BE.NMBS.IC4127",
"vehicleinfo": {
"name": "BE.NMBS.IC4127",
"shortname": "IC 4127",
"number": "4127",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC4127"
},
"platform": "6",
"platforminfo": {
"name": "6",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "3",
"stop": [
{
"id": "0",
"station": "Londerzeel",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008822111",
"id": "BE.NMBS.008822111",
"name": "Londerzeel",
"locationX": "4.299073",
"locationY": "51.009091",
"standardname": "Londerzeel"
},
"scheduledArrivalTime": "1736227560",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736227620",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "1",
"station": "Dendermonde",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893401",
"id": "BE.NMBS.008893401",
"name": "Dendermonde",
"locationX": "4.101427",
"locationY": "51.022781",
"standardname": "Dendermonde"
},
"scheduledArrivalTime": "1736228160",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736228400",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "2",
"station": "Wetteren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893559",
"id": "BE.NMBS.008893559",
"name": "Wetteren",
"locationX": "3.881883",
"locationY": "51.001603",
"standardname": "Wetteren"
},
"scheduledArrivalTime": "1736229060",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736229120",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8822004/20250107/IC4127",
"direction": {
"name": "Ghent-Sint-Pieters"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"timebetween": "540",
"station": "Mechelen",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008822004",
"id": "BE.NMBS.008822004",
"name": "Mechelen",
"locationX": "4.482785",
"locationY": "51.017648",
"standardname": "Mechelen"
},
"vehicle": "BE.NMBS.IC4127",
"vehicleinfo": {
"name": "BE.NMBS.IC4127",
"shortname": "IC 4127",
"number": "4127",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC4127"
}
}
]
},
"duration": "4500",
"remarks": {
"number": "0",
"remark": []
},
"alerts": {
"number": "0",
"alert": []
}
},
{
"id": "5",
"departure": {
"delay": "0",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736226360",
"vehicle": "BE.NMBS.IC1827",
"vehicleinfo": {
"name": "BE.NMBS.IC1827",
"shortname": "IC 1827",
"number": "1827",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1827"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "1"
},
"canceled": "0",
"stops": {
"number": "6",
"stop": [
{
"id": "0",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"scheduledArrivalTime": "1736226600",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736226720",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "1",
"station": "Antwerp-South",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821196",
"id": "BE.NMBS.008821196",
"name": "Antwerp-South",
"locationX": "4.390259",
"locationY": "51.197828",
"standardname": "Antwerpen-Zuid"
},
"scheduledArrivalTime": "1736226960",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736227020",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "2",
"station": "Beveren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894748",
"id": "BE.NMBS.008894748",
"name": "Beveren",
"locationX": "4.25952",
"locationY": "51.208336",
"standardname": "Beveren"
},
"scheduledArrivalTime": "1736227500",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736227560",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "3",
"station": "Sint-Niklaas",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
"scheduledArrivalTime": "1736227980",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736228160",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "4",
"station": "Lokeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
"scheduledArrivalTime": "1736228700",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736228760",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
},
{
"id": "5",
"station": "Ghent-Dampoort",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
"scheduledArrivalTime": "1736229480",
"arrivalCanceled": "0",
"arrived": "0",
"scheduledDepartureTime": "1736229540",
"arrivalDelay": "0",
"departureDelay": "0",
"departureCanceled": "0",
"left": "0",
"isExtraStop": "0",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
}
}
]
},
"departureConnection": "http://irail.be/connections/8821006/20250107/IC1827",
"direction": {
"name": "Ostend"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
}
},
"arrival": {
"delay": "0",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736230080",
"vehicle": "BE.NMBS.IC1827",
"vehicleinfo": {
"name": "BE.NMBS.IC1827",
"shortname": "IC 1827",
"number": "1827",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1827"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Ostend"
},
"arrived": "0",
"walking": "0",
"departureConnection": "http://irail.be/connections/8892007/20250107/IC1827"
},
"duration": "3720",
"remarks": {
"number": "0",
"remark": []
},
"alerts": {
"number": "0",
"alert": []
}
}
]
} tjorim-pyrail-4c4ba2c/examples/disturbances.json 0000664 0000000 0000000 00000172440 14755342216 0022220 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736291958",
"disturbance": [
{
"id": "0",
"title": "Maastricht (NL): operational reasons",
"description": "The S43 trains Liège-Guillemins / Luik-Guillemins - Maastricht (NL) - Aachen-Hbf (d) only run between Liège-Guillemins / Luik-Guillemins and Maastricht (NL).Between Maastricht (NL) and Aachen-Hbf (d):You can use bus 350.Disruption for an undetermined amount of time.Listen to the announcements, consult the screens in the station or plan your journey through sncb.be, the SNCB app, ns.nl or arriva.nl.",
"type": "disturbance",
"link": "http: //www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=trouble&messageID=91380&channelFilter=rss_line_90,custom1&",
"timestamp": "1736289491",
"richtext": "The S43 trains Liège-Guillemins / Luik-Guillemins - Maastricht (NL) - Aachen-Hbf (d) only run between Liège-Guillemins / Luik-Guillemins and Maastricht (NL).Between Maastricht (NL) and Aachen-Hbf (d):You can use bus 350.Disruption for an undetermined amount of time.Listen to the announcements, consult the screens in the station or plan your journey through sncb.be, the SNCB app, ns.nl or arriva.nl.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=trouble&messageID=91380&channelFilter=rss_line_90,custom1&",
"text": "Read more"
}
]
}
},
{
"id": "1",
"title": "Mouscron / Moeskroen - Lille Flandres (FR)",
"description": "On weekdays from 6 to 17/01 works will take place on the French rail network.An SNCB bus replaces some IC trains Courtrai / Kortrijk - Mouscron / Moeskroen - Lille Flandres (FR) between Mouscron / Moeskroen and Lille Flandres (FR).The travel planner takes these changes into account.Meer info over de NMBS-bussen (FAQ)En savoir plus sur les bus SNCB (FAQ)Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"timestamp": "1736172334",
"richtext": "On weekdays from 6 to 17/01 works will take place on the French rail network.An SNCB bus replaces some IC trains Courtrai / Kortrijk - Mouscron / Moeskroen - Lille Flandres (FR) between Mouscron / Moeskroen and Lille Flandres (FR).The travel planner takes these changes into account.
Meer info over de NMBS-bussen (FAQ)
En savoir plus sur les bus SNCB (FAQ)
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "Meer info over de NMBS-bussen (FAQ)"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1736172333792_FR_2501250_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1736172333804_NL_2501250_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "2",
"title": "Landen - Liège-Guillemins / Luik-Guillemins",
"description": "During the weekend of 11-12/01 and on Saturday 18/01 Infrabel is working on the track.An SNCB bus replaces most trains between Landen and Liège-Guillemins / Luik-Guillemins.The travel planner takes these changes into account.Meer infoPlus d'infos",
"type": "planned",
"link": "https: //www.belgiantrain.be/nl/news/works-leuven-landen-liege",
"timestamp": "1735910597",
"richtext": "During the weekend of 11-12/01 and on Saturday 18/01 Infrabel is working on the track.An SNCB bus replaces most trains between Landen and Liège-Guillemins / Luik-Guillemins.The travel planner takes these changes into account.
Meer info
Plus d\"infos",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-leuven-landen-liege",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-leuven-landen-liege",
"text": "Plus d'infos"
}
]
}
},
{
"id": "3",
"title": "Welkenraedt - Aachen Hbf (DE)",
"description": "On Thursday 9/01 works will take place on the German rail network.Some S41 trains Liège-Saint-Lambert / Luik-Sint-Lambertus - Verviers-Central / Verviers-Centraal - Aachen Hbf (DE) only run between Liège-Saint-Lambert / Luik-Sint-Lambertus and Welkenraedt.The travel planner takes these changes into account.",
"type": "planned",
"link": "http: //www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90799&channelFilter=rss_line_90&",
"timestamp": "1735814004",
"richtext": "On Thursday 9/01 works will take place on the German rail network.Some S41 trains Liège-Saint-Lambert / Luik-Sint-Lambertus - Verviers-Central / Verviers-Centraal - Aachen Hbf (DE) only run between Liège-Saint-Lambert / Luik-Sint-Lambertus and Welkenraedt.The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90799&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "4",
"title": "Brussels - Nivelles / Nijvel",
"description": "During the weekend of 25-26/01 Infrabel is working on the track.An SNCB bus replaces all trains between Brux.-Midi/Brus.-Zuid, Braine-l'Alleud and Nivelles / Nijvel.Due to heavy road traffic, the SNCB bus departure times may differ from the theoretical departure times listed. Please allow for longer travel time.The S19 trains Landen - Brux./Brus.-Luxemb. - Nivelles / Nijvel only run between Louvain / Leuven and Brux./Brus.-Luxemb..You can use some busses of STIB with your train ticket.The departure times of the trains running between Nivelles / Nijvel and Charleroi-Central change.The travel planner takes these changes into account.Meer infoPlus d'infos",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/news/works-bruxelles-nivelles",
"timestamp": "1735037256",
"richtext": "During the weekend of 25-26/01 Infrabel is working on the track.An SNCB bus replaces all trains between Brux.-Midi/Brus.-Zuid, Braine-l\"Alleud and Nivelles / Nijvel.Due to heavy road traffic, the SNCB bus departure times may differ from the theoretical departure times listed. Please allow for longer travel time.The S19 trains Landen - Brux./Brus.-Luxemb. - Nivelles / Nijvel only run between Louvain / Leuven and Brux./Brus.-Luxemb..You can use some busses of STIB with your train ticket.The departure times of the trains running between Nivelles / Nijvel and Charleroi-Central change.The travel planner takes these changes into account.
Meer info
Plus d\"infos",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-bruxelles-nivelles",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-bruxelles-nivelles",
"text": "Plus d'infos"
}
]
}
},
{
"id": "5",
"title": "Blankenberge - Bruges / Brugge",
"description": "During the weekends of 18-19 and 25-26/01 Infrabel is working on the track.An SNCB bus replaces all trains between Blankenberge and Bruges / Brugge.The departure times of some IC trains Blankenberge - Bruges / Brugge - Genk change.The travel planner takes these changes into account.Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https: //www.belgianrail.be/jp/download/brail_him/1735037160508_FR_2501193_S.pdf",
"timestamp": "1735037201",
"richtext": "During the weekends of 18-19 and 25-26/01 Infrabel is working on the track.An SNCB bus replaces all trains between Blankenberge and Bruges / Brugge.The departure times of some IC trains Blankenberge - Bruges / Brugge - Genk change.The travel planner takes these changes into account.
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735037160508_FR_2501193_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "1",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735037160562_NL_2501193_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "6",
"title": "Arlon / Aarlen - Athus",
"description": "On Tuesday 14/01 Infrabel is working on the track.An SNCB bus replaces some trains between Arlon / Aarlen and Athus.The travel planner takes these changes into account.Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735036660510_FR_2501157_S.pdf",
"timestamp": "1735036660",
"richtext": "On Tuesday 14/01 Infrabel is working on the track.An SNCB bus replaces some trains between Arlon / Aarlen and Athus.The travel planner takes these changes into account.
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735036660510_FR_2501157_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "1",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735036660528_NL_2501157_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "7",
"title": "Brussels Airport-Zaventem",
"description": "From 1 to 21/2 Infrabel is working on the track.Fewer trains stop in Brussels Airport-Zaventem. With your train ticket, you can also take bus R26 and 82 of De Lijn between the stations of Zaventem and Brussels Airport-Zaventem. Don\"t forget to also select 'bus' as a mode of transport via 'personalize my journey'. The travel planner takes these changes into account.Plus d\"infos",
"type": "planned",
"link": "https://www.belgiantrain.be/fr/news/works-brussels-airport-zaventem",
"timestamp": "1735032365",
"richtext": "From 1 to 21/2 Infrabel is working on the track.Fewer trains stop in Brussels Airport-Zaventem. With your train ticket, you can also take bus R26 and 82 of De Lijn between the stations of Zaventem and Brussels Airport-Zaventem. Don\"t forget to also select 'bus' as a mode of transport via 'personalize my journey'. The travel planner takes these changes into account.
Plus d\"infos",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/fr/news/works-brussels-airport-zaventem",
"text": "Plus d'infos"
}
]
}
},
{
"id": "8",
"title": "Mons / Bergen - La Louvière-Sud / La Louvière-Zuid - Marchienne-au-Pont",
"description": "On weekdays from 13 to 17/01 Infrabel is working on the track.An SNCB bus replaces some trains between La Louvière-Centre and La Louvière-Sud / La Louvière-Zuid.The route of some IC trains Herstal - Liège-Guillemins / Luik-Guillemins - Mons / Bergen change.The travel planner takes these changes into account.Meer info over de NMBS-bussen (FAQ)En savoir plus sur les bus SNCB (FAQ)Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"timestamp": "1735030191",
"richtext": "On weekdays from 13 to 17/01 Infrabel is working on the track.An SNCB bus replaces some trains between La Louvière-Centre and La Louvière-Sud / La Louvière-Zuid.The route of some IC trains Herstal - Liège-Guillemins / Luik-Guillemins - Mons / Bergen change.The travel planner takes these changes into account.
Meer info over de NMBS-bussen (FAQ)
En savoir plus sur les bus SNCB (FAQ)
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "Meer info over de NMBS-bussen (FAQ)"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735030191232_FR_2501180_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1735030191280_NL_2501180_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "9",
"title": "Aarschot - Louvain / Leuven / Hasselt",
"description": "During the weekends, from 11 to 26/01 Infrabel is working on the track.An SNCB bus replaces most trains between Aarschot and Louvain / Leuven/Hasselt.The route of most IC trains Anvers-Central / Antwerpen-Centraal - Lierre / Lier - Hasselt change.The route and departure times of most L trains Anvers-Central / Antwerpen-Centraal - Lierre / Lier - Louvain / Leuven change.The travel planner takes these changes into account.Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734962134622_FR_2501016_S.pdf",
"timestamp": "1734962135",
"richtext": "During the weekends, from 11 to 26/01 Infrabel is working on the track.An SNCB bus replaces most trains between Aarschot and Louvain / Leuven/Hasselt.The route of most IC trains Anvers-Central / Antwerpen-Centraal - Lierre / Lier - Hasselt change.The route and departure times of most L trains Anvers-Central / Antwerpen-Centraal - Lierre / Lier - Louvain / Leuven change.The travel planner takes these changes into account.
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734962134622_FR_2501016_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "1",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734962134637_NL_2501016_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "10",
"title": "Brussels Airport-Zaventem",
"description": "During the weekends, from 1 to 16/2 Infrabel is working on the track.The IC trains Knokke - Brux.-/ Brus-Centr. - Louvain / Leuven do not stop in Brussels Airport-Zaventem.The departure times of this train change.With your train ticket, you can also take bus R26 and 82 of De Lijn between the stations of Zaventem and Brussels Airport-Zaventem. Don't forget to also select ?bus? as a mode of transport via ?personalize my journey?. The travel planner takes these changes into account.Plus d'infos",
"type": "planned",
"link": "https: //www.belgiantrain.be/fr/news/works-brussels-airport-zaventem",
"timestamp": "1734794255",
"richtext": "During the weekends, from 1 to 16/2 Infrabel is working on the track.The IC trains Knokke - Brux.-/ Brus-Centr. - Louvain / Leuven do not stop in Brussels Airport-Zaventem.The departure times of this train change.With your train ticket, you can also take bus R26 and 82 of De Lijn between the stations of Zaventem and Brussels Airport-Zaventem. Don\"t forget to also select ?bus? as a mode of transport via ?personalize my journey?. The travel planner takes these changes into account.
Plus d\"infos",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/fr/news/works-brussels-airport-zaventem",
"text": "Plus d'infos"
}
]
}
},
{
"id": "11",
"title": "Gouvy - Ettelbruck (LU)",
"description": "During the weekends, from 11-12/01 and 18-19/01 works will take place on the Luxembourg rail network.A CLF bus replaces all trains between Gouvy and Ettelbruck (LU).More info on cfl.lu.Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734688608720_FR_2501230_S.pdf",
"timestamp": "1734688608",
"richtext": "During the weekends, from 11-12/01 and 18-19/01 works will take place on the Luxembourg rail network.A CLF bus replaces all trains between Gouvy and Ettelbruck (LU).More info on cfl.lu.
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734688608720_FR_2501230_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "1",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734688608788_NL_2501230_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "12",
"title": "Bruges / Brugge - Gand-Saint-Pierre / Gent-Sint-Pieters",
"description": "During the weekend of 11-12/01 Infrabel is working on the track.An SNCB bus runs between Bruges / Brugge, Aalter and Gand-Saint-Pierre / Gent-Sint-Pieters.The route and/or departure times of the trains below change: IC Ostende / Oostende - Brux.-/ Brus-Centr. - EupenIC Blankenberge - Brux.-/ Brus-Centr. - GenkIC Ostende / Oostende - Gand-Saint-Pierre / Gent-Sint-Pieters - Anvers-Central / Antwerpen-CentraalIC Knokke - Brux.-/ Brus-Centr. - Louvain / LeuvenL Zeebrugge-Strand - Gand-Saint-Pierre / Gent-Sint-Pieters - Malines / MechelenThe travel planner takes these changes into account.Meer infoPlus d'infosOù prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/news/works-brugge-gent",
"timestamp": "1734686221",
"richtext": "During the weekend of 11-12/01 Infrabel is working on the track.An SNCB bus runs between Bruges / Brugge, Aalter and Gand-Saint-Pierre / Gent-Sint-Pieters.The route and/or departure times of the trains below change: IC Ostende / Oostende - Brux.-/ Brus-Centr. - EupenIC Blankenberge - Brux.-/ Brus-Centr. - GenkIC Ostende / Oostende - Gand-Saint-Pierre / Gent-Sint-Pieters - Anvers-Central / Antwerpen-CentraalIC Knokke - Brux.-/ Brus-Centr. - Louvain / LeuvenL Zeebrugge-Strand - Gand-Saint-Pierre / Gent-Sint-Pieters - Malines / MechelenThe travel planner takes these changes into account.
Meer info
Plus d\"infos
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-brugge-gent",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-brugge-gent",
"text": "Plus d'infos"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734686221568_FR_2501216_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734686221582_NL_2501216_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "13",
"title": "Louvain / Leuven - Liège-Guillemins / Luik-Guillemins",
"description": "On weekdays from 7 to 17/01 Infrabel is working on the track.SNCB buses run on different routes.The route and departure times of some trains running between Louvain / Leuven and Liège-Guillemins / Luik-Guillemins change.The travel planner takes these changes into account.Meer info over de NMBS-bussen (FAQ)En savoir plus sur les bus SNCB (FAQ)Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"timestamp": "1734683220",
"richtext": "On weekdays from 7 to 17/01 Infrabel is working on the track.SNCB buses run on different routes.The route and departure times of some trains running between Louvain / Leuven and Liège-Guillemins / Luik-Guillemins change.The travel planner takes these changes into account.
Meer info over de NMBS-bussen (FAQ)
En savoir plus sur les bus SNCB (FAQ)
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "Meer info over de NMBS-bussen (FAQ)"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734683219854_FR_2501163_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734683219872_NL_2501163_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "14",
"title": "Tamines - Namur / Namen",
"description": "During the weekend of 11-12/01 Infrabel is working on the track.On Sunday 12/01, an SNCB bus replaces some trains between Tamines and Namur / Namen.The route and departure times of some trains IC and S running between Tamines and Namur / Namen change.The travel planner takes these changes into account.Meer info over de NMBS-bussen (FAQ)En savoir plus sur les bus SNCB (FAQ)Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"timestamp": "1734682164",
"richtext": "During the weekend of 11-12/01 Infrabel is working on the track.On Sunday 12/01, an SNCB bus replaces some trains between Tamines and Namur / Namen.The route and departure times of some trains IC and S running between Tamines and Namur / Namen change.The travel planner takes these changes into account.
Meer info over de NMBS-bussen (FAQ)
En savoir plus sur les bus SNCB (FAQ)
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "Meer info over de NMBS-bussen (FAQ)"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734682129569_FR_2501149_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734682129583_NL_2501149_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "15",
"title": "Liège-Guillemins / Luik-Guillemins - Verviers-Central / Verviers-Centraal",
"description": "From 13/01 to 17/01 Infrabel is working on the track.Train traffic is adapted between Liège-Guillemins / Luik-Guillemins and Verviers-Central / Verviers-Centraal.The departure times of some L trains Spa-Géronstère - Verviers-Central / Verviers-Centraal change.The travel planner takes these changes into account.",
"type": "planned",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=91232&channelFilter=rss_line_90&",
"timestamp": "1734611084",
"richtext": "From 13/01 to 17/01 Infrabel is working on the track.Train traffic is adapted between Liège-Guillemins / Luik-Guillemins and Verviers-Central / Verviers-Centraal.The departure times of some L trains Spa-Géronstère - Verviers-Central / Verviers-Centraal change.The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=91232&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "16",
"title": "Brux./Brus.-Luxemb. - Ottignies",
"description": "During the weekend of 11-12 and 25-26/01: Infrabel is working on the track.During the weekend of 11-12/01 Only one S8 train out of two runs between Brux.-Midi/Brus.-Zuid and Ottignies.The departure times of the IC trains Brux.-Midi/Brus.-Zuid - Namur / Namen - Dinant change.The departure times of the IC trains Brux.-Midi/Brus.-Zuid - Namur / Namen - Arlon / Aarlen/Luxembourg (LU) change.During the weekend of 25-26/01: The S8 trains Zottegem - Brux.-Midi/Brus.-Zuid - Ottignies only run between Zottegem and Brux.-Midi/Brus.-Zuid.The route and departure times of the IC trains Brux.-Midi/Brus.-Zuid - Namur / Namen - Dinant change.The travel planner takes these changes into account.",
"type": "planned",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=91194&channelFilter=rss_line_90&",
"timestamp": "1734605999",
"richtext": "During the weekend of 11-12 and 25-26/01: Infrabel is working on the track.During the weekend of 11-12/01 Only one S8 train out of two runs between Brux.-Midi/Brus.-Zuid and Ottignies.The departure times of the IC trains Brux.-Midi/Brus.-Zuid - Namur / Namen - Dinant change.The departure times of the IC trains Brux.-Midi/Brus.-Zuid - Namur / Namen - Arlon / Aarlen/Luxembourg (LU) change.During the weekend of 25-26/01: The S8 trains Zottegem - Brux.-Midi/Brus.-Zuid - Ottignies only run between Zottegem and Brux.-Midi/Brus.-Zuid.The route and departure times of the IC trains Brux.-Midi/Brus.-Zuid - Namur / Namen - Dinant change.The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=91194&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "17",
"title": "Mons / Bergen - Quevy",
"description": "On Thursday 9/01 Infrabel is working on the track.An SNCB bus replaces some L trains Quevy - Mons / Bergen - La Louvière-Sud / La Louvière-Zuid between Quévy and Mons / Bergen.The travel planner takes these changes into account.En savoir plus sur les bus SNCB (FAQ)Meer info over de NMBS-bussen (FAQ)Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"timestamp": "1734601741",
"richtext": "On Thursday 9/01 Infrabel is working on the track.An SNCB bus replaces some L trains Quevy - Mons / Bergen - La Louvière-Sud / La Louvière-Zuid between Quévy and Mons / Bergen.The travel planner takes these changes into account.
En savoir plus sur les bus SNCB (FAQ)
Meer info over de NMBS-bussen (FAQ)
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "Meer info over de NMBS-bussen (FAQ)"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734340270052_FR_2501144_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734340270072_NL_2501144_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "18",
"title": "Brux./Brus.-Luxemb. - Hal / Halle",
"description": "During the weekends of 11-12/01 and 18-19/01 Infrabel is working on the track.The S5 trains Malines / Mechelen - Brux./Brus.-Luxemb. - Hal / Halle only run between Malines / Mechelen and Brux./Brus.-Luxemb..The S19 trains Landen - Brux./Brus.-Luxemb. - Nivelles / Nijvel only run between Landen and Brux./Brus.-Luxemb..You can use some busses and trams of De Lijn and STIB with your train ticket.Meer infoPlus d'infosAlternatives STIB & De LijnAlternatieven van MIVB & De Lijn",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/news/works-bruxelles-halle",
"timestamp": "1734591814",
"richtext": "During the weekends of 11-12/01 and 18-19/01 Infrabel is working on the track.The S5 trains Malines / Mechelen - Brux./Brus.-Luxemb. - Hal / Halle only run between Malines / Mechelen and Brux./Brus.-Luxemb..The S19 trains Landen - Brux./Brus.-Luxemb. - Nivelles / Nijvel only run between Landen and Brux./Brus.-Luxemb..You can use some busses and trams of De Lijn and STIB with your train ticket.
Meer info
Plus d\"infos
Alternatives STIB & De Lijn
Alternatieven van MIVB & De Lijn",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-bruxelles-halle",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-bruxelles-halle",
"text": "Plus d'infos"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734515237933_FR_2501033_S.pdf",
"text": "Alternatives STIB & De Lijn"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734515237991_NL_2501033_S.pdf",
"text": "Alternatieven van MIVB & De Lijn"
}
]
}
},
{
"id": "19",
"title": "Mons / Bergen - Saint-Ghislain",
"description": "On weekdays from 6 to 24/01 Infrabel is working on the track.An SNCB bus replaces the IC train Tongres / Tongeren 20:41 - Brux.-/ Brus-Centr. 22:18 - Saint-Ghislain 23:30 between Mons / Bergen and Saint-Ghislain.The travel planner takes these changes into account.Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734520879429_FR_2501204_aff1_S.pdf",
"timestamp": "1734520879",
"richtext": "On weekdays from 6 to 24/01 Infrabel is working on the track.An SNCB bus replaces the IC train Tongres / Tongeren 20:41 - Brux.-/ Brus-Centr. 22:18 - Saint-Ghislain 23:30 between Mons / Bergen and Saint-Ghislain.The travel planner takes these changes into account.
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734520879429_FR_2501204_aff1_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "1",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734520879446_NL_2501204_aff1_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "20",
"title": "Melsele - Zwijndrecht",
"description": "During the weekends of 4-5 and 11-12/01 Infrabel is working on the track.An SNCB bus replaces all S34 trains Termonde / Dendermonde - Saint-Nicolas / Sint-Niklaas - Anvers-Central / Antwerpen-Centraal between Melsele and Zwijndrecht.These buses also stop at the tram station Zwijndrecht-Dorp, where you can take tram 3 to Antwerpen-Central with your train ticket.The route and departure times of all trains running between Gand-Saint-Pierre / Gent-Sint-Pieters / Saint-Nicolas / Sint-Niklaas and Anvers-Central / Antwerpen-Centraal change.The travel planner takes these changes into account.Plus d'infosMeer infoOù prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/fr/news/works-sint-niklaas-antwerpen",
"timestamp": "1734502904",
"richtext": "During the weekends of 4-5 and 11-12/01 Infrabel is working on the track.An SNCB bus replaces all S34 trains Termonde / Dendermonde - Saint-Nicolas / Sint-Niklaas - Anvers-Central / Antwerpen-Centraal between Melsele and Zwijndrecht.These buses also stop at the tram station Zwijndrecht-Dorp, where you can take tram 3 to Antwerpen-Central with your train ticket.The route and departure times of all trains running between Gand-Saint-Pierre / Gent-Sint-Pieters / Saint-Nicolas / Sint-Niklaas and Anvers-Central / Antwerpen-Centraal change.The travel planner takes these changes into account.
Plus d\"infos
Meer info
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/fr/news/works-sint-niklaas-antwerpen",
"text": "Plus d'infos"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/nl/news/works-sint-niklaas-antwerpen",
"text": "Meer info"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734502903594_FR_2501012_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734502903657_NL_2501012_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "21",
"title": "Courtrai / Kortrijk - Audenarde / Oudenaarde",
"description": "During the weekends of 11-12 and 18-19/01 Infrabel is working on the track.An SNCB bus replaces all trains between Courtrai / Kortrijk and Audenarde / Oudenaarde.The departure times of some IC trains Ostende / Oostende - Courtrai / Kortrijk - Brussels Airport-Zaventem change.The travel planner takes these changes into account.Meer infoPlus d'infosOù prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/news/works-kortrijk-oudenaarde",
"timestamp": "1734440716",
"richtext": "During the weekends of 11-12 and 18-19/01 Infrabel is working on the track.An SNCB bus replaces all trains between Courtrai / Kortrijk and Audenarde / Oudenaarde.The departure times of some IC trains Ostende / Oostende - Courtrai / Kortrijk - Brussels Airport-Zaventem change.The travel planner takes these changes into account.
Meer info
Plus d\"infos
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-kortrijk-oudenaarde",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-kortrijk-oudenaarde",
"text": "Plus d'infos"
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734440715958_FR_2501190_aff_2_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734440716028_NL_2501190_aff_2_S.pdf",
"text": "Waar is mijn bushalte?"
}
]
}
},
{
"id": "22",
"title": "Mons / Bergen - Quévy",
"description": "During the weekend of 11-12/01 Infrabel is working on the track.An SNCB bus replaces all L trains Grammont / Geraardsbergen - Mons / Bergen - Quévy between Mons / Bergen and Quévy.The travel planner takes these changes into account.Où prendre mon bus ?Waar is mijn bushalte?Meer info over de NMBS-bussen (FAQ)En savoir plus sur les bus SNCB (FAQ)",
"type": "planned",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734346039945_FR_2501145_S.pdf",
"timestamp": "1734419212",
"richtext": "During the weekend of 11-12/01 Infrabel is working on the track.An SNCB bus replaces all L trains Grammont / Geraardsbergen - Mons / Bergen - Quévy between Mons / Bergen and Quévy.The travel planner takes these changes into account.
Où prendre mon bus ?
Waar is mijn bushalte?
Meer info over de NMBS-bussen (FAQ)
En savoir plus sur les bus SNCB (FAQ)",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734346039945_FR_2501145_S.pdf",
"text": "Où prendre mon bus ?"
},
{
"id": "1",
"link": "https://www.belgianrail.be/jp/download/brail_him/1734346039964_NL_2501145_S.pdf",
"text": "Waar is mijn bushalte?"
},
{
"id": "2",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes",
"text": "Meer info over de NMBS-bussen (FAQ)"
},
{
"id": "3",
"link": "https://www.belgiantrain.be/fr/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)"
}
]
}
},
{
"id": "23",
"title": "Mons / Bergen - Saint-Ghislain",
"description": "Every day, from 6/01 to 5/02 Infrabel is working on the track.The route and departure times of all trains running between Mons / Bergen and Saint-Ghislain change.Some P trains do not run.On some weekends replaces an SNCB bus all trains between Mons / Bergen and Saint-Ghislain.The travel planner takes these changes into account up until 26.01.25 and will be updated at the latest on 23.12.24.Plan your journey through sncb.be or the SNCB app.Plus d'infosMeer info",
"type": "planned",
"link": "https://www.belgiantrain.be/fr/news/works-stghislain-mons",
"timestamp": "1734337470",
"richtext": "Every day, from 6/01 to 5/02 Infrabel is working on the track.The route and departure times of all trains running between Mons / Bergen and Saint-Ghislain change.Some P trains do not run.On some weekends replaces an SNCB bus all trains between Mons / Bergen and Saint-Ghislain.The travel planner takes these changes into account up until 26.01.25 and will be updated at the latest on 23.12.24.Plan your journey through sncb.be or the SNCB app.
Plus d\"infos
Meer info",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/fr/news/works-stghislain-mons",
"text": "Plus d'infos"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/nl/news/works-stghislain-mons",
"text": "Meer info"
}
]
}
},
{
"id": "24",
"title": "Namur / Namen - Gendron-Celles",
"description": "On 13-14/01 Infrabel is working on the track.The departure times of most L trains Namur / Namen - Dinant - Libramont change.The travel planner takes these changes into account.",
"type": "planned",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=91047&channelFilter=rss_line_90&",
"timestamp": "1734101841",
"richtext": "On 13-14/01 Infrabel is working on the track.The departure times of most L trains Namur / Namen - Dinant - Libramont change.The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=91047&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "25",
"title": "Anvers-Central / Antwerpen-Centraal - Anvers-Berchem / Antwerpen-Berchem",
"description": "During the weekends, from 4 to 19/01 Infrabel is working on the track.The route and departure times of most trains running between Anvers-Central / Antwerpen-Centraal and Anvers-Berchem / Antwerpen-Berchem change.The travel planner takes these changes into account.Meer infoPlus d'infos",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/news/works-antwerpen-centraal-antwerpen-berchem2",
"timestamp": "1733903961",
"richtext": "During the weekends, from 4 to 19/01 Infrabel is working on the track.The route and departure times of most trains running between Anvers-Central / Antwerpen-Centraal and Anvers-Berchem / Antwerpen-Berchem change.The travel planner takes these changes into account.
Meer info
Plus d\"infos",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-antwerpen-centraal-antwerpen-berchem2",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-antwerpen-centraal-antwerpen-berchem2",
"text": "Plus d'infos"
}
]
}
},
{
"id": "26",
"title": "Arlon / Aarlen - Libramont",
"description": "During the weekend of 11-12/01 Infrabel is working on the track.The departure times of some L trains Libramont - Bertrix - Arlon / Aarlen change.The travel planner takes these changes into account.",
"type": "planned",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90810&channelFilter=rss_line_90&",
"timestamp": "1733481219",
"richtext": "During the weekend of 11-12/01 Infrabel is working on the track.The departure times of some L trains Libramont - Bertrix - Arlon / Aarlen change.The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90810&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "27",
"title": "Anvers-Berchem / Antwerpen-Berchem - Hoboken-Polder",
"description": "During the weekends of 4-5 and 11-12/01 Infrabel is working on the track.An SNCB bus replaces all S32 trains Puurs - Anvers-Central / Antwerpen-Centraal - Roosendaal (NL) between Hoboken-Polder and Anvers-Berchem / Antwerpen-Berchem.The departure times of all S32 trains change.The travel planner takes these changes into account.Plus d'infosMeer info",
"type": "planned",
"link": "https://www.belgiantrain.be/fr/news/works-antwerpen-hoboken-polder",
"timestamp": "1733404142",
"richtext": "During the weekends of 4-5 and 11-12/01 Infrabel is working on the track.An SNCB bus replaces all S32 trains Puurs - Anvers-Central / Antwerpen-Centraal - Roosendaal (NL) between Hoboken-Polder and Anvers-Berchem / Antwerpen-Berchem.The departure times of all S32 trains change.The travel planner takes these changes into account.
Plus d\"infos
Meer info",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/fr/news/works-antwerpen-hoboken-polder",
"text": "Plus d'infos"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/nl/news/works-antwerpen-hoboken-polder",
"text": "Meer info"
}
]
}
},
{
"id": "28",
"title": "Arlon / Aarlen - Libramont",
"description": "On 7 and 8/01 Infrabel is working on the track.The departure times of some trains running between Arlon / Aarlen and Libramont change.The travel planner takes these changes into account.",
"type": "planned",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90776&channelFilter=rss_line_90&",
"timestamp": "1733318792",
"richtext": "On 7 and 8/01 Infrabel is working on the track.The departure times of some trains running between Arlon / Aarlen and Libramont change.The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90776&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "29",
"title": "Namur / Namen - Dinant",
"description": "From 7 to 10/01 Infrabel is working on the track.The departure times of the trains below change: IC Brussels Airport-Zaventem - Namur - Dinant L Namur - Dinant - Libramont S61 Charleroi-Central - Tamines - Jambes The travel planner takes these changes into account.",
"type": "planned",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90702&channelFilter=rss_line_90&",
"timestamp": "1733130884",
"richtext": "From 7 to 10/01 Infrabel is working on the track.The departure times of the trains below change: IC Brussels Airport-Zaventem - Namur - Dinant L Namur - Dinant - Libramont S61 Charleroi-Central - Tamines - Jambes The travel planner takes these changes into account.",
"descriptionLinks": {
"number": "1",
"descriptionLink": [
{
"id": "0",
"link": "http://www.belgianrail.be/jp/nmbs-realtime/help.exe/en?tpl=showmap_external&tplParamHimMsgInfoGroup=works&messageID=90702&channelFilter=rss_line_90&",
"text": "Read more"
}
]
}
},
{
"id": "30",
"title": "Brux./Brus.-Luxemb. - Saint-Job / Sint-Job",
"description": "Every day, from 14/10 to 15/06 Infrabel is working on the track.The route and departure times of the trains below change: S5 Malines / Mechelen - Brux./Brus.-Luxemb. - Hal / Halle, Enghien / EdingenS7 Vilvorde / Vilvoorde - Mérode/Merode - Hal / HalleS9 Nivelles / Nijvel - Brux./Brus.-Luxemb. - LandenS19 Brussels Airport-Zaventem - Brux./Brus.-Luxemb. - Charleroi-CentralThe travel planner takes these changes into account.Meer infoPlus d'infos",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/news/works-brussels-lux-saint-job",
"timestamp": "1732104381",
"richtext": "Every day, from 14/10 to 15/06 Infrabel is working on the track.The route and departure times of the trains below change: S5 Malines / Mechelen - Brux./Brus.-Luxemb. - Hal / Halle, Enghien / EdingenS7 Vilvorde / Vilvoorde - Mérode/Merode - Hal / HalleS9 Nivelles / Nijvel - Brux./Brus.-Luxemb. - LandenS19 Brussels Airport-Zaventem - Brux./Brus.-Luxemb. - Charleroi-CentralThe travel planner takes these changes into account.
Meer info
Plus d\"infos",
"descriptionLinks": {
"number": "2",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/news/works-brussels-lux-saint-job",
"text": "Meer info"
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/news/works-brussels-lux-saint-job",
"text": "Plus d'infos"
}
]
}
}
]
} tjorim-pyrail-4c4ba2c/examples/liveboard.json 0000664 0000000 0000000 00000021423 14755342216 0021473 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736201508",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http: //irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"departures": {
"number": "6",
"departure": [
{
"id": "0",
"station": "Brussels-South/Brussels-Midi",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814001",
"id": "BE.NMBS.008814001",
"name": "Brussels-South/Brussels-Midi",
"locationX": "4.336531",
"locationY": "50.835707",
"standardname": "Brussel-Zuid/Bruxelles-Midi"
},
"time": "1736201940",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EC9272",
"vehicleinfo": {
"name": "BE.NMBS.EC9272",
"shortname": "EC 9272",
"number": "9272",
"type": "EC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EC9272"
},
"platform": "23",
"platforminfo": {
"name": "23",
"normal": "1"
},
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8821006/20250106/EC9272"
},
{
"id": "1",
"station": "Mol",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008832409",
"id": "BE.NMBS.008832409",
"name": "Mol",
"locationX": "5.116336",
"locationY": "51.19105",
"standardname": "Mol"
},
"time": "1736202240",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC4323",
"vehicleinfo": {
"name": "BE.NMBS.IC4323",
"shortname": "IC 4323",
"number": "4323",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC4323"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "1"
},
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8821006/20250106/IC4323"
},
{
"id": "2",
"station": "Brussels-South/Brussels-Midi",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814001",
"id": "BE.NMBS.008814001",
"name": "Brussels-South/Brussels-Midi",
"locationX": "4.336531",
"locationY": "50.835707",
"standardname": "Brussel-Zuid/Bruxelles-Midi"
},
"time": "1736202300",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2045",
"vehicleinfo": {
"name": "BE.NMBS.IC2045",
"shortname": "IC 2045",
"number": "2045",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2045"
},
"platform": "23",
"platforminfo": {
"name": "23",
"normal": "1"
},
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8821006/20250106/IC2045"
},
{
"id": "3",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736202960",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC723",
"vehicleinfo": {
"name": "BE.NMBS.IC723",
"shortname": "IC 723",
"number": "723",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC723"
},
"platform": "11",
"platforminfo": {
"name": "11",
"normal": "1"
},
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8821006/20250106/IC723"
},
{
"id": "4",
"station": "Brussels-South/Brussels-Midi",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814001",
"id": "BE.NMBS.008814001",
"name": "Brussels-South/Brussels-Midi",
"locationX": "4.336531",
"locationY": "50.835707",
"standardname": "Brussel-Zuid/Bruxelles-Midi"
},
"time": "1736204700",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S11996",
"vehicleinfo": {
"name": "BE.NMBS.S11996",
"shortname": "S1 1996",
"number": "1996",
"type": "S1",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S11996"
},
"platform": "14",
"platforminfo": {
"name": "14",
"normal": "1"
},
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
},
"departureConnection": "http://irail.be/connections/8821006/20250107/S11996"
},
{
"id": "5",
"station": "Essen",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821402",
"id": "BE.NMBS.008821402",
"name": "Essen",
"locationX": "4.451314",
"locationY": "51.462767",
"standardname": "Essen"
},
"time": "1736205000",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S322573",
"vehicleinfo": {
"name": "BE.NMBS.S322573",
"shortname": "S32 2573",
"number": "2573",
"type": "S32",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S322573"
},
"platform": "21",
"platforminfo": {
"name": "21",
"normal": "1"
},
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
},
"departureConnection": "http://irail.be/connections/8821006/20250107/S322573"
}
]
}
} tjorim-pyrail-4c4ba2c/examples/liveboard_arrivals.json 0000664 0000000 0000000 00000213064 14755342216 0023402 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736358159",
"station": "Brussels-South/Brussels-Midi",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814001",
"id": "BE.NMBS.008814001",
"name": "Brussels-South/Brussels-Midi",
"locationX": "4.336531",
"locationY": "50.835707",
"standardname": "Brussel-Zuid/Bruxelles-Midi"
},
"arrivals": {
"number": "56",
"arrival": [
{
"id": "0",
"station": "Köln Hbf",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008015458",
"id": "BE.NMBS.008015458",
"name": "Köln Hbf",
"locationX": "6.958823",
"locationY": "50.942721",
"standardname": "Köln Hbf"
},
"time": "1736357700",
"delay": "900",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EUR9474",
"vehicleinfo": {
"name": "BE.NMBS.EUR9474",
"shortname": "EUR 9474",
"number": "9474",
"type": "EUR",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EUR9474"
},
"platform": "4",
"platforminfo": {
"name": "4",
"normal": "0"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/EUR9474"
},
{
"id": "1",
"station": "Quievrain",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008884335",
"id": "BE.NMBS.008884335",
"name": "Quievrain",
"locationX": "3.68608",
"locationY": "50.410103",
"standardname": "Quievrain"
},
"time": "1736357760",
"delay": "420",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1717",
"vehicleinfo": {
"name": "BE.NMBS.IC1717",
"shortname": "IC 1717",
"number": "1717",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1717"
},
"platform": "13",
"platforminfo": {
"name": "13",
"normal": "0"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1717"
},
{
"id": "2",
"station": "Dendermonde",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893401",
"id": "BE.NMBS.008893401",
"name": "Dendermonde",
"locationX": "4.101427",
"locationY": "51.022781",
"standardname": "Dendermonde"
},
"time": "1736358180",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3240",
"vehicleinfo": {
"name": "BE.NMBS.IC3240",
"shortname": "IC 3240",
"number": "3240",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3240"
},
"platform": "9",
"platforminfo": {
"name": "9",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3240"
},
{
"id": "3",
"station": "Zottegem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008895208",
"id": "BE.NMBS.008895208",
"name": "Zottegem",
"locationX": "3.81441",
"locationY": "50.869102",
"standardname": "Zottegem"
},
"time": "1736358300",
"delay": "60",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S86567",
"vehicleinfo": {
"name": "BE.NMBS.S86567",
"shortname": "S8 6567",
"number": "6567",
"type": "S8",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S86567"
},
"platform": "14",
"platforminfo": {
"name": "14",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S86567"
},
{
"id": "4",
"station": "Charleroi-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008872009",
"id": "BE.NMBS.008872009",
"name": "Charleroi-Central",
"locationX": "4.438567",
"locationY": "50.40471",
"standardname": "Charleroi-Central"
},
"time": "1736358300",
"delay": "240",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2017",
"vehicleinfo": {
"name": "BE.NMBS.IC2017",
"shortname": "IC 2017",
"number": "2017",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2017"
},
"platform": "20",
"platforminfo": {
"name": "20",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2017"
},
{
"id": "5",
"station": "Paris Nord",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008727100",
"id": "BE.NMBS.008727100",
"name": "Paris Nord",
"locationX": "2.354577",
"locationY": "48.88011",
"standardname": "Paris Nord"
},
"time": "1736358420",
"delay": "960",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EUR9369",
"vehicleinfo": {
"name": "BE.NMBS.EUR9369",
"shortname": "EUR 9369",
"number": "9369",
"type": "EUR",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EUR9369"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "0"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/EUR9369"
},
{
"id": "6",
"station": "Liège-Guillemins",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008841004",
"id": "BE.NMBS.008841004",
"name": "Liège-Guillemins",
"locationX": "5.566695",
"locationY": "50.62455",
"standardname": "Liège-Guillemins"
},
"time": "1736358420",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2840",
"vehicleinfo": {
"name": "BE.NMBS.IC2840",
"shortname": "IC 2840",
"number": "2840",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2840"
},
"platform": "12",
"platforminfo": {
"name": "12",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2840"
},
{
"id": "7",
"station": "Tournai",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008885001",
"id": "BE.NMBS.008885001",
"name": "Tournai",
"locationX": "3.396942",
"locationY": "50.613134",
"standardname": "Tournai"
},
"time": "1736358480",
"delay": "120",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1917",
"vehicleinfo": {
"name": "BE.NMBS.IC1917",
"shortname": "IC 1917",
"number": "1917",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1917"
},
"platform": "16",
"platforminfo": {
"name": "16",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1917"
},
{
"id": "8",
"station": "Genk",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008831765",
"id": "BE.NMBS.008831765",
"name": "Genk",
"locationX": "5.497685",
"locationY": "50.967057",
"standardname": "Genk"
},
"time": "1736358540",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3639",
"vehicleinfo": {
"name": "BE.NMBS.IC3639",
"shortname": "IC 3639",
"number": "3639",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3639"
},
"platform": "17",
"platforminfo": {
"name": "17",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3639"
},
{
"id": "9",
"station": "Brussels Airport - Zaventem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008819406",
"id": "BE.NMBS.008819406",
"name": "Brussels Airport - Zaventem",
"locationX": "4.482076",
"locationY": "50.896456",
"standardname": "Brussels Airport - Zaventem"
},
"time": "1736358720",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3739",
"vehicleinfo": {
"name": "BE.NMBS.IC3739",
"shortname": "IC 3739",
"number": "3739",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3739"
},
"platform": "8",
"platforminfo": {
"name": "8",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3739"
},
{
"id": "10",
"station": "Ostend",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008891702",
"id": "BE.NMBS.008891702",
"name": "Ostend",
"locationX": "2.925809",
"locationY": "51.228212",
"standardname": "Oostende"
},
"time": "1736358720",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC517",
"vehicleinfo": {
"name": "BE.NMBS.IC517",
"shortname": "IC 517",
"number": "517",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC517"
},
"platform": "6",
"platforminfo": {
"name": "6",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC517"
},
{
"id": "11",
"station": "Kortrijk",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008896008",
"id": "BE.NMBS.008896008",
"name": "Kortrijk",
"locationX": "3.264549",
"locationY": "50.824506",
"standardname": "Kortrijk"
},
"time": "1736358960",
"delay": "0",
"canceled": "1",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC5117",
"vehicleinfo": {
"name": "BE.NMBS.IC5117",
"shortname": "IC 5117",
"number": "5117",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC5117"
},
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC5117"
},
{
"id": "12",
"station": "Braine-le-Comte",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008883006",
"id": "BE.NMBS.008883006",
"name": "Braine-le-Comte",
"locationX": "4.137662",
"locationY": "50.605079",
"standardname": "Braine-le-Comte"
},
"time": "1736359020",
"delay": "180",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S23768",
"vehicleinfo": {
"name": "BE.NMBS.S23768",
"shortname": "S2 3768",
"number": "3768",
"type": "S2",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S23768"
},
"platform": "18",
"platforminfo": {
"name": "18",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S23768"
},
{
"id": "13",
"station": "Liège-Saint-Lambert",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008841525",
"id": "BE.NMBS.008841525",
"name": "Liège-Saint-Lambert",
"locationX": "5.570453",
"locationY": "50.646349",
"standardname": "Liège-Saint-Lambert"
},
"time": "1736359020",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2438",
"vehicleinfo": {
"name": "BE.NMBS.IC2438",
"shortname": "IC 2438",
"number": "2438",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2438"
},
"platform": "16",
"platforminfo": {
"name": "16",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2438"
},
{
"id": "14",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736359020",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S11789",
"vehicleinfo": {
"name": "BE.NMBS.S11789",
"shortname": "S1 1789",
"number": "1789",
"type": "S1",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S11789"
},
"platform": "21",
"platforminfo": {
"name": "21",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S11789"
},
{
"id": "15",
"station": "Aalst",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008895000",
"id": "BE.NMBS.008895000",
"name": "Aalst",
"locationX": "4.039653",
"locationY": "50.942813",
"standardname": "Aalst"
},
"time": "1736359080",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S102088",
"vehicleinfo": {
"name": "BE.NMBS.S102088",
"shortname": "S10 2088",
"number": "2088",
"type": "S10",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S102088"
},
"platform": "7",
"platforminfo": {
"name": "7",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S102088"
},
{
"id": "16",
"station": "Dendermonde",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893401",
"id": "BE.NMBS.008893401",
"name": "Dendermonde",
"locationX": "4.101427",
"locationY": "51.022781",
"standardname": "Dendermonde"
},
"time": "1736359080",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S103868",
"vehicleinfo": {
"name": "BE.NMBS.S103868",
"shortname": "S10 3868",
"number": "3868",
"type": "S10",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S103868"
},
"platform": "10",
"platforminfo": {
"name": "10",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S103868"
},
{
"id": "17",
"station": "Leuven",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008833001",
"id": "BE.NMBS.008833001",
"name": "Leuven",
"locationX": "4.715866",
"locationY": "50.88228",
"standardname": "Leuven"
},
"time": "1736359200",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S23789",
"vehicleinfo": {
"name": "BE.NMBS.S23789",
"shortname": "S2 3789",
"number": "3789",
"type": "S2",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S23789"
},
"platform": "17",
"platforminfo": {
"name": "17",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S23789"
},
{
"id": "18",
"station": "Nivelles",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814209",
"id": "BE.NMBS.008814209",
"name": "Nivelles",
"locationX": "4.335065",
"locationY": "50.599641",
"standardname": "Nivelles"
},
"time": "1736359260",
"delay": "120",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S11768",
"vehicleinfo": {
"name": "BE.NMBS.S11768",
"shortname": "S1 1768",
"number": "1768",
"type": "S1",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S11768"
},
"platform": "19",
"platforminfo": {
"name": "19",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S11768"
},
{
"id": "19",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736359380",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3139",
"vehicleinfo": {
"name": "BE.NMBS.IC3139",
"shortname": "IC 3139",
"number": "3139",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3139"
},
"platform": "20",
"platforminfo": {
"name": "20",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3139"
},
{
"id": "20",
"station": "Eupen",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008844628",
"id": "BE.NMBS.008844628",
"name": "Eupen",
"locationX": "6.03711",
"locationY": "50.635157",
"standardname": "Eupen"
},
"time": "1736359380",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC540",
"vehicleinfo": {
"name": "BE.NMBS.IC540",
"shortname": "IC 540",
"number": "540",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC540"
},
"platform": "12",
"platforminfo": {
"name": "12",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC540"
},
{
"id": "21",
"station": "Schaarbeek/Schaerbeek",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008811007",
"id": "BE.NMBS.008811007",
"name": "Schaarbeek/Schaerbeek",
"locationX": "4.378636",
"locationY": "50.878513",
"standardname": "Schaarbeek/Schaerbeek"
},
"time": "1736359440",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC5140",
"vehicleinfo": {
"name": "BE.NMBS.IC5140",
"shortname": "IC 5140",
"number": "5140",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC5140"
},
"platform": "15",
"platforminfo": {
"name": "15",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC5140"
},
{
"id": "22",
"station": "Mons",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008881000",
"id": "BE.NMBS.008881000",
"name": "Mons",
"locationX": "3.942542",
"locationY": "50.453854",
"standardname": "Mons"
},
"time": "1736359560",
"delay": "60",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3718",
"vehicleinfo": {
"name": "BE.NMBS.IC3718",
"shortname": "IC 3718",
"number": "3718",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3718"
},
"platform": "9",
"platforminfo": {
"name": "9",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3718"
},
{
"id": "23",
"station": "Amsterdam CS",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008400058",
"id": "BE.NMBS.008400058",
"name": "Amsterdam CS",
"locationX": "4.900632",
"locationY": "52.37908",
"standardname": "Amsterdam CS"
},
"time": "1736359560",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EUR9376",
"vehicleinfo": {
"name": "BE.NMBS.EUR9376",
"shortname": "EUR 9376",
"number": "9376",
"type": "EUR",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EUR9376"
},
"platform": "6",
"platforminfo": {
"name": "6",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/EUR9376"
},
{
"id": "24",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736359620",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3618",
"vehicleinfo": {
"name": "BE.NMBS.IC3618",
"shortname": "IC 3618",
"number": "3618",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3618"
},
"platform": "14",
"platforminfo": {
"name": "14",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3618"
},
{
"id": "25",
"station": "Knokke",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008891660",
"id": "BE.NMBS.008891660",
"name": "Knokke",
"locationX": "3.285188",
"locationY": "51.339894",
"standardname": "Knokke"
},
"time": "1736359740",
"delay": "60",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2817",
"vehicleinfo": {
"name": "BE.NMBS.IC2817",
"shortname": "IC 2817",
"number": "2817",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2817"
},
"platform": "8",
"platforminfo": {
"name": "8",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2817"
},
{
"id": "26",
"station": "Brussels Airport - Zaventem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008819406",
"id": "BE.NMBS.008819406",
"name": "Brussels Airport - Zaventem",
"locationX": "4.482076",
"locationY": "50.896456",
"standardname": "Brussels Airport - Zaventem"
},
"time": "1736359800",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1940",
"vehicleinfo": {
"name": "BE.NMBS.IC1940",
"shortname": "IC 1940",
"number": "1940",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1940"
},
"platform": "19",
"platforminfo": {
"name": "19",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1940"
},
{
"id": "27",
"station": "Essen",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821402",
"id": "BE.NMBS.008821402",
"name": "Essen",
"locationX": "4.451314",
"locationY": "51.462767",
"standardname": "Essen"
},
"time": "1736359860",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2040",
"vehicleinfo": {
"name": "BE.NMBS.IC2040",
"shortname": "IC 2040",
"number": "2040",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2040"
},
"platform": "21",
"platforminfo": {
"name": "21",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2040"
},
{
"id": "28",
"station": "Lelystad Centrum",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008400394",
"id": "BE.NMBS.008400394",
"name": "Lelystad Centrum",
"locationX": "5.470484",
"locationY": "52.511736",
"standardname": "Lelystad Centrum"
},
"time": "1736359860",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.ECD9556",
"vehicleinfo": {
"name": "BE.NMBS.ECD9556",
"shortname": "ECD 9556",
"number": "9556",
"type": "ECD",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/ECD9556"
},
"platform": "12",
"platforminfo": {
"name": "12",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/ECD9556"
},
{
"id": "29",
"station": "Louvain-la-Neuve",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008811676",
"id": "BE.NMBS.008811676",
"name": "Louvain-la-Neuve",
"locationX": "4.615745",
"locationY": "50.669793",
"standardname": "Louvain-la-Neuve"
},
"time": "1736359980",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S86590",
"vehicleinfo": {
"name": "BE.NMBS.S86590",
"shortname": "S8 6590",
"number": "6590",
"type": "S8",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S86590"
},
"platform": "17",
"platforminfo": {
"name": "17",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S86590"
},
{
"id": "30",
"station": "Kortrijk",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008896008",
"id": "BE.NMBS.008896008",
"name": "Kortrijk",
"locationX": "3.264549",
"locationY": "50.824506",
"standardname": "Kortrijk"
},
"time": "1736360040",
"delay": "60",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3217",
"vehicleinfo": {
"name": "BE.NMBS.IC3217",
"shortname": "IC 3217",
"number": "3217",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3217"
},
"platform": "7",
"platforminfo": {
"name": "7",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3217"
},
{
"id": "31",
"station": "Charleroi-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008872009",
"id": "BE.NMBS.008872009",
"name": "Charleroi-Central",
"locationX": "4.438567",
"locationY": "50.40471",
"standardname": "Charleroi-Central"
},
"time": "1736360160",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC4518",
"vehicleinfo": {
"name": "BE.NMBS.IC4518",
"shortname": "IC 4518",
"number": "4518",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC4518"
},
"platform": "20",
"platforminfo": {
"name": "20",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC4518"
},
{
"id": "32",
"station": "Dendermonde",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893401",
"id": "BE.NMBS.008893401",
"name": "Dendermonde",
"locationX": "4.101427",
"locationY": "51.022781",
"standardname": "Dendermonde"
},
"time": "1736360160",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S32290",
"vehicleinfo": {
"name": "BE.NMBS.S32290",
"shortname": "S3 2290",
"number": "2290",
"type": "S3",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S32290"
},
"platform": "9",
"platforminfo": {
"name": "9",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S32290"
},
{
"id": "33",
"station": "Rotterdam CS",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008400530",
"id": "BE.NMBS.008400530",
"name": "Rotterdam CS",
"locationX": "4.469313",
"locationY": "51.92485",
"standardname": "Rotterdam CS"
},
"time": "1736360220",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EC9252",
"vehicleinfo": {
"name": "BE.NMBS.EC9252",
"shortname": "EC 9252",
"number": "9252",
"type": "EC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EC9252"
},
"platform": "15",
"platforminfo": {
"name": "15",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/EC9252"
},
{
"id": "34",
"station": "Paris Nord",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008727100",
"id": "BE.NMBS.008727100",
"name": "Paris Nord",
"locationX": "2.354577",
"locationY": "48.88011",
"standardname": "Paris Nord"
},
"time": "1736360220",
"delay": "120",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EUR9471",
"vehicleinfo": {
"name": "BE.NMBS.EUR9471",
"shortname": "EUR 9471",
"number": "9471",
"type": "EUR",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EUR9471"
},
"platform": "4",
"platforminfo": {
"name": "4",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/EUR9471"
},
{
"id": "35",
"station": "Ostend",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008891702",
"id": "BE.NMBS.008891702",
"name": "Ostend",
"locationX": "2.925809",
"locationY": "51.228212",
"standardname": "Oostende"
},
"time": "1736360400",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2316",
"vehicleinfo": {
"name": "BE.NMBS.IC2316",
"shortname": "IC 2316",
"number": "2316",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2316"
},
"platform": "14",
"platforminfo": {
"name": "14",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2316"
},
{
"id": "36",
"station": "Brussels Airport - Zaventem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008819406",
"id": "BE.NMBS.008819406",
"name": "Brussels Airport - Zaventem",
"locationX": "4.482076",
"locationY": "50.896456",
"standardname": "Brussels Airport - Zaventem"
},
"time": "1736360400",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2240",
"vehicleinfo": {
"name": "BE.NMBS.IC2240",
"shortname": "IC 2240",
"number": "2240",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2240"
},
"platform": "13",
"platforminfo": {
"name": "13",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2240"
},
{
"id": "37",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736360520",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S11990",
"vehicleinfo": {
"name": "BE.NMBS.S11990",
"shortname": "S1 1990",
"number": "1990",
"type": "S1",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S11990"
},
"platform": "21",
"platforminfo": {
"name": "21",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S11990"
},
{
"id": "38",
"station": "Tongeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008831310",
"id": "BE.NMBS.008831310",
"name": "Tongeren",
"locationX": "5.47328",
"locationY": "50.784405",
"standardname": "Tongeren"
},
"time": "1736360520",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1740",
"vehicleinfo": {
"name": "BE.NMBS.IC1740",
"shortname": "IC 1740",
"number": "1740",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1740"
},
"platform": "19",
"platforminfo": {
"name": "19",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1740"
},
{
"id": "39",
"station": "Kortrijk",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008896008",
"id": "BE.NMBS.008896008",
"name": "Kortrijk",
"locationX": "3.264549",
"locationY": "50.824506",
"standardname": "Kortrijk"
},
"time": "1736360640",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC418",
"vehicleinfo": {
"name": "BE.NMBS.IC418",
"shortname": "IC 418",
"number": "418",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC418"
},
"platform": "5",
"platforminfo": {
"name": "5",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC418"
},
{
"id": "40",
"station": "Hasselt",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008831005",
"id": "BE.NMBS.008831005",
"name": "Hasselt",
"locationX": "5.327627",
"locationY": "50.930822",
"standardname": "Hasselt"
},
"time": "1736360700",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1540",
"vehicleinfo": {
"name": "BE.NMBS.IC1540",
"shortname": "IC 1540",
"number": "1540",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1540"
},
"platform": "11",
"platforminfo": {
"name": "11",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1540"
},
{
"id": "41",
"station": "Braine-le-Comte",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008883006",
"id": "BE.NMBS.008883006",
"name": "Braine-le-Comte",
"locationX": "4.137662",
"locationY": "50.605079",
"standardname": "Braine-le-Comte"
},
"time": "1736360760",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S23668",
"vehicleinfo": {
"name": "BE.NMBS.S23668",
"shortname": "S2 3668",
"number": "3668",
"type": "S2",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S23668"
},
"platform": "17",
"platforminfo": {
"name": "17",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S23668"
},
{
"id": "42",
"station": "Turnhout",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821907",
"id": "BE.NMBS.008821907",
"name": "Turnhout",
"locationX": "4.937415",
"locationY": "51.322032",
"standardname": "Turnhout"
},
"time": "1736360820",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3440",
"vehicleinfo": {
"name": "BE.NMBS.IC3440",
"shortname": "IC 3440",
"number": "3440",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3440"
},
"platform": "20",
"platforminfo": {
"name": "20",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3440"
},
{
"id": "43",
"station": "Blankenberge",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008891405",
"id": "BE.NMBS.008891405",
"name": "Blankenberge",
"locationX": "3.133864",
"locationY": "51.312432",
"standardname": "Blankenberge"
},
"time": "1736360880",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1518",
"vehicleinfo": {
"name": "BE.NMBS.IC1518",
"shortname": "IC 1518",
"number": "1518",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1518"
},
"platform": "3",
"platforminfo": {
"name": "3",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1518"
},
{
"id": "44",
"station": "Lëtzebuerg",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008200100",
"id": "BE.NMBS.008200100",
"name": "Lëtzebuerg",
"locationX": "6.133331",
"locationY": "49.599996",
"standardname": "Lëtzebuerg"
},
"time": "1736360880",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2139",
"vehicleinfo": {
"name": "BE.NMBS.IC2139",
"shortname": "IC 2139",
"number": "2139",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2139"
},
"platform": "14",
"platforminfo": {
"name": "14",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2139"
},
{
"id": "45",
"station": "Binche",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008882362",
"id": "BE.NMBS.008882362",
"name": "Binche",
"locationX": "4.172451",
"locationY": "50.408764",
"standardname": "Binche"
},
"time": "1736361000",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC3418",
"vehicleinfo": {
"name": "BE.NMBS.IC3418",
"shortname": "IC 3418",
"number": "3418",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3418"
},
"platform": "18",
"platforminfo": {
"name": "18",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC3418"
},
{
"id": "46",
"station": "Leuven",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008833001",
"id": "BE.NMBS.008833001",
"name": "Leuven",
"locationX": "4.715866",
"locationY": "50.88228",
"standardname": "Leuven"
},
"time": "1736361060",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S23690",
"vehicleinfo": {
"name": "BE.NMBS.S23690",
"shortname": "S2 3690",
"number": "3690",
"type": "S2",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S23690"
},
"platform": "16",
"platforminfo": {
"name": "16",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S23690"
},
{
"id": "47",
"station": "Welkenraedt",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008844503",
"id": "BE.NMBS.008844503",
"name": "Welkenraedt",
"locationX": "5.975381",
"locationY": "50.659707",
"standardname": "Welkenraedt"
},
"time": "1736361120",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC440",
"vehicleinfo": {
"name": "BE.NMBS.IC440",
"shortname": "IC 440",
"number": "440",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC440"
},
"platform": "8",
"platforminfo": {
"name": "8",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC440"
},
{
"id": "48",
"station": "Frankfurt am Main Hbf",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008011068",
"id": "BE.NMBS.008011068",
"name": "Frankfurt am Main Hbf",
"locationX": "8.6653708",
"locationY": "50.1071318",
"standardname": "Frankfurt am Main Hbf"
},
"time": "1736361300",
"delay": "780",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.ICE12",
"vehicleinfo": {
"name": "BE.NMBS.ICE12",
"shortname": "ICE 12",
"number": "12",
"type": "ICE",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/ICE12"
},
"platform": "11",
"platforminfo": {
"name": "11",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/ICE12"
},
{
"id": "49",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736361300",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2218",
"vehicleinfo": {
"name": "BE.NMBS.IC2218",
"shortname": "IC 2218",
"number": "2218",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2218"
},
"platform": "7",
"platforminfo": {
"name": "7",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2218"
},
{
"id": "50",
"station": "Nivelles",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814209",
"id": "BE.NMBS.008814209",
"name": "Nivelles",
"locationX": "4.335065",
"locationY": "50.599641",
"standardname": "Nivelles"
},
"time": "1736361300",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S11968",
"vehicleinfo": {
"name": "BE.NMBS.S11968",
"shortname": "S1 1968",
"number": "1968",
"type": "S1",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S11968"
},
"platform": "20",
"platforminfo": {
"name": "20",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S11968"
},
{
"id": "51",
"station": "Quievrain",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008884335",
"id": "BE.NMBS.008884335",
"name": "Quievrain",
"locationX": "3.68608",
"locationY": "50.410103",
"standardname": "Quievrain"
},
"time": "1736361360",
"delay": "60",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC1718",
"vehicleinfo": {
"name": "BE.NMBS.IC1718",
"shortname": "IC 1718",
"number": "1718",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC1718"
},
"platform": "13",
"platforminfo": {
"name": "13",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC1718"
},
{
"id": "52",
"station": "Brussels Airport - Zaventem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008819406",
"id": "BE.NMBS.008819406",
"name": "Brussels Airport - Zaventem",
"locationX": "4.482076",
"locationY": "50.896456",
"standardname": "Brussels Airport - Zaventem"
},
"time": "1736361360",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC2342",
"vehicleinfo": {
"name": "BE.NMBS.IC2342",
"shortname": "IC 2342",
"number": "2342",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC2342"
},
"platform": "17",
"platforminfo": {
"name": "17",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC2342"
},
{
"id": "53",
"station": "Louvain-la-Neuve",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008811676",
"id": "BE.NMBS.008811676",
"name": "Louvain-la-Neuve",
"locationX": "4.615745",
"locationY": "50.669793",
"standardname": "Louvain-la-Neuve"
},
"time": "1736361540",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S83990",
"vehicleinfo": {
"name": "BE.NMBS.S83990",
"shortname": "S8 3990",
"number": "3990",
"type": "S8",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S83990"
},
"platform": "19",
"platforminfo": {
"name": "19",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S83990"
},
{
"id": "54",
"station": "Noorderkempen (brecht)",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821105",
"id": "BE.NMBS.008821105",
"name": "Noorderkempen (brecht)",
"locationX": "4.632204",
"locationY": "51.356838",
"standardname": "Noorderkempen"
},
"time": "1736361660",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.IC4540",
"vehicleinfo": {
"name": "BE.NMBS.IC4540",
"shortname": "IC 4540",
"number": "4540",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC4540"
},
"platform": "21",
"platforminfo": {
"name": "21",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/IC4540"
},
{
"id": "55",
"station": "Denderleeuw",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008895802",
"id": "BE.NMBS.008895802",
"name": "Denderleeuw",
"locationX": "4.071825",
"locationY": "50.891925",
"standardname": "Denderleeuw"
},
"time": "1736361660",
"delay": "0",
"canceled": "0",
"arrived": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.S32268",
"vehicleinfo": {
"name": "BE.NMBS.S32268",
"shortname": "S3 2268",
"number": "2268",
"type": "S3",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/S32268"
},
"platform": "9",
"platforminfo": {
"name": "9",
"normal": "1"
},
"departureConnection": "http://irail.be/connections/8814001/20250108/S32268"
}
]
}
} tjorim-pyrail-4c4ba2c/examples/stations.json 0000664 0000000 0000000 00000574210 14755342216 0021377 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736202192",
"station": [
{
"@id": "http://irail.be/stations/NMBS/008400319",
"id": "BE.NMBS.008400319",
"name": "'s Hertogenbosch",
"locationX": "5.294278",
"locationY": "51.69042",
"standardname": "'s Hertogenbosch"
},
{
"@id": "http://irail.be/stations/NMBS/008015345",
"id": "BE.NMBS.008015345",
"name": "Aachen Hbf",
"locationX": "6.105275",
"locationY": "50.770832",
"standardname": "Aachen Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008015199",
"id": "BE.NMBS.008015199",
"name": "Aachen West",
"locationX": "6.07055",
"locationY": "50.78078",
"standardname": "Aachen West"
},
{
"@id": "http://irail.be/stations/NMBS/008895000",
"id": "BE.NMBS.008895000",
"name": "Aalst",
"locationX": "4.039653",
"locationY": "50.942813",
"standardname": "Aalst"
},
{
"@id": "http://irail.be/stations/NMBS/008895125",
"id": "BE.NMBS.008895125",
"name": "Aalst-Kerrebroek",
"locationX": "4.024407",
"locationY": "50.948377",
"standardname": "Aalst-Kerrebroek"
},
{
"@id": "http://irail.be/stations/NMBS/008891140",
"id": "BE.NMBS.008891140",
"name": "Aalter",
"locationX": "3.447848",
"locationY": "51.092295",
"standardname": "Aalter"
},
{
"@id": "http://irail.be/stations/NMBS/008833209",
"id": "BE.NMBS.008833209",
"name": "Aarschot",
"locationX": "4.824043",
"locationY": "50.984406",
"standardname": "Aarschot"
},
{
"@id": "http://irail.be/stations/NMBS/008892288",
"id": "BE.NMBS.008892288",
"name": "Aarsele",
"locationX": "3.418363",
"locationY": "50.98446",
"standardname": "Aarsele"
},
{
"@id": "http://irail.be/stations/NMBS/008886546",
"id": "BE.NMBS.008886546",
"name": "Acren",
"locationX": "3.847086",
"locationY": "50.733095",
"standardname": "Acren"
},
{
"@id": "http://irail.be/stations/NMBS/008778127",
"id": "BE.NMBS.008778127",
"name": "Agde",
"locationX": "3.4658",
"locationY": "43.317498",
"standardname": "Agde"
},
{
"@id": "http://irail.be/stations/NMBS/008774176",
"id": "BE.NMBS.008774176",
"name": "Aime-la-Plagne",
"locationX": "6.648394",
"locationY": "45.554202",
"standardname": "Aime-la-Plagne"
},
{
"@id": "http://irail.be/stations/NMBS/008874583",
"id": "BE.NMBS.008874583",
"name": "Aiseau",
"locationX": "4.584552",
"locationY": "50.429529",
"standardname": "Aiseau"
},
{
"@id": "http://irail.be/stations/NMBS/008731901",
"id": "BE.NMBS.008731901",
"name": "Aix-en-Provence TGV",
"locationX": "5.433333",
"locationY": "43.53333",
"standardname": "Aix-en-Provence TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008774164",
"id": "BE.NMBS.008774164",
"name": "Albertville",
"locationX": "6.383617",
"locationY": "45.673624",
"standardname": "Albertville"
},
{
"@id": "http://irail.be/stations/NMBS/008831039",
"id": "BE.NMBS.008831039",
"name": "Alken",
"locationX": "5.292866",
"locationY": "50.886837",
"standardname": "Alken"
},
{
"@id": "http://irail.be/stations/NMBS/008400081",
"id": "BE.NMBS.008400081",
"name": "Almere Buiten",
"locationX": "5.277962",
"locationY": "52.394175",
"standardname": "Almere Buiten"
},
{
"@id": "http://irail.be/stations/NMBS/008400080",
"id": "BE.NMBS.008400080",
"name": "Almere Centrum",
"locationX": "5.217778",
"locationY": "52.375",
"standardname": "Almere Centrum"
},
{
"@id": "http://irail.be/stations/NMBS/008843331",
"id": "BE.NMBS.008843331",
"name": "Amay",
"locationX": "5.32049",
"locationY": "50.546011",
"standardname": "Amay"
},
{
"@id": "http://irail.be/stations/NMBS/008843323",
"id": "BE.NMBS.008843323",
"name": "Ampsin",
"locationX": "5.289729",
"locationY": "50.539215",
"standardname": "Ampsin"
},
{
"@id": "http://irail.be/stations/NMBS/008400058",
"id": "BE.NMBS.008400058",
"name": "Amsterdam CS",
"locationX": "4.900632",
"locationY": "52.37908",
"standardname": "Amsterdam CS"
},
{
"@id": "http://irail.be/stations/NMBS/008400061",
"id": "BE.NMBS.008400061",
"name": "Amsterdam South",
"locationX": "4.871946",
"locationY": "52.338865",
"standardname": "Amsterdam Zuid"
},
{
"@id": "http://irail.be/stations/NMBS/008863404",
"id": "BE.NMBS.008863404",
"name": "Andenne",
"locationX": "5.094699",
"locationY": "50.496759",
"standardname": "Andenne"
},
{
"@id": "http://irail.be/stations/NMBS/008811940",
"id": "BE.NMBS.008811940",
"name": "Anderlecht",
"locationX": "4.2918",
"locationY": "50.8179",
"standardname": "Anderlecht"
},
{
"@id": "http://irail.be/stations/NMBS/008842002",
"id": "BE.NMBS.008842002",
"name": "Angleur",
"locationX": "5.599695",
"locationY": "50.613152",
"standardname": "Angleur"
},
{
"@id": "http://irail.be/stations/NMBS/008728685",
"id": "BE.NMBS.008728685",
"name": "Annappes",
"locationX": "3.15",
"locationY": "50.633333",
"standardname": "Annappes"
},
{
"@id": "http://irail.be/stations/NMBS/008841202",
"id": "BE.NMBS.008841202",
"name": "Ans",
"locationX": "5.509704",
"locationY": "50.661208",
"standardname": "Ans"
},
{
"@id": "http://irail.be/stations/NMBS/008863818",
"id": "BE.NMBS.008863818",
"name": "Anseremme",
"locationX": "4.90553",
"locationY": "50.238023",
"standardname": "Anseremme"
},
{
"@id": "http://irail.be/stations/NMBS/008775767",
"id": "BE.NMBS.008775767",
"name": "Antibes",
"locationX": "7.1201361",
"locationY": "43.586618",
"standardname": "Antibes"
},
{
"@id": "http://irail.be/stations/NMBS/008885522",
"id": "BE.NMBS.008885522",
"name": "Antoing",
"locationX": "3.451309",
"locationY": "50.569626",
"standardname": "Antoing"
},
{
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
{
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
{
"@id": "http://irail.be/stations/NMBS/008821022",
"id": "BE.NMBS.008821022",
"name": "Antwerp-East",
"locationX": "4.436392",
"locationY": "51.207357",
"standardname": "Antwerpen-Oost"
},
{
"@id": "http://irail.be/stations/NMBS/008821048",
"id": "BE.NMBS.008821048",
"name": "Antwerp-Haven",
"locationX": "4.379086",
"locationY": "51.289968",
"standardname": "Antwerpen-Haven"
},
{
"@id": "http://irail.be/stations/NMBS/008821063",
"id": "BE.NMBS.008821063",
"name": "Antwerp-Luchtbal",
"locationX": "4.425029",
"locationY": "51.244132",
"standardname": "Antwerpen-Luchtbal"
},
{
"@id": "http://irail.be/stations/NMBS/008821089",
"id": "BE.NMBS.008821089",
"name": "Antwerp-Noorderdokken",
"locationX": "4.427906",
"locationY": "51.261643",
"standardname": "Antwerpen-Noorderdokken"
},
{
"@id": "http://irail.be/stations/NMBS/008821196",
"id": "BE.NMBS.008821196",
"name": "Antwerp-South",
"locationX": "4.390259",
"locationY": "51.197828",
"standardname": "Antwerpen-Zuid"
},
{
"@id": "http://irail.be/stations/NMBS/008821030",
"id": "BE.NMBS.008821030",
"name": "Antwerpen-Dam",
"locationX": "4.426238",
"locationY": "51.231991",
"standardname": "Antwerpen-Dam"
},
{
"@id": "http://irail.be/stations/NMBS/008892734",
"id": "BE.NMBS.008892734",
"name": "Anzegem",
"locationX": "3.495014",
"locationY": "50.826385",
"standardname": "Anzegem"
},
{
"@id": "http://irail.be/stations/NMBS/008895745",
"id": "BE.NMBS.008895745",
"name": "Appelterre",
"locationX": "3.972108",
"locationY": "50.813063",
"standardname": "Appelterre"
},
{
"@id": "http://irail.be/stations/NMBS/008814472",
"id": "BE.NMBS.008814472",
"name": "Arcaden",
"locationX": "4.398333",
"locationY": "50.809722",
"standardname": "Arcaden/Arcades"
},
{
"@id": "http://irail.be/stations/NMBS/008811759",
"id": "BE.NMBS.008811759",
"name": "Archennes",
"locationX": "4.662444",
"locationY": "50.754345",
"standardname": "Archennes"
},
{
"@id": "http://irail.be/stations/NMBS/008866001",
"id": "BE.NMBS.008866001",
"name": "Arlon",
"locationX": "5.809971",
"locationY": "49.68053",
"standardname": "Arlon"
},
{
"@id": "http://irail.be/stations/NMBS/008734201",
"id": "BE.NMBS.008734201",
"name": "Arras",
"locationX": "2.78169",
"locationY": "50.28683",
"standardname": "Arras"
},
{
"@id": "http://irail.be/stations/NMBS/008728686",
"id": "BE.NMBS.008728686",
"name": "Ascq",
"locationX": "3.166666",
"locationY": "50.616666",
"standardname": "Ascq"
},
{
"@id": "http://irail.be/stations/NMBS/008812070",
"id": "BE.NMBS.008812070",
"name": "Asse",
"locationX": "4.207985",
"locationY": "50.906488",
"standardname": "Asse"
},
{
"@id": "http://irail.be/stations/NMBS/008864931",
"id": "BE.NMBS.008864931",
"name": "Assesse",
"locationX": "5.022839",
"locationY": "50.368133",
"standardname": "Assesse"
},
{
"@id": "http://irail.be/stations/NMBS/008886009",
"id": "BE.NMBS.008886009",
"name": "Ath",
"locationX": "3.777429",
"locationY": "50.626932",
"standardname": "Ath"
},
{
"@id": "http://irail.be/stations/NMBS/008866605",
"id": "BE.NMBS.008866605",
"name": "Athus",
"locationX": "5.828947",
"locationY": "49.563346",
"standardname": "Athus"
},
{
"@id": "http://irail.be/stations/NMBS/008869047",
"id": "BE.NMBS.008869047",
"name": "Athus-Frontiere",
"locationX": "5.824932",
"locationY": "49.551749",
"standardname": "Athus-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008866654",
"id": "BE.NMBS.008866654",
"name": "Aubange",
"locationX": "5.79806",
"locationY": "49.564093",
"standardname": "Aubange"
},
{
"@id": "http://irail.be/stations/NMBS/008869088",
"id": "BE.NMBS.008869088",
"name": "Aubange-Frontiere-Luxembourg",
"locationX": "5.826307",
"locationY": "49.549455",
"standardname": "Aubange-Frontiere-Luxembourg"
},
{
"@id": "http://irail.be/stations/NMBS/008729560",
"id": "BE.NMBS.008729560",
"name": "Aulnoye-Aymeries",
"locationX": "3.843413",
"locationY": "50.19744",
"standardname": "Aulnoye-Aymeries"
},
{
"@id": "http://irail.be/stations/NMBS/008874716",
"id": "BE.NMBS.008874716",
"name": "Auvelais",
"locationX": "4.630532",
"locationY": "50.449197",
"standardname": "Auvelais"
},
{
"@id": "http://irail.be/stations/NMBS/008731896",
"id": "BE.NMBS.008731896",
"name": "Avignon TGV",
"locationX": "4.816667",
"locationY": "43.95",
"standardname": "Avignon TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008864352",
"id": "BE.NMBS.008864352",
"name": "Aye",
"locationX": "5.301091",
"locationY": "50.224135",
"standardname": "Aye"
},
{
"@id": "http://irail.be/stations/NMBS/008842754",
"id": "BE.NMBS.008842754",
"name": "Aywaille",
"locationX": "5.672499",
"locationY": "50.472938",
"standardname": "Aywaille"
},
{
"@id": "http://irail.be/stations/NMBS/008727149",
"id": "BE.NMBS.008727149",
"name": "Aéroport Charles-de-Gaulle TGV",
"locationX": "2.571123",
"locationY": "49.003955",
"standardname": "Aéroport Charles-de-Gaulle TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008822160",
"id": "BE.NMBS.008822160",
"name": "Baasrode-Zuid",
"locationX": "4.153492",
"locationY": "51.019437",
"standardname": "Baasrode-Zuid"
},
{
"@id": "http://irail.be/stations/NMBS/008728687",
"id": "BE.NMBS.008728687",
"name": "Baisieux",
"locationX": "3.25",
"locationY": "50.6",
"standardname": "Baisieux"
},
{
"@id": "http://irail.be/stations/NMBS/008895257",
"id": "BE.NMBS.008895257",
"name": "Balegem-Dorp",
"locationX": "3.791425",
"locationY": "50.919612",
"standardname": "Balegem-Dorp"
},
{
"@id": "http://irail.be/stations/NMBS/008895240",
"id": "BE.NMBS.008895240",
"name": "Balegem-Zuid",
"locationX": "3.80587",
"locationY": "50.90051",
"standardname": "Balegem-Zuid"
},
{
"@id": "http://irail.be/stations/NMBS/008832045",
"id": "BE.NMBS.008832045",
"name": "Balen",
"locationX": "5.164986",
"locationY": "51.169099",
"standardname": "Balen"
},
{
"@id": "http://irail.be/stations/NMBS/008895463",
"id": "BE.NMBS.008895463",
"name": "Bambrugge",
"locationX": "3.935711",
"locationY": "50.913769",
"standardname": "Bambrugge"
},
{
"@id": "http://irail.be/stations/NMBS/008864451",
"id": "BE.NMBS.008864451",
"name": "Barvaux",
"locationX": "5.501542",
"locationY": "50.349417",
"standardname": "Barvaux"
},
{
"@id": "http://irail.be/stations/NMBS/008843430",
"id": "BE.NMBS.008843430",
"name": "Bas-Oha",
"locationX": "5.190937",
"locationY": "50.52263",
"standardname": "Bas-Oha"
},
{
"@id": "http://irail.be/stations/NMBS/008200718",
"id": "BE.NMBS.008200718",
"name": "Bascharage-Sanem",
"locationX": "5.923742",
"locationY": "49.55836",
"standardname": "Bascharage-Sanem"
},
{
"@id": "http://irail.be/stations/NMBS/008500010",
"id": "BE.NMBS.008500010",
"name": "Basel",
"locationX": "7.590716",
"locationY": "47.547408",
"standardname": "Basel"
},
{
"@id": "http://irail.be/stations/NMBS/008811734",
"id": "BE.NMBS.008811734",
"name": "Basse-Wavre",
"locationX": "4.621651",
"locationY": "50.72442",
"standardname": "Basse-Wavre"
},
{
"@id": "http://irail.be/stations/NMBS/008865128",
"id": "BE.NMBS.008865128",
"name": "Bastogne-Nord",
"locationX": "5.720744",
"locationY": "50.006919",
"standardname": "Bastogne-Nord"
},
{
"@id": "http://irail.be/stations/NMBS/008865110",
"id": "BE.NMBS.008865110",
"name": "Bastogne-Sud",
"locationX": "5.709858",
"locationY": "49.999737",
"standardname": "Bastogne-Sud"
},
{
"@id": "http://irail.be/stations/NMBS/008863867",
"id": "BE.NMBS.008863867",
"name": "Beauraing",
"locationX": "4.95684",
"locationY": "50.11443",
"standardname": "Beauraing"
},
{
"@id": "http://irail.be/stations/NMBS/008891124",
"id": "BE.NMBS.008891124",
"name": "Beernem",
"locationX": "3.329892",
"locationY": "51.128009",
"standardname": "Beernem"
},
{
"@id": "http://irail.be/stations/NMBS/008814423",
"id": "BE.NMBS.008814423",
"name": "Beersel",
"locationX": "4.302605",
"locationY": "50.766616",
"standardname": "Beersel"
},
{
"@id": "http://irail.be/stations/NMBS/008894151",
"id": "BE.NMBS.008894151",
"name": "Beervelde",
"locationX": "3.879384",
"locationY": "51.08753",
"standardname": "Beervelde"
},
{
"@id": "http://irail.be/stations/NMBS/008821865",
"id": "BE.NMBS.008821865",
"name": "Begijnendijk",
"locationX": "4.800338",
"locationY": "51.021972",
"standardname": "Begijnendijk"
},
{
"@id": "http://irail.be/stations/NMBS/008871183",
"id": "BE.NMBS.008871183",
"name": "Beignée",
"locationX": "4.406305",
"locationY": "50.333893",
"standardname": "Beignée"
},
{
"@id": "http://irail.be/stations/NMBS/008891157",
"id": "BE.NMBS.008891157",
"name": "Bellem",
"locationX": "3.487374",
"locationY": "51.083908",
"standardname": "Bellem"
},
{
"@id": "http://irail.be/stations/NMBS/008894433",
"id": "BE.NMBS.008894433",
"name": "Belsele",
"locationX": "4.088608",
"locationY": "51.150994",
"standardname": "Belsele"
},
{
"@id": "http://irail.be/stations/NMBS/008832235",
"id": "BE.NMBS.008832235",
"name": "Beringen",
"locationX": "5.235892",
"locationY": "51.050603",
"standardname": "Beringen"
},
{
"@id": "http://irail.be/stations/NMBS/008821816",
"id": "BE.NMBS.008821816",
"name": "Berlaar",
"locationX": "4.638811",
"locationY": "51.113662",
"standardname": "Berlaar"
},
{
"@id": "http://irail.be/stations/NMBS/008065969",
"id": "BE.NMBS.008065969",
"name": "Berlin Hbf",
"locationX": "13.369548",
"locationY": "52.525589",
"standardname": "Berlin Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008032318",
"id": "BE.NMBS.008032318",
"name": "Berlin Lichtenberg",
"locationX": "13.4965",
"locationY": "52.5097",
"standardname": "Berlin Lichtenberg"
},
{
"@id": "http://irail.be/stations/NMBS/008007817",
"id": "BE.NMBS.008007817",
"name": "Berlin Ostbahnhof",
"locationX": "13.45",
"locationY": "52.51667",
"standardname": "Berlin Ostbahnhof"
},
{
"@id": "http://irail.be/stations/NMBS/008200510",
"id": "BE.NMBS.008200510",
"name": "Bertrange Strassen",
"locationX": "6.060601",
"locationY": "49.613002",
"standardname": "Bertrange Strassen"
},
{
"@id": "http://irail.be/stations/NMBS/008865300",
"id": "BE.NMBS.008865300",
"name": "Bertrix",
"locationX": "5.267193",
"locationY": "49.852835",
"standardname": "Bertrix"
},
{
"@id": "http://irail.be/stations/NMBS/008873320",
"id": "BE.NMBS.008873320",
"name": "Berzée",
"locationX": "4.405909",
"locationY": "50.285603",
"standardname": "Berzée"
},
{
"@id": "http://irail.be/stations/NMBS/008861424",
"id": "BE.NMBS.008861424",
"name": "Beuzet",
"locationX": "4.748533",
"locationY": "50.534208",
"standardname": "Beuzet"
},
{
"@id": "http://irail.be/stations/NMBS/008894748",
"id": "BE.NMBS.008894748",
"name": "Beveren",
"locationX": "4.25952",
"locationY": "51.208336",
"standardname": "Beveren"
},
{
"@id": "http://irail.be/stations/NMBS/008832227",
"id": "BE.NMBS.008832227",
"name": "Beverlo",
"locationX": "5.234373",
"locationY": "51.087719",
"standardname": "Beverlo"
},
{
"@id": "http://irail.be/stations/NMBS/008811718",
"id": "BE.NMBS.008811718",
"name": "Bierges-Walibi",
"locationX": "4.594746",
"locationY": "50.707772",
"standardname": "Bierges-Walibi"
},
{
"@id": "http://irail.be/stations/NMBS/008841319",
"id": "BE.NMBS.008841319",
"name": "Bierset-Awans",
"locationX": "5.460551",
"locationY": "50.65861",
"standardname": "Bierset-Awans"
},
{
"@id": "http://irail.be/stations/NMBS/008831138",
"id": "BE.NMBS.008831138",
"name": "Bilzen",
"locationX": "5.50938",
"locationY": "50.868643",
"standardname": "Bilzen"
},
{
"@id": "http://irail.be/stations/NMBS/008882362",
"id": "BE.NMBS.008882362",
"name": "Binche",
"locationX": "4.172451",
"locationY": "50.408764",
"standardname": "Binche"
},
{
"@id": "http://irail.be/stations/NMBS/008896388",
"id": "BE.NMBS.008896388",
"name": "Bissegem",
"locationX": "3.224205",
"locationY": "50.825845",
"standardname": "Bissegem"
},
{
"@id": "http://irail.be/stations/NMBS/008889045",
"id": "BE.NMBS.008889045",
"name": "Blandain-Frontiere",
"locationX": "3.26373",
"locationY": "50.61749",
"standardname": "Blandain-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008891405",
"id": "BE.NMBS.008891405",
"name": "Blankenberge",
"locationX": "3.133864",
"locationY": "51.312432",
"standardname": "Blankenberge"
},
{
"@id": "http://irail.be/stations/NMBS/008861531",
"id": "BE.NMBS.008861531",
"name": "Blanmont",
"locationX": "4.636393",
"locationY": "50.619453",
"standardname": "Blanmont"
},
{
"@id": "http://irail.be/stations/NMBS/008884715",
"id": "BE.NMBS.008884715",
"name": "Blaton",
"locationX": "3.666304",
"locationY": "50.505461",
"standardname": "Blaton"
},
{
"@id": "http://irail.be/stations/NMBS/008841434",
"id": "BE.NMBS.008841434",
"name": "Bleret",
"locationX": "5.286394",
"locationY": "50.685065",
"standardname": "Bleret"
},
{
"@id": "http://irail.be/stations/NMBS/008812021",
"id": "BE.NMBS.008812021",
"name": "Bockstael",
"locationX": "4.348513",
"locationY": "50.87943",
"standardname": "Bockstael"
},
{
"@id": "http://irail.be/stations/NMBS/008821634",
"id": "BE.NMBS.008821634",
"name": "Boechout",
"locationX": "4.494489",
"locationY": "51.16348",
"standardname": "Boechout"
},
{
"@id": "http://irail.be/stations/NMBS/008831781",
"id": "BE.NMBS.008831781",
"name": "Bokrijk",
"locationX": "5.408386",
"locationY": "50.955812",
"standardname": "Bokrijk"
},
{
"@id": "http://irail.be/stations/NMBS/008864469",
"id": "BE.NMBS.008864469",
"name": "Bomal",
"locationX": "5.519304",
"locationY": "50.376798",
"standardname": "Bomal"
},
{
"@id": "http://irail.be/stations/NMBS/008015577",
"id": "BE.NMBS.008015577",
"name": "Bonn-Beuel (DE)",
"locationX": "7.1276",
"locationY": "50.7385",
"standardname": "Bonn-Beuel (DE)"
},
{
"@id": "http://irail.be/stations/NMBS/008821857",
"id": "BE.NMBS.008821857",
"name": "Booischot",
"locationX": "4.773478",
"locationY": "51.037344",
"standardname": "Booischot"
},
{
"@id": "http://irail.be/stations/NMBS/008822814",
"id": "BE.NMBS.008822814",
"name": "Boom",
"locationX": "4.360694",
"locationY": "51.090713",
"standardname": "Boom"
},
{
"@id": "http://irail.be/stations/NMBS/008814456",
"id": "BE.NMBS.008814456",
"name": "Boondaal/Boondael",
"locationX": "4.393387",
"locationY": "50.801665",
"standardname": "Boondaal/Boondael"
},
{
"@id": "http://irail.be/stations/NMBS/008822475",
"id": "BE.NMBS.008822475",
"name": "Boortmeerbeek",
"locationX": "4.5739",
"locationY": "50.981853",
"standardname": "Boortmeerbeek"
},
{
"@id": "http://irail.be/stations/NMBS/008758100",
"id": "BE.NMBS.008758100",
"name": "Bordeaux Saint Jean",
"locationX": "-0.5557068",
"locationY": "44.8256102",
"standardname": "Bordeaux Saint Jean"
},
{
"@id": "http://irail.be/stations/NMBS/008811163",
"id": "BE.NMBS.008811163",
"name": "Bordet",
"locationX": "4.410026",
"locationY": "50.877785",
"standardname": "Bordet"
},
{
"@id": "http://irail.be/stations/NMBS/008822772",
"id": "BE.NMBS.008822772",
"name": "Bornem",
"locationX": "4.240526",
"locationY": "51.099225",
"standardname": "Bornem"
},
{
"@id": "http://irail.be/stations/NMBS/008811437",
"id": "BE.NMBS.008811437",
"name": "Bosvoorde/Boitsfort",
"locationX": "4.408112",
"locationY": "50.794698",
"standardname": "Bosvoorde/Boitsfort"
},
{
"@id": "http://irail.be/stations/NMBS/008774179",
"id": "BE.NMBS.008774179",
"name": "Bourg-Saint-Maurice",
"locationX": "6.771664",
"locationY": "45.618826",
"standardname": "Bourg-Saint-Maurice"
},
{
"@id": "http://irail.be/stations/NMBS/008884319",
"id": "BE.NMBS.008884319",
"name": "Boussu",
"locationX": "3.797025",
"locationY": "50.436388",
"standardname": "Boussu"
},
{
"@id": "http://irail.be/stations/NMBS/008821725",
"id": "BE.NMBS.008821725",
"name": "Bouwel",
"locationX": "4.746511",
"locationY": "51.165764",
"standardname": "Bouwel"
},
{
"@id": "http://irail.be/stations/NMBS/008881463",
"id": "BE.NMBS.008881463",
"name": "Bracquegnies",
"locationX": "4.126345",
"locationY": "50.474457",
"standardname": "Bracquegnies"
},
{
"@id": "http://irail.be/stations/NMBS/008814258",
"id": "BE.NMBS.008814258",
"name": "Braine-l'Alleud",
"locationX": "4.375526",
"locationY": "50.684778",
"standardname": "Braine-l'Alleud"
},
{
"@id": "http://irail.be/stations/NMBS/008883006",
"id": "BE.NMBS.008883006",
"name": "Braine-le-Comte",
"locationX": "4.137662",
"locationY": "50.605079",
"standardname": "Braine-le-Comte"
},
{
"@id": "http://irail.be/stations/NMBS/008400131",
"id": "BE.NMBS.008400131",
"name": "Breda",
"locationX": "4.7764",
"locationY": "51.594459",
"standardname": "Breda"
},
{
"@id": "http://irail.be/stations/NMBS/008843901",
"id": "BE.NMBS.008843901",
"name": "Bressoux",
"locationX": "5.611057",
"locationY": "50.643967",
"standardname": "Bressoux"
},
{
"@id": "http://irail.be/stations/NMBS/008886066",
"id": "BE.NMBS.008886066",
"name": "Brugelette",
"locationX": "3.852551",
"locationY": "50.594229",
"standardname": "Brugelette"
},
{
"@id": "http://irail.be/stations/NMBS/008891009",
"id": "BE.NMBS.008891009",
"name": "Bruges",
"locationX": "3.216726",
"locationY": "51.197226",
"standardname": "Brugge"
},
{
"@id": "http://irail.be/stations/NMBS/008891033",
"id": "BE.NMBS.008891033",
"name": "Brugge-Sint-Pieters",
"locationX": "3.201795",
"locationY": "51.223115",
"standardname": "Brugge-Sint-Pieters"
},
{
"@id": "http://irail.be/stations/NMBS/008819406",
"id": "BE.NMBS.008819406",
"name": "Brussels Airport - Zaventem",
"locationX": "4.482076",
"locationY": "50.896456",
"standardname": "Brussels Airport - Zaventem"
},
{
"@id": "http://irail.be/stations/NMBS/008813003",
"id": "BE.NMBS.008813003",
"name": "Brussels-Central",
"locationX": "4.356801",
"locationY": "50.845658",
"standardname": "Brussel-Centraal/Bruxelles-Central"
},
{
"@id": "http://irail.be/stations/NMBS/008813037",
"id": "BE.NMBS.008813037",
"name": "Brussels-Chapelle/Brussels-Kapellekerk",
"locationX": "4.347866",
"locationY": "50.841127",
"standardname": "Brussel-Kapellekerk/Bruxelles-Chapelle"
},
{
"@id": "http://irail.be/stations/NMBS/008813045",
"id": "BE.NMBS.008813045",
"name": "Brussels-Congres",
"locationX": "4.362051",
"locationY": "50.852067",
"standardname": "Brussel-Congres/Bruxelles-Congrès"
},
{
"@id": "http://irail.be/stations/NMBS/008811304",
"id": "BE.NMBS.008811304",
"name": "Brussels-Luxemburg/Brussels-Luxembourg",
"locationX": "4.373674",
"locationY": "50.838943",
"standardname": "Brussel-Luxemburg/Bruxelles-Luxembourg"
},
{
"@id": "http://irail.be/stations/NMBS/008812005",
"id": "BE.NMBS.008812005",
"name": "Brussels-North",
"locationX": "4.360846",
"locationY": "50.859663",
"standardname": "Brussel-Noord/Bruxelles-Nord"
},
{
"@id": "http://irail.be/stations/NMBS/008811916",
"id": "BE.NMBS.008811916",
"name": "Brussels-Schuman",
"locationX": "4.380722",
"locationY": "50.843276",
"standardname": "Brussel-Schuman/Bruxelles-Schuman"
},
{
"@id": "http://irail.be/stations/NMBS/008814001",
"id": "BE.NMBS.008814001",
"name": "Brussels-South/Brussels-Midi",
"locationX": "4.336531",
"locationY": "50.835707",
"standardname": "Brussel-Zuid/Bruxelles-Midi"
},
{
"@id": "http://irail.be/stations/NMBS/008815040",
"id": "BE.NMBS.008815040",
"name": "Brussels-West",
"locationX": "4.321042",
"locationY": "50.848552",
"standardname": "Brussel-West/Bruxelles-Ouest"
},
{
"@id": "http://irail.be/stations/NMBS/008811148",
"id": "BE.NMBS.008811148",
"name": "Buda",
"locationX": "4.417074",
"locationY": "50.907495",
"standardname": "Buda"
},
{
"@id": "http://irail.be/stations/NMBS/008822145",
"id": "BE.NMBS.008822145",
"name": "Buggenhout",
"locationX": "4.201666",
"locationY": "51.016291",
"standardname": "Buggenhout"
},
{
"@id": "http://irail.be/stations/NMBS/008814340",
"id": "BE.NMBS.008814340",
"name": "Buizingen",
"locationX": "4.258558",
"locationY": "50.751577",
"standardname": "Buizingen"
},
{
"@id": "http://irail.be/stations/NMBS/008895455",
"id": "BE.NMBS.008895455",
"name": "Burst",
"locationX": "3.922416",
"locationY": "50.907198",
"standardname": "Burst"
},
{
"@id": "http://irail.be/stations/NMBS/008778100",
"id": "BE.NMBS.008778100",
"name": "Béziers",
"locationX": "3.218794",
"locationY": "43.336177",
"standardname": "Béziers"
},
{
"@id": "http://irail.be/stations/NMBS/008884889",
"id": "BE.NMBS.008884889",
"name": "Callenelle",
"locationX": "3.52618",
"locationY": "50.527359",
"standardname": "Callenelle"
},
{
"@id": "http://irail.be/stations/NMBS/008886074",
"id": "BE.NMBS.008886074",
"name": "Cambron-Casteau",
"locationX": "3.874809",
"locationY": "50.586759",
"standardname": "Cambron-Casteau"
},
{
"@id": "http://irail.be/stations/NMBS/008775762",
"id": "BE.NMBS.008775762",
"name": "Cannes",
"locationX": "7.019895",
"locationY": "43.553742",
"standardname": "Cannes"
},
{
"@id": "http://irail.be/stations/NMBS/008200518",
"id": "BE.NMBS.008200518",
"name": "Capellen",
"locationX": "5.990833",
"locationY": "49.645",
"standardname": "Capellen"
},
{
"@id": "http://irail.be/stations/NMBS/008865565",
"id": "BE.NMBS.008865565",
"name": "Carlsbourg",
"locationX": "5.092784",
"locationY": "49.905458",
"standardname": "Carlsbourg"
},
{
"@id": "http://irail.be/stations/NMBS/008882248",
"id": "BE.NMBS.008882248",
"name": "Carnieres",
"locationX": "4.263826",
"locationY": "50.447957",
"standardname": "Carnieres"
},
{
"@id": "http://irail.be/stations/NMBS/008811817",
"id": "BE.NMBS.008811817",
"name": "Ceroux-Mousty",
"locationX": "4.569046",
"locationY": "50.659941",
"standardname": "Ceroux-Mousty"
},
{
"@id": "http://irail.be/stations/NMBS/008774100",
"id": "BE.NMBS.008774100",
"name": "Chambéry-Challes-les-Eaux",
"locationX": "5.919756",
"locationY": "45.571498",
"standardname": "Chambéry-Challes-les-Eaux"
},
{
"@id": "http://irail.be/stations/NMBS/008861317",
"id": "BE.NMBS.008861317",
"name": "Chapelle-Dieu",
"locationX": "4.697627",
"locationY": "50.557374",
"standardname": "Chapelle-Dieu"
},
{
"@id": "http://irail.be/stations/NMBS/008864824",
"id": "BE.NMBS.008864824",
"name": "Chapois",
"locationX": "5.124255",
"locationY": "50.262366",
"standardname": "Chapois"
},
{
"@id": "http://irail.be/stations/NMBS/008872009",
"id": "BE.NMBS.008872009",
"name": "Charleroi-Central",
"locationX": "4.438567",
"locationY": "50.40471",
"standardname": "Charleroi-Central"
},
{
"@id": "http://irail.be/stations/NMBS/008872066",
"id": "BE.NMBS.008872066",
"name": "Charleroi-Ouest",
"locationX": "4.436653",
"locationY": "50.410948",
"standardname": "Charleroi-Ouest"
},
{
"@id": "http://irail.be/stations/NMBS/008861523",
"id": "BE.NMBS.008861523",
"name": "Chastre",
"locationX": "4.648888",
"locationY": "50.608819",
"standardname": "Chastre"
},
{
"@id": "http://irail.be/stations/NMBS/008842051",
"id": "BE.NMBS.008842051",
"name": "Chaudfontaine",
"locationX": "5.643734",
"locationY": "50.586982",
"standardname": "Chaudfontaine"
},
{
"@id": "http://irail.be/stations/NMBS/008863438",
"id": "BE.NMBS.008863438",
"name": "Château-de-Seilles",
"locationX": "5.081745",
"locationY": "50.497209",
"standardname": "Château-de-Seilles"
},
{
"@id": "http://irail.be/stations/NMBS/008874005",
"id": "BE.NMBS.008874005",
"name": "Châtelet",
"locationX": "4.521861",
"locationY": "50.410103",
"standardname": "Châtelet"
},
{
"@id": "http://irail.be/stations/NMBS/008842036",
"id": "BE.NMBS.008842036",
"name": "Chênée",
"locationX": "5.616073",
"locationY": "50.608019",
"standardname": "Chênée"
},
{
"@id": "http://irail.be/stations/NMBS/008864501",
"id": "BE.NMBS.008864501",
"name": "Ciney",
"locationX": "5.091409",
"locationY": "50.29105",
"standardname": "Ciney"
},
{
"@id": "http://irail.be/stations/NMBS/008200134",
"id": "BE.NMBS.008200134",
"name": "Clervaux",
"locationX": "6.031393",
"locationY": "50.054724",
"standardname": "Clervaux"
},
{
"@id": "http://irail.be/stations/NMBS/008718201",
"id": "BE.NMBS.008718201",
"name": "Colmar",
"locationX": "7.366668",
"locationY": "48.083335",
"standardname": "Colmar"
},
{
"@id": "http://irail.be/stations/NMBS/008842838",
"id": "BE.NMBS.008842838",
"name": "Comblain-la-Tour",
"locationX": "5.566956",
"locationY": "50.456865",
"standardname": "Comblain-la-Tour"
},
{
"@id": "http://irail.be/stations/NMBS/008845229",
"id": "BE.NMBS.008845229",
"name": "Coo",
"locationX": "5.880473",
"locationY": "50.391127",
"standardname": "Coo"
},
{
"@id": "http://irail.be/stations/NMBS/008874054",
"id": "BE.NMBS.008874054",
"name": "Couillet",
"locationX": "4.46851",
"locationY": "50.392718",
"standardname": "Couillet"
},
{
"@id": "http://irail.be/stations/NMBS/008873379",
"id": "BE.NMBS.008873379",
"name": "Cour-sur-Heure",
"locationX": "4.391491",
"locationY": "50.300138",
"standardname": "Cour-sur-Heure"
},
{
"@id": "http://irail.be/stations/NMBS/008871225",
"id": "BE.NMBS.008871225",
"name": "Courcelles-Motte",
"locationX": "4.400534",
"locationY": "50.462007",
"standardname": "Courcelles-Motte"
},
{
"@id": "http://irail.be/stations/NMBS/008864949",
"id": "BE.NMBS.008864949",
"name": "Courrière",
"locationX": "4.996051",
"locationY": "50.387442",
"standardname": "Courrière"
},
{
"@id": "http://irail.be/stations/NMBS/008811825",
"id": "BE.NMBS.008811825",
"name": "Court-Saint-Étienne",
"locationX": "4.565819",
"locationY": "50.645567",
"standardname": "Court-Saint-Étienne"
},
{
"@id": "http://irail.be/stations/NMBS/008875127",
"id": "BE.NMBS.008875127",
"name": "Couvin",
"locationX": "4.491702",
"locationY": "50.056324",
"standardname": "Couvin"
},
{
"@id": "http://irail.be/stations/NMBS/008701687",
"id": "BE.NMBS.008701687",
"name": "Creil",
"locationX": "2.469167",
"locationY": "49.263889",
"standardname": "Creil"
},
{
"@id": "http://irail.be/stations/NMBS/008728671",
"id": "BE.NMBS.008728671",
"name": "Croix Wasquehal",
"locationX": "3.15",
"locationY": "50.666667",
"standardname": "Croix Wasquehal"
},
{
"@id": "http://irail.be/stations/NMBS/008728105",
"id": "BE.NMBS.008728105",
"name": "Croix l'Allumette",
"locationX": "3.150797",
"locationY": "50.68668",
"standardname": "Croix l'Allumette"
},
{
"@id": "http://irail.be/stations/NMBS/008863362",
"id": "BE.NMBS.008863362",
"name": "Dave-Saint-Martin",
"locationX": "4.884414",
"locationY": "50.429098",
"standardname": "Dave-Saint-Martin"
},
{
"@id": "http://irail.be/stations/NMBS/008814175",
"id": "BE.NMBS.008814175",
"name": "De Hoek",
"locationX": "4.370717",
"locationY": "50.738812",
"standardname": "De Hoek"
},
{
"@id": "http://irail.be/stations/NMBS/008892338",
"id": "BE.NMBS.008892338",
"name": "De Panne",
"locationX": "2.601963",
"locationY": "51.0774",
"standardname": "De Panne"
},
{
"@id": "http://irail.be/stations/NMBS/008892080",
"id": "BE.NMBS.008892080",
"name": "De Pinte",
"locationX": "3.650465",
"locationY": "50.997063",
"standardname": "De Pinte"
},
{
"@id": "http://irail.be/stations/NMBS/008892106",
"id": "BE.NMBS.008892106",
"name": "Deinze",
"locationX": "3.534432",
"locationY": "50.978258",
"standardname": "Deinze"
},
{
"@id": "http://irail.be/stations/NMBS/008811205",
"id": "BE.NMBS.008811205",
"name": "Delta",
"locationX": "4.403869",
"locationY": "50.818357",
"standardname": "Delta"
},
{
"@id": "http://irail.be/stations/NMBS/008400280",
"id": "BE.NMBS.008400280",
"name": "Den Haag HS",
"locationX": "4.299999",
"locationY": "52.083329",
"standardname": "Den Haag HS"
},
{
"@id": "http://irail.be/stations/NMBS/008895802",
"id": "BE.NMBS.008895802",
"name": "Denderleeuw",
"locationX": "4.071825",
"locationY": "50.891925",
"standardname": "Denderleeuw"
},
{
"@id": "http://irail.be/stations/NMBS/008893401",
"id": "BE.NMBS.008893401",
"name": "Dendermonde",
"locationX": "4.101427",
"locationY": "51.022781",
"standardname": "Dendermonde"
},
{
"@id": "http://irail.be/stations/NMBS/008811213",
"id": "BE.NMBS.008811213",
"name": "Diegem",
"locationX": "4.442774",
"locationY": "50.890478",
"standardname": "Diegem"
},
{
"@id": "http://irail.be/stations/NMBS/008831112",
"id": "BE.NMBS.008831112",
"name": "Diepenbeek",
"locationX": "5.419947",
"locationY": "50.910452",
"standardname": "Diepenbeek"
},
{
"@id": "http://irail.be/stations/NMBS/008814464",
"id": "BE.NMBS.008814464",
"name": "Diesdelle/Vivier d'Oie",
"locationX": "4.374052",
"locationY": "50.796145",
"standardname": "Diesdelle/Vivier d'Oie"
},
{
"@id": "http://irail.be/stations/NMBS/008831401",
"id": "BE.NMBS.008831401",
"name": "Diest",
"locationX": "5.050031",
"locationY": "50.993341",
"standardname": "Diest"
},
{
"@id": "http://irail.be/stations/NMBS/008892452",
"id": "BE.NMBS.008892452",
"name": "Diksmuide",
"locationX": "2.868943",
"locationY": "51.032723",
"standardname": "Diksmuide"
},
{
"@id": "http://irail.be/stations/NMBS/008812237",
"id": "BE.NMBS.008812237",
"name": "Dilbeek",
"locationX": "4.243393",
"locationY": "50.866728",
"standardname": "Dilbeek"
},
{
"@id": "http://irail.be/stations/NMBS/008863503",
"id": "BE.NMBS.008863503",
"name": "Dinant",
"locationX": "4.908182",
"locationY": "50.260721",
"standardname": "Dinant"
},
{
"@id": "http://irail.be/stations/NMBS/008200714",
"id": "BE.NMBS.008200714",
"name": "Dippach-Reckange",
"locationX": "5.995267",
"locationY": "49.57256",
"standardname": "Dippach-Reckange"
},
{
"@id": "http://irail.be/stations/NMBS/008844545",
"id": "BE.NMBS.008844545",
"name": "Dolhain-Gileppe",
"locationX": "5.936494",
"locationY": "50.616244",
"standardname": "Dolhain-Gileppe"
},
{
"@id": "http://irail.be/stations/NMBS/008200101",
"id": "BE.NMBS.008200101",
"name": "Dommeldange",
"locationX": "6.13668",
"locationY": "49.633838",
"standardname": "Dommeldange"
},
{
"@id": "http://irail.be/stations/NMBS/008400180",
"id": "BE.NMBS.008400180",
"name": "Dordrecht",
"locationX": "4.666668",
"locationY": "51.799998",
"standardname": "Dordrecht"
},
{
"@id": "http://irail.be/stations/NMBS/008010053",
"id": "BE.NMBS.008010053",
"name": "Dortmund Hbf",
"locationX": "7.459293",
"locationY": "51.517898",
"standardname": "Dortmund Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008200133",
"id": "BE.NMBS.008200133",
"name": "Drauffelt",
"locationX": "6.006106",
"locationY": "50.017778",
"standardname": "Drauffelt"
},
{
"@id": "http://irail.be/stations/NMBS/008892031",
"id": "BE.NMBS.008892031",
"name": "Drongen",
"locationX": "3.655202",
"locationY": "51.047295",
"standardname": "Drongen"
},
{
"@id": "http://irail.be/stations/NMBS/008015653",
"id": "BE.NMBS.008015653",
"name": "Duesseldorf Flughafen (DE)",
"locationX": "6.767052",
"locationY": "51.27656",
"standardname": "Duesseldorf Flughafen (DE)"
},
{
"@id": "http://irail.be/stations/NMBS/008822210",
"id": "BE.NMBS.008822210",
"name": "Duffel",
"locationX": "4.493186",
"locationY": "51.091243",
"standardname": "Duffel"
},
{
"@id": "http://irail.be/stations/NMBS/008891652",
"id": "BE.NMBS.008891652",
"name": "Duinbergen",
"locationX": "3.263587",
"locationY": "51.338195",
"standardname": "Duinbergen"
},
{
"@id": "http://irail.be/stations/NMBS/008010316",
"id": "BE.NMBS.008010316",
"name": "Duisburg Hbf",
"locationX": "6.7759037",
"locationY": "51.42978",
"standardname": "Duisburg Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008008094",
"id": "BE.NMBS.008008094",
"name": "Dusseldorf Hbf",
"locationX": "6.795297",
"locationY": "51.219178",
"standardname": "Duesseldorf Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008039904",
"id": "BE.NMBS.008039904",
"name": "Düsseldorf Flughafen Hbf",
"locationX": "6.786837",
"locationY": "51.292008",
"standardname": "Düsseldorf Flughafen Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/007015440",
"id": "BE.NMBS.007015440",
"name": "Ebbsfleet International",
"locationX": "0.275775",
"locationY": "51.45117",
"standardname": "Ebbsfleet International"
},
{
"@id": "http://irail.be/stations/NMBS/008895877",
"id": "BE.NMBS.008895877",
"name": "Ede",
"locationX": "3.987524",
"locationY": "50.911054",
"standardname": "Ede"
},
{
"@id": "http://irail.be/stations/NMBS/008883311",
"id": "BE.NMBS.008883311",
"name": "Edingen/Enghien",
"locationX": "4.047357",
"locationY": "50.697273",
"standardname": "Enghien"
},
{
"@id": "http://irail.be/stations/NMBS/008893708",
"id": "BE.NMBS.008893708",
"name": "Eeklo",
"locationX": "3.574515",
"locationY": "51.181333",
"standardname": "Eeklo"
},
{
"@id": "http://irail.be/stations/NMBS/008895752",
"id": "BE.NMBS.008895752",
"name": "Eichem",
"locationX": "3.993745",
"locationY": "50.823994",
"standardname": "Eichem"
},
{
"@id": "http://irail.be/stations/NMBS/008400219",
"id": "BE.NMBS.008400219",
"name": "Eijsden",
"locationX": "5.709786",
"locationY": "50.772135",
"standardname": "Eijsden"
},
{
"@id": "http://irail.be/stations/NMBS/008892627",
"id": "BE.NMBS.008892627",
"name": "Eine",
"locationX": "3.623776",
"locationY": "50.870432",
"standardname": "Eine"
},
{
"@id": "http://irail.be/stations/NMBS/008892650",
"id": "BE.NMBS.008892650",
"name": "Eke-Nazareth",
"locationX": "3.627839",
"locationY": "50.960774",
"standardname": "Eke-Nazareth"
},
{
"@id": "http://irail.be/stations/NMBS/008821071",
"id": "BE.NMBS.008821071",
"name": "Ekeren",
"locationX": "4.434154",
"locationY": "51.281626",
"standardname": "Ekeren"
},
{
"@id": "http://irail.be/stations/NMBS/008843240",
"id": "BE.NMBS.008843240",
"name": "Engis",
"locationX": "5.401986",
"locationY": "50.582957",
"standardname": "Engis"
},
{
"@id": "http://irail.be/stations/NMBS/008822269",
"id": "BE.NMBS.008822269",
"name": "Eppegem",
"locationX": "4.45749",
"locationY": "50.9584",
"standardname": "Eppegem"
},
{
"@id": "http://irail.be/stations/NMBS/008881158",
"id": "BE.NMBS.008881158",
"name": "Erbisoeul",
"locationX": "3.887987",
"locationY": "50.507025",
"standardname": "Erbisœul"
},
{
"@id": "http://irail.be/stations/NMBS/008895091",
"id": "BE.NMBS.008895091",
"name": "Erembodegem",
"locationX": "4.055447",
"locationY": "50.919621",
"standardname": "Erembodegem"
},
{
"@id": "http://irail.be/stations/NMBS/008861515",
"id": "BE.NMBS.008861515",
"name": "Ernage",
"locationX": "4.668538",
"locationY": "50.590823",
"standardname": "Ernage"
},
{
"@id": "http://irail.be/stations/NMBS/008895471",
"id": "BE.NMBS.008895471",
"name": "Erpe-Mere",
"locationX": "3.962463",
"locationY": "50.928601",
"standardname": "Erpe-Mere"
},
{
"@id": "http://irail.be/stations/NMBS/008811262",
"id": "BE.NMBS.008811262",
"name": "Erps-Kwerps",
"locationX": "4.585001",
"locationY": "50.89651",
"standardname": "Erps-Kwerps"
},
{
"@id": "http://irail.be/stations/NMBS/008871605",
"id": "BE.NMBS.008871605",
"name": "Erquelinnes",
"locationX": "4.113562",
"locationY": "50.304192",
"standardname": "Erquelinnes"
},
{
"@id": "http://irail.be/stations/NMBS/008879004",
"id": "BE.NMBS.008879004",
"name": "Erquelinnes-Frontière",
"locationX": "4.107929",
"locationY": "50.30233",
"standardname": "Erquelinnes-Frontière"
},
{
"@id": "http://irail.be/stations/NMBS/008871647",
"id": "BE.NMBS.008871647",
"name": "Erquelinnes-Village",
"locationX": "4.132314",
"locationY": "50.310179",
"standardname": "Erquelinnes-Village"
},
{
"@id": "http://irail.be/stations/NMBS/008842663",
"id": "BE.NMBS.008842663",
"name": "Esneux",
"locationX": "5.572565",
"locationY": "50.530568",
"standardname": "Esneux"
},
{
"@id": "http://irail.be/stations/NMBS/008821402",
"id": "BE.NMBS.008821402",
"name": "Essen",
"locationX": "4.451314",
"locationY": "51.462767",
"standardname": "Essen"
},
{
"@id": "http://irail.be/stations/NMBS/008010184",
"id": "BE.NMBS.008010184",
"name": "Essen Hbf",
"locationX": "6.776118",
"locationY": "51.42952",
"standardname": "Essen Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008829009",
"id": "BE.NMBS.008829009",
"name": "Essen-Grens",
"locationX": "4.44893",
"locationY": "51.46909",
"standardname": "Essen-Grens"
},
{
"@id": "http://irail.be/stations/NMBS/008812260",
"id": "BE.NMBS.008812260",
"name": "Essene-Lombeek",
"locationX": "4.115171",
"locationY": "50.882451",
"standardname": "Essene-Lombeek"
},
{
"@id": "http://irail.be/stations/NMBS/008200120",
"id": "BE.NMBS.008200120",
"name": "Ettelbréck",
"locationX": "6.104169",
"locationY": "49.847496",
"standardname": "Ettelbréck"
},
{
"@id": "http://irail.be/stations/NMBS/008811411",
"id": "BE.NMBS.008811411",
"name": "Etterbeek",
"locationX": "4.389513",
"locationY": "50.822187",
"standardname": "Etterbeek"
},
{
"@id": "http://irail.be/stations/NMBS/008844628",
"id": "BE.NMBS.008844628",
"name": "Eupen",
"locationX": "6.03711",
"locationY": "50.635157",
"standardname": "Eupen"
},
{
"@id": "http://irail.be/stations/NMBS/008811106",
"id": "BE.NMBS.008811106",
"name": "Evere",
"locationX": "4.400965",
"locationY": "50.86778",
"standardname": "Evere"
},
{
"@id": "http://irail.be/stations/NMBS/008893252",
"id": "BE.NMBS.008893252",
"name": "Evergem",
"locationX": "3.70138",
"locationY": "51.107585",
"standardname": "Evergem"
},
{
"@id": "http://irail.be/stations/NMBS/008400234",
"id": "BE.NMBS.008400234",
"name": "Eygelshoven markt",
"locationX": "6.057451",
"locationY": "50.89607",
"standardname": "Eygelshoven markt"
},
{
"@id": "http://irail.be/stations/NMBS/008833449",
"id": "BE.NMBS.008833449",
"name": "Ezemaal",
"locationX": "4.994217",
"locationY": "50.772126",
"standardname": "Ezemaal"
},
{
"@id": "http://irail.be/stations/NMBS/008883238",
"id": "BE.NMBS.008883238",
"name": "Familleureux",
"locationX": "4.211581",
"locationY": "50.519358",
"standardname": "Familleureux"
},
{
"@id": "http://irail.be/stations/NMBS/008874567",
"id": "BE.NMBS.008874567",
"name": "Farciennes",
"locationX": "4.55265",
"locationY": "50.429148",
"standardname": "Farciennes"
},
{
"@id": "http://irail.be/stations/NMBS/008872611",
"id": "BE.NMBS.008872611",
"name": "Faux",
"locationX": "4.54926",
"locationY": "50.621826",
"standardname": "Faux"
},
{
"@id": "http://irail.be/stations/NMBS/008841467",
"id": "BE.NMBS.008841467",
"name": "Fexhe-le-Haut-Clocher",
"locationX": "5.398453",
"locationY": "50.664049",
"standardname": "Fexhe-le-Haut-Clocher"
},
{
"@id": "http://irail.be/stations/NMBS/008861127",
"id": "BE.NMBS.008861127",
"name": "Flawinne",
"locationX": "4.806298",
"locationY": "50.456236",
"standardname": "Flawinne"
},
{
"@id": "http://irail.be/stations/NMBS/008843166",
"id": "BE.NMBS.008843166",
"name": "Flemalle-Grande",
"locationX": "5.480983",
"locationY": "50.605349",
"standardname": "Flemalle-Grande"
},
{
"@id": "http://irail.be/stations/NMBS/008843208",
"id": "BE.NMBS.008843208",
"name": "Flemalle-Haute",
"locationX": "5.457656",
"locationY": "50.595308",
"standardname": "Flemalle-Haute"
},
{
"@id": "http://irail.be/stations/NMBS/008872413",
"id": "BE.NMBS.008872413",
"name": "Fleurus",
"locationX": "4.543741",
"locationY": "50.481927",
"standardname": "Fleurus"
},
{
"@id": "http://irail.be/stations/NMBS/008861135",
"id": "BE.NMBS.008861135",
"name": "Floreffe",
"locationX": "4.762368",
"locationY": "50.443328",
"standardname": "Floreffe"
},
{
"@id": "http://irail.be/stations/NMBS/008866845",
"id": "BE.NMBS.008866845",
"name": "Florenville",
"locationX": "5.331115",
"locationY": "49.706967",
"standardname": "Florenville"
},
{
"@id": "http://irail.be/stations/NMBS/008811767",
"id": "BE.NMBS.008811767",
"name": "Florival",
"locationX": "4.653868",
"locationY": "50.761501",
"standardname": "Florival"
},
{
"@id": "http://irail.be/stations/NMBS/008864923",
"id": "BE.NMBS.008864923",
"name": "Florée",
"locationX": "5.056099",
"locationY": "50.357786",
"standardname": "Florée"
},
{
"@id": "http://irail.be/stations/NMBS/008871688",
"id": "BE.NMBS.008871688",
"name": "Fontaine-Valmont",
"locationX": "4.212785",
"locationY": "50.321164",
"standardname": "Fontaine-Valmont"
},
{
"@id": "http://irail.be/stations/NMBS/008871514",
"id": "BE.NMBS.008871514",
"name": "Forchies",
"locationX": "4.325384",
"locationY": "50.433314",
"standardname": "Forchies"
},
{
"@id": "http://irail.be/stations/NMBS/008864311",
"id": "BE.NMBS.008864311",
"name": "Forrières",
"locationX": "5.276784",
"locationY": "50.132759",
"standardname": "Forrières"
},
{
"@id": "http://irail.be/stations/NMBS/008844255",
"id": "BE.NMBS.008844255",
"name": "Fraipont",
"locationX": "5.723665",
"locationY": "50.565059",
"standardname": "Fraipont"
},
{
"@id": "http://irail.be/stations/NMBS/008881570",
"id": "BE.NMBS.008881570",
"name": "Frameries",
"locationX": "3.906586",
"locationY": "50.405932",
"standardname": "Frameries"
},
{
"@id": "http://irail.be/stations/NMBS/008844347",
"id": "BE.NMBS.008844347",
"name": "Franchimont",
"locationX": "5.822223",
"locationY": "50.525723",
"standardname": "Franchimont"
},
{
"@id": "http://irail.be/stations/NMBS/008861143",
"id": "BE.NMBS.008861143",
"name": "Franière",
"locationX": "4.733548",
"locationY": "50.439543",
"standardname": "Franière"
},
{
"@id": "http://irail.be/stations/NMBS/008061676",
"id": "BE.NMBS.008061676",
"name": "Frankfurt am Main Flughafen Fernbf",
"locationX": "8.663611",
"locationY": "50.13083",
"standardname": "Frankfurt am Main Flughafen Fernbf"
},
{
"@id": "http://irail.be/stations/NMBS/008011090",
"id": "BE.NMBS.008011090",
"name": "Frankfurt am Main Flughafen Reginalbf",
"locationX": "8.569853",
"locationY": "50.051696",
"standardname": "Frankfurt am Main Flughafen Reginalbf"
},
{
"@id": "http://irail.be/stations/NMBS/008011068",
"id": "BE.NMBS.008011068",
"name": "Frankfurt am Main Hbf",
"locationX": "8.6653708",
"locationY": "50.1071318",
"standardname": "Frankfurt am Main Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008885068",
"id": "BE.NMBS.008885068",
"name": "Froyennes",
"locationX": "3.354837",
"locationY": "50.62989",
"standardname": "Froyennes"
},
{
"@id": "http://irail.be/stations/NMBS/008895620",
"id": "BE.NMBS.008895620",
"name": "Galmaarden",
"locationX": "3.965726",
"locationY": "50.743918",
"standardname": "Galmaarden"
},
{
"@id": "http://irail.be/stations/NMBS/008811742",
"id": "BE.NMBS.008811742",
"name": "Gastuche",
"locationX": "4.649598",
"locationY": "50.736646",
"standardname": "Gastuche"
},
{
"@id": "http://irail.be/stations/NMBS/008892643",
"id": "BE.NMBS.008892643",
"name": "Gavere-Asper",
"locationX": "3.639732",
"locationY": "50.930021",
"standardname": "Gavere-Asper"
},
{
"@id": "http://irail.be/stations/NMBS/008865649",
"id": "BE.NMBS.008865649",
"name": "Gedinne",
"locationX": "4.978073",
"locationY": "49.984123",
"standardname": "Gedinne"
},
{
"@id": "http://irail.be/stations/NMBS/008832433",
"id": "BE.NMBS.008832433",
"name": "Geel",
"locationX": "4.988608",
"locationY": "51.168955",
"standardname": "Geel"
},
{
"@id": "http://irail.be/stations/NMBS/008861200",
"id": "BE.NMBS.008861200",
"name": "Gembloux",
"locationX": "4.691497",
"locationY": "50.570489",
"standardname": "Gembloux"
},
{
"@id": "http://irail.be/stations/NMBS/008863834",
"id": "BE.NMBS.008863834",
"name": "Gendron-Celles",
"locationX": "4.964607",
"locationY": "50.211235",
"standardname": "Gendron-Celles"
},
{
"@id": "http://irail.be/stations/NMBS/008831765",
"id": "BE.NMBS.008831765",
"name": "Genk",
"locationX": "5.497685",
"locationY": "50.967057",
"standardname": "Genk"
},
{
"@id": "http://irail.be/stations/NMBS/008881562",
"id": "BE.NMBS.008881562",
"name": "Genly",
"locationX": "3.911638",
"locationY": "50.390642",
"standardname": "Genly"
},
{
"@id": "http://irail.be/stations/NMBS/008893179",
"id": "BE.NMBS.008893179",
"name": "Gentbrugge",
"locationX": "3.756322",
"locationY": "51.038647",
"standardname": "Gentbrugge"
},
{
"@id": "http://irail.be/stations/NMBS/008811528",
"id": "BE.NMBS.008811528",
"name": "Genval",
"locationX": "4.514832",
"locationY": "50.725697",
"standardname": "Genval"
},
{
"@id": "http://irail.be/stations/NMBS/008895505",
"id": "BE.NMBS.008895505",
"name": "Geraardsbergen",
"locationX": "3.872328",
"locationY": "50.771137",
"standardname": "Geraardsbergen"
},
{
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
{
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
{
"@id": "http://irail.be/stations/NMBS/008881125",
"id": "BE.NMBS.008881125",
"name": "Ghlin",
"locationX": "3.906343",
"locationY": "50.487411",
"standardname": "Ghlin"
},
{
"@id": "http://irail.be/stations/NMBS/008841731",
"id": "BE.NMBS.008841731",
"name": "Glons",
"locationX": "5.535431",
"locationY": "50.750426",
"standardname": "Glons"
},
{
"@id": "http://irail.be/stations/NMBS/008871381",
"id": "BE.NMBS.008871381",
"name": "Godarville",
"locationX": "4.290308",
"locationY": "50.492795",
"standardname": "Godarville"
},
{
"@id": "http://irail.be/stations/NMBS/008863560",
"id": "BE.NMBS.008863560",
"name": "Godinne",
"locationX": "4.86996",
"locationY": "50.348914",
"standardname": "Godinne"
},
{
"@id": "http://irail.be/stations/NMBS/008200129",
"id": "BE.NMBS.008200129",
"name": "Goebelsmühle",
"locationX": "6.053335",
"locationY": "49.92104",
"standardname": "Goebelsmühle"
},
{
"@id": "http://irail.be/stations/NMBS/008893047",
"id": "BE.NMBS.008893047",
"name": "Gontrode",
"locationX": "3.801672",
"locationY": "50.980199",
"standardname": "Gontrode"
},
{
"@id": "http://irail.be/stations/NMBS/008845005",
"id": "BE.NMBS.008845005",
"name": "Gouvy",
"locationX": "5.953906",
"locationY": "50.189409",
"standardname": "Gouvy"
},
{
"@id": "http://irail.be/stations/NMBS/008849072",
"id": "BE.NMBS.008849072",
"name": "Gouvy-Frontiere",
"locationX": "5.968613",
"locationY": "50.171653",
"standardname": "Gouvy-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008871373",
"id": "BE.NMBS.008871373",
"name": "Gouy-lez-Pieton",
"locationX": "4.325123",
"locationY": "50.497065",
"standardname": "Gouy-lez-Pieton"
},
{
"@id": "http://irail.be/stations/NMBS/008865615",
"id": "BE.NMBS.008865615",
"name": "Graide",
"locationX": "5.043047",
"locationY": "49.934134",
"standardname": "Graide"
},
{
"@id": "http://irail.be/stations/NMBS/008811445",
"id": "BE.NMBS.008811445",
"name": "Groenendaal",
"locationX": "4.449489",
"locationY": "50.766103",
"standardname": "Groenendaal"
},
{
"@id": "http://irail.be/stations/NMBS/008812229",
"id": "BE.NMBS.008812229",
"name": "Groot-Bijgaarden",
"locationX": "4.273543",
"locationY": "50.868337",
"standardname": "Groot-Bijgaarden"
},
{
"@id": "http://irail.be/stations/NMBS/008864337",
"id": "BE.NMBS.008864337",
"name": "Grupont",
"locationX": "5.280524",
"locationY": "50.0906",
"standardname": "Grupont"
},
{
"@id": "http://irail.be/stations/NMBS/008822517",
"id": "BE.NMBS.008822517",
"name": "Haacht",
"locationX": "4.613309",
"locationY": "50.966428",
"standardname": "Haacht"
},
{
"@id": "http://irail.be/stations/NMBS/008895869",
"id": "BE.NMBS.008895869",
"name": "Haaltert",
"locationX": "4.023958",
"locationY": "50.906838",
"standardname": "Haaltert"
},
{
"@id": "http://irail.be/stations/NMBS/008866142",
"id": "BE.NMBS.008866142",
"name": "Habay",
"locationX": "5.632685",
"locationY": "49.718249",
"standardname": "Habay"
},
{
"@id": "http://irail.be/stations/NMBS/008884327",
"id": "BE.NMBS.008884327",
"name": "Hainin",
"locationX": "3.766893",
"locationY": "50.428019",
"standardname": "Hainin"
},
{
"@id": "http://irail.be/stations/NMBS/008866530",
"id": "BE.NMBS.008866530",
"name": "Halanzy",
"locationX": "5.741347",
"locationY": "49.5562",
"standardname": "Halanzy"
},
{
"@id": "http://irail.be/stations/NMBS/008814308",
"id": "BE.NMBS.008814308",
"name": "Halle",
"locationX": "4.240634",
"locationY": "50.733931",
"standardname": "Halle"
},
{
"@id": "http://irail.be/stations/NMBS/008873387",
"id": "BE.NMBS.008873387",
"name": "Ham-sur-Heure",
"locationX": "4.404696",
"locationY": "50.319555",
"standardname": "Ham-sur-Heure"
},
{
"@id": "http://irail.be/stations/NMBS/008861168",
"id": "BE.NMBS.008861168",
"name": "Ham-sur-Sambre",
"locationX": "4.669392",
"locationY": "50.45255",
"standardname": "Ham-sur-Sambre"
},
{
"@id": "http://irail.be/stations/NMBS/008822533",
"id": "BE.NMBS.008822533",
"name": "Hambos",
"locationX": "4.66301",
"locationY": "50.944251",
"standardname": "Hambos"
},
{
"@id": "http://irail.be/stations/NMBS/008842846",
"id": "BE.NMBS.008842846",
"name": "Hamoir",
"locationX": "5.533561",
"locationY": "50.428181",
"standardname": "Hamoir"
},
{
"@id": "http://irail.be/stations/NMBS/008832664",
"id": "BE.NMBS.008832664",
"name": "Hamont",
"locationX": "5.543279",
"locationY": "51.246424",
"standardname": "Hamont"
},
{
"@id": "http://irail.be/stations/NMBS/008891165",
"id": "BE.NMBS.008891165",
"name": "Hansbeke",
"locationX": "3.536212",
"locationY": "51.073202",
"standardname": "Hansbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008884640",
"id": "BE.NMBS.008884640",
"name": "Harchies",
"locationX": "3.698764",
"locationY": "50.482565",
"standardname": "Harchies"
},
{
"@id": "http://irail.be/stations/NMBS/008896115",
"id": "BE.NMBS.008896115",
"name": "Harelbeke",
"locationX": "3.314008",
"locationY": "50.85586",
"standardname": "Harelbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008811155",
"id": "BE.NMBS.008811155",
"name": "Haren",
"locationX": "4.419978",
"locationY": "50.888878",
"standardname": "Haren"
},
{
"@id": "http://irail.be/stations/NMBS/008811130",
"id": "BE.NMBS.008811130",
"name": "Haren-Sud/Haren-Zuid",
"locationX": "4.415357",
"locationY": "50.889696",
"standardname": "Haren-Sud/Haren-Zuid"
},
{
"@id": "http://irail.be/stations/NMBS/008831005",
"id": "BE.NMBS.008831005",
"name": "Hasselt",
"locationX": "5.327627",
"locationY": "50.930822",
"standardname": "Hasselt"
},
{
"@id": "http://irail.be/stations/NMBS/008843349",
"id": "BE.NMBS.008843349",
"name": "Haute-Flône",
"locationX": "5.330333",
"locationY": "50.55349",
"standardname": "Haute-Flône"
},
{
"@id": "http://irail.be/stations/NMBS/008731388",
"id": "BE.NMBS.008731388",
"name": "Haute-Picardie TGV",
"locationX": "2.49565",
"locationY": "49.85894",
"standardname": "Haute-Picardie TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008864832",
"id": "BE.NMBS.008864832",
"name": "Haversin",
"locationX": "5.194371",
"locationY": "50.249044",
"standardname": "Haversin"
},
{
"@id": "http://irail.be/stations/NMBS/008881430",
"id": "BE.NMBS.008881430",
"name": "Havre",
"locationX": "4.059987",
"locationY": "50.470754",
"standardname": "Havre"
},
{
"@id": "http://irail.be/stations/NMBS/008400307",
"id": "BE.NMBS.008400307",
"name": "Heerlen",
"locationX": "5.974577",
"locationY": "50.89095",
"standardname": "Heerlen"
},
{
"@id": "http://irail.be/stations/NMBS/008821519",
"id": "BE.NMBS.008821519",
"name": "Heide",
"locationX": "4.460483",
"locationY": "51.364623",
"standardname": "Heide"
},
{
"@id": "http://irail.be/stations/NMBS/008891645",
"id": "BE.NMBS.008891645",
"name": "Heist",
"locationX": "3.239181",
"locationY": "51.333979",
"standardname": "Heist"
},
{
"@id": "http://irail.be/stations/NMBS/008821832",
"id": "BE.NMBS.008821832",
"name": "Heist-op-den-Berg",
"locationX": "4.708235",
"locationY": "51.074146",
"standardname": "Heist-op-den-Berg"
},
{
"@id": "http://irail.be/stations/NMBS/008812153",
"id": "BE.NMBS.008812153",
"name": "Heizijde",
"locationX": "4.156171",
"locationY": "50.989593",
"standardname": "Heizijde"
},
{
"@id": "http://irail.be/stations/NMBS/008728606",
"id": "BE.NMBS.008728606",
"name": "Hellemmes",
"locationX": "3.108892",
"locationY": "50.626941",
"standardname": "Hellemmes"
},
{
"@id": "http://irail.be/stations/NMBS/008824224",
"id": "BE.NMBS.008824224",
"name": "Hemiksem",
"locationX": "4.338293",
"locationY": "51.136243",
"standardname": "Hemiksem"
},
{
"@id": "http://irail.be/stations/NMBS/008883022",
"id": "BE.NMBS.008883022",
"name": "Hennuyères",
"locationX": "4.175893",
"locationY": "50.651005",
"standardname": "Hennuyères"
},
{
"@id": "http://irail.be/stations/NMBS/008811288",
"id": "BE.NMBS.008811288",
"name": "Herent",
"locationX": "4.672188",
"locationY": "50.90353",
"standardname": "Herent"
},
{
"@id": "http://irail.be/stations/NMBS/008821717",
"id": "BE.NMBS.008821717",
"name": "Herentals",
"locationX": "4.829535",
"locationY": "51.181513",
"standardname": "Herentals"
},
{
"@id": "http://irail.be/stations/NMBS/008844644",
"id": "BE.NMBS.008844644",
"name": "Hergenrath",
"locationX": "6.041335",
"locationY": "50.718209",
"standardname": "Hergenrath"
},
{
"@id": "http://irail.be/stations/NMBS/008849023",
"id": "BE.NMBS.008849023",
"name": "Hergenrath-Frontiere",
"locationX": "6.041269",
"locationY": "50.718955",
"standardname": "Hergenrath-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008895646",
"id": "BE.NMBS.008895646",
"name": "Herne",
"locationX": "4.014573",
"locationY": "50.723701",
"standardname": "Herne"
},
{
"@id": "http://irail.be/stations/NMBS/008885753",
"id": "BE.NMBS.008885753",
"name": "Herseaux",
"locationX": "3.245959",
"locationY": "50.713894",
"standardname": "Herseaux"
},
{
"@id": "http://irail.be/stations/NMBS/008841608",
"id": "BE.NMBS.008841608",
"name": "Herstal",
"locationX": "5.622761",
"locationY": "50.660911",
"standardname": "Herstal"
},
{
"@id": "http://irail.be/stations/NMBS/008895430",
"id": "BE.NMBS.008895430",
"name": "Herzele",
"locationX": "3.880616",
"locationY": "50.89722",
"standardname": "Herzele"
},
{
"@id": "http://irail.be/stations/NMBS/008015190",
"id": "BE.NMBS.008015190",
"name": "Herzogenrath",
"locationX": "6.0944",
"locationY": "50.8709",
"standardname": "Herzogenrath"
},
{
"@id": "http://irail.be/stations/NMBS/008832243",
"id": "BE.NMBS.008832243",
"name": "Heusden",
"locationX": "5.281782",
"locationY": "51.038207",
"standardname": "Heusden"
},
{
"@id": "http://irail.be/stations/NMBS/008822459",
"id": "BE.NMBS.008822459",
"name": "Hever",
"locationX": "4.537637",
"locationY": "50.997791",
"standardname": "Hever"
},
{
"@id": "http://irail.be/stations/NMBS/008833126",
"id": "BE.NMBS.008833126",
"name": "Heverlee",
"locationX": "4.6952",
"locationY": "50.86253",
"standardname": "Heverlee"
},
{
"@id": "http://irail.be/stations/NMBS/008895422",
"id": "BE.NMBS.008895422",
"name": "Hillegem",
"locationX": "3.857469",
"locationY": "50.891296",
"standardname": "Hillegem"
},
{
"@id": "http://irail.be/stations/NMBS/008824158",
"id": "BE.NMBS.008824158",
"name": "Hoboken-Polder",
"locationX": "4.347785",
"locationY": "51.182699",
"standardname": "Hoboken-Polder"
},
{
"@id": "http://irail.be/stations/NMBS/008811460",
"id": "BE.NMBS.008811460",
"name": "Hoeilaart",
"locationX": "4.467414",
"locationY": "50.760161",
"standardname": "Hoeilaart"
},
{
"@id": "http://irail.be/stations/NMBS/008822277",
"id": "BE.NMBS.008822277",
"name": "Hofstade",
"locationX": "4.498336",
"locationY": "50.988658",
"standardname": "Hofstade"
},
{
"@id": "http://irail.be/stations/NMBS/008814159",
"id": "BE.NMBS.008814159",
"name": "Holleken",
"locationX": "4.353952",
"locationY": "50.767631",
"standardname": "Holleken"
},
{
"@id": "http://irail.be/stations/NMBS/008200710",
"id": "BE.NMBS.008200710",
"name": "Hollerich",
"locationX": "6.120938",
"locationY": "49.59516",
"standardname": "Hollerich"
},
{
"@id": "http://irail.be/stations/NMBS/008842655",
"id": "BE.NMBS.008842655",
"name": "Hony",
"locationX": "5.573563",
"locationY": "50.539917",
"standardname": "Hony"
},
{
"@id": "http://irail.be/stations/NMBS/008886553",
"id": "BE.NMBS.008886553",
"name": "Houraing",
"locationX": "3.835175",
"locationY": "50.703062",
"standardname": "Houraing"
},
{
"@id": "http://irail.be/stations/NMBS/008871829",
"id": "BE.NMBS.008871829",
"name": "Hourpes",
"locationX": "4.308736",
"locationY": "50.363692",
"standardname": "Hourpes"
},
{
"@id": "http://irail.be/stations/NMBS/008863842",
"id": "BE.NMBS.008863842",
"name": "Houyet",
"locationX": "5.006074",
"locationY": "50.189868",
"standardname": "Houyet"
},
{
"@id": "http://irail.be/stations/NMBS/008821337",
"id": "BE.NMBS.008821337",
"name": "Hove",
"locationX": "4.465157",
"locationY": "51.154114",
"standardname": "Hove"
},
{
"@id": "http://irail.be/stations/NMBS/008814415",
"id": "BE.NMBS.008814415",
"name": "Huizingen",
"locationX": "4.266487",
"locationY": "50.7519",
"standardname": "Huizingen"
},
{
"@id": "http://irail.be/stations/NMBS/008843307",
"id": "BE.NMBS.008843307",
"name": "Huy",
"locationX": "5.234211",
"locationY": "50.527242",
"standardname": "Huy"
},
{
"@id": "http://irail.be/stations/NMBS/008003040",
"id": "BE.NMBS.008003040",
"name": "Idar-Oberstein",
"locationX": "7.321228",
"locationY": "49.699371",
"standardname": "Idar-Oberstein"
},
{
"@id": "http://irail.be/stations/NMBS/008895844",
"id": "BE.NMBS.008895844",
"name": "Iddergem",
"locationX": "4.06849",
"locationY": "50.876886",
"standardname": "Iddergem"
},
{
"@id": "http://irail.be/stations/NMBS/008895729",
"id": "BE.NMBS.008895729",
"name": "Idegem",
"locationX": "3.921553",
"locationY": "50.801871",
"standardname": "Idegem"
},
{
"@id": "http://irail.be/stations/NMBS/008896925",
"id": "BE.NMBS.008896925",
"name": "Ingelmunster",
"locationX": "3.255416",
"locationY": "50.914326",
"standardname": "Ingelmunster"
},
{
"@id": "http://irail.be/stations/NMBS/008896909",
"id": "BE.NMBS.008896909",
"name": "Izegem",
"locationX": "3.212088",
"locationY": "50.921149",
"standardname": "Izegem"
},
{
"@id": "http://irail.be/stations/NMBS/008863115",
"id": "BE.NMBS.008863115",
"name": "Jambes",
"locationX": "4.876144",
"locationY": "50.454843",
"standardname": "Jambes"
},
{
"@id": "http://irail.be/stations/NMBS/008863354",
"id": "BE.NMBS.008863354",
"name": "Jambes-Est",
"locationX": "4.880261",
"locationY": "50.454798",
"standardname": "Jambes-Est"
},
{
"@id": "http://irail.be/stations/NMBS/008871175",
"id": "BE.NMBS.008871175",
"name": "Jamioulx",
"locationX": "4.411294",
"locationY": "50.352896",
"standardname": "Jamioulx"
},
{
"@id": "http://irail.be/stations/NMBS/008884566",
"id": "BE.NMBS.008884566",
"name": "Jemappes",
"locationX": "3.885587",
"locationY": "50.452577",
"standardname": "Jemappes"
},
{
"@id": "http://irail.be/stations/NMBS/008843158",
"id": "BE.NMBS.008843158",
"name": "Jemeppe-sur-Meuse",
"locationX": "5.497874",
"locationY": "50.618446",
"standardname": "Jemeppe-sur-Meuse"
},
{
"@id": "http://irail.be/stations/NMBS/008874724",
"id": "BE.NMBS.008874724",
"name": "Jemeppe-sur-Sambre",
"locationX": "4.662632",
"locationY": "50.45095",
"standardname": "Jemeppe-sur-Sambre"
},
{
"@id": "http://irail.be/stations/NMBS/008812047",
"id": "BE.NMBS.008812047",
"name": "Jette",
"locationX": "4.32622",
"locationY": "50.880833",
"standardname": "Jette"
},
{
"@id": "http://irail.be/stations/NMBS/008881166",
"id": "BE.NMBS.008881166",
"name": "Jurbise",
"locationX": "3.910694",
"locationY": "50.530496",
"standardname": "Jurbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008844321",
"id": "BE.NMBS.008844321",
"name": "Juslenville",
"locationX": "5.809935",
"locationY": "50.544717",
"standardname": "Juslenville"
},
{
"@id": "http://irail.be/stations/NMBS/008821444",
"id": "BE.NMBS.008821444",
"name": "Kalmthout",
"locationX": "4.46682",
"locationY": "51.391177",
"standardname": "Kalmthout"
},
{
"@id": "http://irail.be/stations/NMBS/008822053",
"id": "BE.NMBS.008822053",
"name": "Kapelle-op-den-Bos",
"locationX": "4.359121",
"locationY": "51.010843",
"standardname": "Kapelle-op-den-Bos"
},
{
"@id": "http://irail.be/stations/NMBS/008821535",
"id": "BE.NMBS.008821535",
"name": "Kapellen",
"locationX": "4.432661",
"locationY": "51.313528",
"standardname": "Kapellen"
},
{
"@id": "http://irail.be/stations/NMBS/008200130",
"id": "BE.NMBS.008200130",
"name": "Kautebaach",
"locationX": "6.020003",
"locationY": "49.952777",
"standardname": "Kautebaach"
},
{
"@id": "http://irail.be/stations/NMBS/008821659",
"id": "BE.NMBS.008821659",
"name": "Kessel",
"locationX": "4.618459",
"locationY": "51.151057",
"standardname": "Kessel"
},
{
"@id": "http://irail.be/stations/NMBS/008832375",
"id": "BE.NMBS.008832375",
"name": "Kiewit",
"locationX": "5.350226",
"locationY": "50.954841",
"standardname": "Kiewit"
},
{
"@id": "http://irail.be/stations/NMBS/008821451",
"id": "BE.NMBS.008821451",
"name": "Kijkuit",
"locationX": "4.467315",
"locationY": "51.378664",
"standardname": "Kijkuit"
},
{
"@id": "http://irail.be/stations/NMBS/008200520",
"id": "BE.NMBS.008200520",
"name": "Klengbetten",
"locationX": "5.916385",
"locationY": "49.646389",
"standardname": "Klengbetten"
},
{
"@id": "http://irail.be/stations/NMBS/008891660",
"id": "BE.NMBS.008891660",
"name": "Knokke",
"locationX": "3.285188",
"locationY": "51.339894",
"standardname": "Knokke"
},
{
"@id": "http://irail.be/stations/NMBS/008019022",
"id": "BE.NMBS.008019022",
"name": "Koblenz Hbf (DE)",
"locationX": "7.588441",
"locationY": "50.35084",
"standardname": "Koblenz Hbf (DE)"
},
{
"@id": "http://irail.be/stations/NMBS/008892320",
"id": "BE.NMBS.008892320",
"name": "Koksijde",
"locationX": "2.65277",
"locationY": "51.079197",
"standardname": "Koksijde"
},
{
"@id": "http://irail.be/stations/NMBS/008896412",
"id": "BE.NMBS.008896412",
"name": "Komen/Comines",
"locationX": "2.999286",
"locationY": "50.772072",
"standardname": "Comines"
},
{
"@id": "http://irail.be/stations/NMBS/008821311",
"id": "BE.NMBS.008821311",
"name": "Kontich-Lint",
"locationX": "4.476358",
"locationY": "51.134023",
"standardname": "Kontich-Lint"
},
{
"@id": "http://irail.be/stations/NMBS/008892403",
"id": "BE.NMBS.008892403",
"name": "Kortemark",
"locationX": "3.043459",
"locationY": "51.025244",
"standardname": "Kortemark"
},
{
"@id": "http://irail.be/stations/NMBS/008811254",
"id": "BE.NMBS.008811254",
"name": "Kortenberg",
"locationX": "4.543301",
"locationY": "50.893067",
"standardname": "Kortenberg"
},
{
"@id": "http://irail.be/stations/NMBS/008896008",
"id": "BE.NMBS.008896008",
"name": "Kortrijk",
"locationX": "3.264549",
"locationY": "50.824506",
"standardname": "Kortrijk"
},
{
"@id": "http://irail.be/stations/NMBS/008893567",
"id": "BE.NMBS.008893567",
"name": "Kwatrecht",
"locationX": "3.829593",
"locationY": "50.99175",
"standardname": "Kwatrecht"
},
{
"@id": "http://irail.be/stations/NMBS/008015458",
"id": "BE.NMBS.008015458",
"name": "Köln Hbf",
"locationX": "6.958823",
"locationY": "50.942721",
"standardname": "Köln Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008811510",
"id": "BE.NMBS.008811510",
"name": "La Hulpe",
"locationX": "4.49706",
"locationY": "50.737958",
"standardname": "La Hulpe"
},
{
"@id": "http://irail.be/stations/NMBS/008882107",
"id": "BE.NMBS.008882107",
"name": "La Louvière-Centre",
"locationX": "4.179858",
"locationY": "50.478161",
"standardname": "La Louvière-Centre"
},
{
"@id": "http://irail.be/stations/NMBS/008882206",
"id": "BE.NMBS.008882206",
"name": "La Louvière-Sud",
"locationX": "4.190609",
"locationY": "50.464974",
"standardname": "La Louvière-Sud"
},
{
"@id": "http://irail.be/stations/NMBS/008872587",
"id": "BE.NMBS.008872587",
"name": "La Roche (Brabant)",
"locationX": "4.539157",
"locationY": "50.610338",
"standardname": "La Roche (Brabant)"
},
{
"@id": "http://irail.be/stations/NMBS/008871670",
"id": "BE.NMBS.008871670",
"name": "Labuissière",
"locationX": "4.186833",
"locationY": "50.316328",
"standardname": "Labuissière"
},
{
"@id": "http://irail.be/stations/NMBS/008200935",
"id": "BE.NMBS.008200935",
"name": "Lamadeleine",
"locationX": "5.861335",
"locationY": "49.55334",
"standardname": "Lamadeleine"
},
{
"@id": "http://irail.be/stations/NMBS/008892056",
"id": "BE.NMBS.008892056",
"name": "Landegem",
"locationX": "3.576852",
"locationY": "51.064311",
"standardname": "Landegem"
},
{
"@id": "http://irail.be/stations/NMBS/008871837",
"id": "BE.NMBS.008871837",
"name": "Landelies",
"locationX": "4.350976",
"locationY": "50.377311",
"standardname": "Landelies"
},
{
"@id": "http://irail.be/stations/NMBS/008833605",
"id": "BE.NMBS.008833605",
"name": "Landen",
"locationX": "5.07966",
"locationY": "50.747927",
"standardname": "Landen"
},
{
"@id": "http://irail.be/stations/NMBS/008400548",
"id": "BE.NMBS.008400548",
"name": "Landgraaf",
"locationX": "6.019776",
"locationY": "50.89651",
"standardname": "Landgraaf"
},
{
"@id": "http://irail.be/stations/NMBS/008774177",
"id": "BE.NMBS.008774177",
"name": "Landry",
"locationX": "6.733522",
"locationY": "45.574194",
"standardname": "Landry"
},
{
"@id": "http://irail.be/stations/NMBS/008893054",
"id": "BE.NMBS.008893054",
"name": "Landskouter",
"locationX": "3.791146",
"locationY": "50.970545",
"standardname": "Landskouter"
},
{
"@id": "http://irail.be/stations/NMBS/008833258",
"id": "BE.NMBS.008833258",
"name": "Langdorp",
"locationX": "4.863541",
"locationY": "51.002466",
"standardname": "Langdorp"
},
{
"@id": "http://irail.be/stations/NMBS/008874559",
"id": "BE.NMBS.008874559",
"name": "Le Campinaire",
"locationX": "4.542787",
"locationY": "50.42383",
"standardname": "Le Campinaire"
},
{
"@id": "http://irail.be/stations/NMBS/008812161",
"id": "BE.NMBS.008812161",
"name": "Lebbeke",
"locationX": "4.134372",
"locationY": "51.005009",
"standardname": "Lebbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008895067",
"id": "BE.NMBS.008895067",
"name": "Lede",
"locationX": "3.984981",
"locationY": "50.970895",
"standardname": "Lede"
},
{
"@id": "http://irail.be/stations/NMBS/008864816",
"id": "BE.NMBS.008864816",
"name": "Leignon",
"locationX": "5.107778",
"locationY": "50.267768",
"standardname": "Leignon"
},
{
"@id": "http://irail.be/stations/NMBS/008400394",
"id": "BE.NMBS.008400394",
"name": "Lelystad Centrum",
"locationX": "5.470484",
"locationY": "52.511736",
"standardname": "Lelystad Centrum"
},
{
"@id": "http://irail.be/stations/NMBS/008843224",
"id": "BE.NMBS.008843224",
"name": "Leman",
"locationX": "5.468309",
"locationY": "50.600396",
"standardname": "Leman"
},
{
"@id": "http://irail.be/stations/NMBS/008814332",
"id": "BE.NMBS.008814332",
"name": "Lembeek",
"locationX": "4.221577",
"locationY": "50.715107",
"standardname": "Lembeek"
},
{
"@id": "http://irail.be/stations/NMBS/008881190",
"id": "BE.NMBS.008881190",
"name": "Lens",
"locationX": "3.903224",
"locationY": "50.559342",
"standardname": "Lens"
},
{
"@id": "http://irail.be/stations/NMBS/008832003",
"id": "BE.NMBS.008832003",
"name": "Leopoldsburg",
"locationX": "5.257287",
"locationY": "51.117312",
"standardname": "Leopoldsburg"
},
{
"@id": "http://irail.be/stations/NMBS/008775544",
"id": "BE.NMBS.008775544",
"name": "Les Arcs - Draguignan",
"locationX": "6.4826446",
"locationY": "43.4555673",
"standardname": "Les Arcs - Draguignan"
},
{
"@id": "http://irail.be/stations/NMBS/008886504",
"id": "BE.NMBS.008886504",
"name": "Lessines",
"locationX": "3.836434",
"locationY": "50.712015",
"standardname": "Lessen"
},
{
"@id": "http://irail.be/stations/NMBS/008200712",
"id": "BE.NMBS.008200712",
"name": "Leudelange",
"locationX": "6.059306",
"locationY": "49.58712",
"standardname": "Leudelange"
},
{
"@id": "http://irail.be/stations/NMBS/008833001",
"id": "BE.NMBS.008833001",
"name": "Leuven",
"locationX": "4.715866",
"locationY": "50.88228",
"standardname": "Leuven"
},
{
"@id": "http://irail.be/stations/NMBS/008886348",
"id": "BE.NMBS.008886348",
"name": "Leuze",
"locationX": "3.616872",
"locationY": "50.600612",
"standardname": "Leuze"
},
{
"@id": "http://irail.be/stations/NMBS/008882339",
"id": "BE.NMBS.008882339",
"name": "Leval",
"locationX": "4.211041",
"locationY": "50.430797",
"standardname": "Leval"
},
{
"@id": "http://irail.be/stations/NMBS/008728710",
"id": "BE.NMBS.008728710",
"name": "Lezennes",
"locationX": "3.116667",
"locationY": "50.616666",
"standardname": "Lezennes"
},
{
"@id": "http://irail.be/stations/NMBS/008865003",
"id": "BE.NMBS.008865003",
"name": "Libramont",
"locationX": "5.37927",
"locationY": "49.920434",
"standardname": "Libramont"
},
{
"@id": "http://irail.be/stations/NMBS/008892205",
"id": "BE.NMBS.008892205",
"name": "Lichtervelde",
"locationX": "3.127212",
"locationY": "51.025163",
"standardname": "Lichtervelde"
},
{
"@id": "http://irail.be/stations/NMBS/008895836",
"id": "BE.NMBS.008895836",
"name": "Liedekerke",
"locationX": "4.095287",
"locationY": "50.882531",
"standardname": "Liedekerke"
},
{
"@id": "http://irail.be/stations/NMBS/008821600",
"id": "BE.NMBS.008821600",
"name": "Lier",
"locationX": "4.560614",
"locationY": "51.135758",
"standardname": "Lier"
},
{
"@id": "http://irail.be/stations/NMBS/008895570",
"id": "BE.NMBS.008895570",
"name": "Lierde",
"locationX": "3.826564",
"locationY": "50.816236",
"standardname": "Lierde"
},
{
"@id": "http://irail.be/stations/NMBS/008841673",
"id": "BE.NMBS.008841673",
"name": "Liers",
"locationX": "5.56683",
"locationY": "50.698181",
"standardname": "Liers"
},
{
"@id": "http://irail.be/stations/NMBS/008872520",
"id": "BE.NMBS.008872520",
"name": "Ligny",
"locationX": "4.566133",
"locationY": "50.511726",
"standardname": "Ligny"
},
{
"@id": "http://irail.be/stations/NMBS/008722326",
"id": "BE.NMBS.008722326",
"name": "Lille Europe",
"locationX": "3.0756612",
"locationY": "50.6391167",
"standardname": "Lille Europe"
},
{
"@id": "http://irail.be/stations/NMBS/008728600",
"id": "BE.NMBS.008728600",
"name": "Lille Flandres",
"locationX": "3.066669",
"locationY": "50.633333",
"standardname": "Lille Flandres"
},
{
"@id": "http://irail.be/stations/NMBS/008814241",
"id": "BE.NMBS.008814241",
"name": "Lillois",
"locationX": "4.365368",
"locationY": "50.645423",
"standardname": "Lillois"
},
{
"@id": "http://irail.be/stations/NMBS/008811635",
"id": "BE.NMBS.008811635",
"name": "Limal",
"locationX": "4.575302",
"locationY": "50.69214",
"standardname": "Limal"
},
{
"@id": "http://irail.be/stations/NMBS/008032572",
"id": "BE.NMBS.008032572",
"name": "Limburg Süd",
"locationX": "8.063261",
"locationY": "50.3842",
"standardname": "Limburg Süd"
},
{
"@id": "http://irail.be/stations/NMBS/008814142",
"id": "BE.NMBS.008814142",
"name": "Linkebeek",
"locationX": "4.339434",
"locationY": "50.773681",
"standardname": "Linkebeek"
},
{
"@id": "http://irail.be/stations/NMBS/008891629",
"id": "BE.NMBS.008891629",
"name": "Lissewege",
"locationX": "3.194505",
"locationY": "51.294714",
"standardname": "Lissewege"
},
{
"@id": "http://irail.be/stations/NMBS/008841558",
"id": "BE.NMBS.008841558",
"name": "Liège-Carré",
"locationX": "5.561131",
"locationY": "50.640299",
"standardname": "Liège-Carré"
},
{
"@id": "http://irail.be/stations/NMBS/008841004",
"id": "BE.NMBS.008841004",
"name": "Liège-Guillemins",
"locationX": "5.566695",
"locationY": "50.62455",
"standardname": "Liège-Guillemins"
},
{
"@id": "http://irail.be/stations/NMBS/008841525",
"id": "BE.NMBS.008841525",
"name": "Liège-Saint-Lambert",
"locationX": "5.570453",
"locationY": "50.646349",
"standardname": "Liège-Saint-Lambert"
},
{
"@id": "http://irail.be/stations/NMBS/008871712",
"id": "BE.NMBS.008871712",
"name": "Lobbes",
"locationX": "4.260958",
"locationY": "50.346469",
"standardname": "Lobbes"
},
{
"@id": "http://irail.be/stations/NMBS/008872306",
"id": "BE.NMBS.008872306",
"name": "Lodelinsart",
"locationX": "4.462946",
"locationY": "50.432451",
"standardname": "Lodelinsart"
},
{
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
{
"@id": "http://irail.be/stations/NMBS/008832565",
"id": "BE.NMBS.008832565",
"name": "Lommel",
"locationX": "5.312031",
"locationY": "51.211564",
"standardname": "Lommel"
},
{
"@id": "http://irail.be/stations/NMBS/008822111",
"id": "BE.NMBS.008822111",
"name": "Londerzeel",
"locationX": "4.299073",
"locationY": "51.009091",
"standardname": "Londerzeel"
},
{
"@id": "http://irail.be/stations/NMBS/007015400",
"id": "BE.NMBS.007015400",
"name": "London Saint Pancras International",
"locationX": "0.123808",
"locationY": "51.5304",
"standardname": "London Saint Pancras International"
},
{
"@id": "http://irail.be/stations/NMBS/007054650",
"id": "BE.NMBS.007054650",
"name": "London Waterloo",
"locationX": "-0.1132",
"locationY": "51.5031",
"standardname": "London Waterloo"
},
{
"@id": "http://irail.be/stations/NMBS/008861416",
"id": "BE.NMBS.008861416",
"name": "Lonzée",
"locationX": "4.7201",
"locationY": "50.551935",
"standardname": "Lonzée"
},
{
"@id": "http://irail.be/stations/NMBS/008714210",
"id": "BE.NMBS.008714210",
"name": "Lorraine TGV",
"locationX": "6.169722",
"locationY": "48.9475",
"standardname": "Lorraine TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008814357",
"id": "BE.NMBS.008814357",
"name": "Lot",
"locationX": "4.273696",
"locationY": "50.766364",
"standardname": "Lot"
},
{
"@id": "http://irail.be/stations/NMBS/008811676",
"id": "BE.NMBS.008811676",
"name": "Louvain-la-Neuve",
"locationX": "4.615745",
"locationY": "50.669793",
"standardname": "Louvain-la-Neuve"
},
{
"@id": "http://irail.be/stations/NMBS/008863156",
"id": "BE.NMBS.008863156",
"name": "Lustin",
"locationX": "4.877071380615234",
"locationY": "50.369000316323856",
"standardname": "Lustin"
},
{
"@id": "http://irail.be/stations/NMBS/008871308",
"id": "BE.NMBS.008871308",
"name": "Luttre",
"locationX": "4.38412",
"locationY": "50.505856",
"standardname": "Luttre"
},
{
"@id": "http://irail.be/stations/NMBS/008772319",
"id": "BE.NMBS.008772319",
"name": "Lyon Part Dieu TGV",
"locationX": "4.85",
"locationY": "45.75",
"standardname": "Lyon Part Dieu TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008772202",
"id": "BE.NMBS.008772202",
"name": "Lyon-Perrache TGV",
"locationX": "4.825301",
"locationY": "45.74836",
"standardname": "Lyon-Perrache TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008776290",
"id": "BE.NMBS.008776290",
"name": "Lyon-Saint Exupéry TGV",
"locationX": "5.075822",
"locationY": "45.720907",
"standardname": "Lyon-Saint Exupéry TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008200100",
"id": "BE.NMBS.008200100",
"name": "Lëtzebuerg",
"locationX": "6.133331",
"locationY": "49.599996",
"standardname": "Lëtzebuerg"
},
{
"@id": "http://irail.be/stations/NMBS/008400424",
"id": "BE.NMBS.008400424",
"name": "Maastricht",
"locationX": "5.705392",
"locationY": "50.85",
"standardname": "Maastricht"
},
{
"@id": "http://irail.be/stations/NMBS/008400426",
"id": "BE.NMBS.008400426",
"name": "Maastricht Randwyck",
"locationX": "5.716707",
"locationY": "50.838502",
"standardname": "Maastricht Randwyck"
},
{
"@id": "http://irail.be/stations/NMBS/008886041",
"id": "BE.NMBS.008886041",
"name": "Maffle",
"locationX": "3.800117",
"locationY": "50.614356",
"standardname": "Maffle"
},
{
"@id": "http://irail.be/stations/NMBS/008019052",
"id": "BE.NMBS.008019052",
"name": "Mainz Hbf (DE)",
"locationX": "8.2585",
"locationY": "50.0013",
"standardname": "Mainz Hbf (DE)"
},
{
"@id": "http://irail.be/stations/NMBS/008822137",
"id": "BE.NMBS.008822137",
"name": "Malderen",
"locationX": "4.22911",
"locationY": "51.014484",
"standardname": "Malderen"
},
{
"@id": "http://irail.be/stations/NMBS/008200516",
"id": "BE.NMBS.008200516",
"name": "Mamer",
"locationX": "6.02014",
"locationY": "49.625663",
"standardname": "Mamer"
},
{
"@id": "http://irail.be/stations/NMBS/008210014",
"id": "BE.NMBS.008210014",
"name": "Mamer-Lycée",
"locationX": "6.02968",
"locationY": "49.618415",
"standardname": "Mamer-Lycée"
},
{
"@id": "http://irail.be/stations/NMBS/008882701",
"id": "BE.NMBS.008882701",
"name": "Manage",
"locationX": "4.234683",
"locationY": "50.506108",
"standardname": "Manage"
},
{
"@id": "http://irail.be/stations/NMBS/008014008",
"id": "BE.NMBS.008014008",
"name": "Mannheim Hbf",
"locationX": "8.469722",
"locationY": "49.479722",
"standardname": "Mannheim Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008866175",
"id": "BE.NMBS.008866175",
"name": "Marbehan",
"locationX": "5.539755",
"locationY": "49.727337",
"standardname": "Marbehan"
},
{
"@id": "http://irail.be/stations/NMBS/008864410",
"id": "BE.NMBS.008864410",
"name": "Marche-en-Famenne",
"locationX": "5.346289",
"locationY": "50.222472",
"standardname": "Marche-en-Famenne"
},
{
"@id": "http://irail.be/stations/NMBS/008863461",
"id": "BE.NMBS.008863461",
"name": "Marche-les-Dames",
"locationX": "4.96458",
"locationY": "50.480741",
"standardname": "Marche-les-Dames"
},
{
"@id": "http://irail.be/stations/NMBS/008883220",
"id": "BE.NMBS.008883220",
"name": "Marche-lez-Écaussinnes",
"locationX": "4.177098",
"locationY": "50.546173",
"standardname": "Marche-lez-Écaussinnes"
},
{
"@id": "http://irail.be/stations/NMBS/008871852",
"id": "BE.NMBS.008871852",
"name": "Marchienne-Zone",
"locationX": "4.388767",
"locationY": "50.397465",
"standardname": "Marchienne-Zone"
},
{
"@id": "http://irail.be/stations/NMBS/008871100",
"id": "BE.NMBS.008871100",
"name": "Marchienne-au-Pont",
"locationX": "4.394223",
"locationY": "50.412171",
"standardname": "Marchienne-au-Pont"
},
{
"@id": "http://irail.be/stations/NMBS/008891132",
"id": "BE.NMBS.008891132",
"name": "Maria-Aalter",
"locationX": "3.38673",
"locationY": "51.107612",
"standardname": "Maria-Aalter"
},
{
"@id": "http://irail.be/stations/NMBS/008875002",
"id": "BE.NMBS.008875002",
"name": "Mariembourg",
"locationX": "4.525691",
"locationY": "50.09549",
"standardname": "Mariembourg"
},
{
"@id": "http://irail.be/stations/NMBS/008864345",
"id": "BE.NMBS.008864345",
"name": "Marloie",
"locationX": "5.313892",
"locationY": "50.202821",
"standardname": "Marloie"
},
{
"@id": "http://irail.be/stations/NMBS/008711184",
"id": "BE.NMBS.008711184",
"name": "Marne-la-Vallée - Chessy",
"locationX": "2.782184",
"locationY": "48.868256",
"standardname": "Marne-la-Vallée - Chessy"
},
{
"@id": "http://irail.be/stations/NMBS/008775100",
"id": "BE.NMBS.008775100",
"name": "Marseille-Saint-Charles",
"locationX": "5.380752",
"locationY": "43.303178",
"standardname": "Marseille-Saint-Charles"
},
{
"@id": "http://irail.be/stations/NMBS/008881174",
"id": "BE.NMBS.008881174",
"name": "Masnuy-Saint-Pierre",
"locationX": "3.962139",
"locationY": "50.536546",
"standardname": "Masnuy-Saint-Pierre"
},
{
"@id": "http://irail.be/stations/NMBS/008739370",
"id": "BE.NMBS.008739370",
"name": "Massy TGV",
"locationX": "2.261254",
"locationY": "48.725758",
"standardname": "Massy TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008729500",
"id": "BE.NMBS.008729500",
"name": "Maubeuge",
"locationX": "3.966566",
"locationY": "50.27289",
"standardname": "Maubeuge"
},
{
"@id": "http://irail.be/stations/NMBS/008885530",
"id": "BE.NMBS.008885530",
"name": "Maubray",
"locationX": "3.495527",
"locationY": "50.547557",
"standardname": "Maubray"
},
{
"@id": "http://irail.be/stations/NMBS/008861333",
"id": "BE.NMBS.008861333",
"name": "Mazy",
"locationX": "4.675829",
"locationY": "50.513497",
"standardname": "Mazy"
},
{
"@id": "http://irail.be/stations/NMBS/008822004",
"id": "BE.NMBS.008822004",
"name": "Mechelen",
"locationX": "4.482785",
"locationY": "51.017648",
"standardname": "Mechelen"
},
{
"@id": "http://irail.be/stations/NMBS/008822343",
"id": "BE.NMBS.008822343",
"name": "Mechelen-Nekkerspoel",
"locationX": "4.489914",
"locationY": "51.029883",
"standardname": "Mechelen-Nekkerspoel"
},
{
"@id": "http://irail.be/stations/NMBS/008829025",
"id": "BE.NMBS.008829025",
"name": "Meer-Grens",
"locationX": "4.734469757625622",
"locationY": "51.48573529673874",
"standardname": "Meer-Grens"
},
{
"@id": "http://irail.be/stations/NMBS/008400434",
"id": "BE.NMBS.008400434",
"name": "Meerssen",
"locationX": "5.750631",
"locationY": "50.8826",
"standardname": "Meerssen"
},
{
"@id": "http://irail.be/stations/NMBS/008811171",
"id": "BE.NMBS.008811171",
"name": "Meiser",
"locationX": "4.394421",
"locationY": "50.854072",
"standardname": "Meiser"
},
{
"@id": "http://irail.be/stations/NMBS/008821824",
"id": "BE.NMBS.008821824",
"name": "Melkouwen",
"locationX": "4.671532",
"locationY": "51.094938",
"standardname": "Melkouwen"
},
{
"@id": "http://irail.be/stations/NMBS/008893039",
"id": "BE.NMBS.008893039",
"name": "Melle",
"locationX": "3.797088",
"locationY": "51.002807",
"standardname": "Melle"
},
{
"@id": "http://irail.be/stations/NMBS/008890142",
"id": "BE.NMBS.008890142",
"name": "Melle PW",
"locationX": "3.77939",
"locationY": "51.01394",
"standardname": "Melle PW"
},
{
"@id": "http://irail.be/stations/NMBS/008864436",
"id": "BE.NMBS.008864436",
"name": "Melreux-Hotton",
"locationX": "5.440136",
"locationY": "50.28367",
"standardname": "Melreux-Hotton"
},
{
"@id": "http://irail.be/stations/NMBS/008894755",
"id": "BE.NMBS.008894755",
"name": "Melsele",
"locationX": "4.286766",
"locationY": "51.21071",
"standardname": "Melsele"
},
{
"@id": "http://irail.be/stations/NMBS/008896305",
"id": "BE.NMBS.008896305",
"name": "Menen",
"locationX": "3.113791",
"locationY": "50.799489",
"standardname": "Menen"
},
{
"@id": "http://irail.be/stations/NMBS/008812120",
"id": "BE.NMBS.008812120",
"name": "Merchtem",
"locationX": "4.222718",
"locationY": "50.954958",
"standardname": "Merchtem"
},
{
"@id": "http://irail.be/stations/NMBS/008893013",
"id": "BE.NMBS.008893013",
"name": "Merelbeke",
"locationX": "3.768889",
"locationY": "51.017531",
"standardname": "Merelbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008811197",
"id": "BE.NMBS.008811197",
"name": "Merode",
"locationX": "4.398934",
"locationY": "50.839284",
"standardname": "Merode"
},
{
"@id": "http://irail.be/stations/NMBS/008200110",
"id": "BE.NMBS.008200110",
"name": "Mersch",
"locationX": "6.106111",
"locationY": "49.748893",
"standardname": "Mersch"
},
{
"@id": "http://irail.be/stations/NMBS/008866662",
"id": "BE.NMBS.008866662",
"name": "Messancy",
"locationX": "5.818915",
"locationY": "49.592777",
"standardname": "Messancy"
},
{
"@id": "http://irail.be/stations/NMBS/008719203",
"id": "BE.NMBS.008719203",
"name": "Metz",
"locationX": "6.166663",
"locationY": "49.13333",
"standardname": "Metz"
},
{
"@id": "http://irail.be/stations/NMBS/008886058",
"id": "BE.NMBS.008886058",
"name": "Mevergnies-Attre",
"locationX": "3.833917",
"locationY": "50.600108",
"standardname": "Mevergnies-Attre"
},
{
"@id": "http://irail.be/stations/NMBS/008200128",
"id": "BE.NMBS.008200128",
"name": "Michelau",
"locationX": "6.09149",
"locationY": "49.89729",
"standardname": "Michelau"
},
{
"@id": "http://irail.be/stations/NMBS/008841665",
"id": "BE.NMBS.008841665",
"name": "Milmort",
"locationX": "5.60009",
"locationY": "50.692455",
"standardname": "Milmort"
},
{
"@id": "http://irail.be/stations/NMBS/008814431",
"id": "BE.NMBS.008814431",
"name": "Moensberg",
"locationX": "4.330733",
"locationY": "50.77832",
"standardname": "Moensberg"
},
{
"@id": "http://irail.be/stations/NMBS/008885704",
"id": "BE.NMBS.008885704",
"name": "Moeskroen/Mouscron",
"locationX": "3.228448",
"locationY": "50.741005",
"standardname": "Mouscron"
},
{
"@id": "http://irail.be/stations/NMBS/008832409",
"id": "BE.NMBS.008832409",
"name": "Mol",
"locationX": "5.116336",
"locationY": "51.19105",
"standardname": "Mol"
},
{
"@id": "http://irail.be/stations/NMBS/008812112",
"id": "BE.NMBS.008812112",
"name": "Mollem",
"locationX": "4.216965",
"locationY": "50.933473",
"standardname": "Mollem"
},
{
"@id": "http://irail.be/stations/NMBS/008841459",
"id": "BE.NMBS.008841459",
"name": "Momalle",
"locationX": "5.367602",
"locationY": "50.66991",
"standardname": "Momalle"
},
{
"@id": "http://irail.be/stations/NMBS/008881000",
"id": "BE.NMBS.008881000",
"name": "Mons",
"locationX": "3.942542",
"locationY": "50.453854",
"standardname": "Mons"
},
{
"@id": "http://irail.be/stations/NMBS/008861549",
"id": "BE.NMBS.008861549",
"name": "Mont-Saint-Guibert",
"locationX": "4.613884",
"locationY": "50.637611",
"standardname": "Mont-Saint-Guibert"
},
{
"@id": "http://irail.be/stations/NMBS/008777300",
"id": "BE.NMBS.008777300",
"name": "Montpellier",
"locationX": "3.880534",
"locationY": "43.604947",
"standardname": "Montpellier"
},
{
"@id": "http://irail.be/stations/NMBS/008777301",
"id": "BE.NMBS.008777301",
"name": "Montpellier-Sud-de-France",
"locationX": "3.92428293",
"locationY": "43.59518401",
"standardname": "Montpellier-Sud-de-France"
},
{
"@id": "http://irail.be/stations/NMBS/008893062",
"id": "BE.NMBS.008893062",
"name": "Moortsele",
"locationX": "3.781339",
"locationY": "50.953519",
"standardname": "Moortsele"
},
{
"@id": "http://irail.be/stations/NMBS/008882230",
"id": "BE.NMBS.008882230",
"name": "Morlanwelz",
"locationX": "4.247367",
"locationY": "50.457998",
"standardname": "Morlanwelz"
},
{
"@id": "http://irail.be/stations/NMBS/008821147",
"id": "BE.NMBS.008821147",
"name": "Mortsel",
"locationX": "4.448437",
"locationY": "51.18296",
"standardname": "Mortsel"
},
{
"@id": "http://irail.be/stations/NMBS/008821154",
"id": "BE.NMBS.008821154",
"name": "Mortsel-Deurnesteenweg",
"locationX": "4.446514",
"locationY": "51.183023",
"standardname": "Mortsel-Deurnesteenweg"
},
{
"@id": "http://irail.be/stations/NMBS/008821246",
"id": "BE.NMBS.008821246",
"name": "Mortsel-Liersesteenweg",
"locationX": "4.468843",
"locationY": "51.169027",
"standardname": "Mortsel-Liersesteenweg"
},
{
"@id": "http://irail.be/stations/NMBS/008821238",
"id": "BE.NMBS.008821238",
"name": "Mortsel-Oude God",
"locationX": "4.455737",
"locationY": "51.171256",
"standardname": "Mortsel-Oude God"
},
{
"@id": "http://irail.be/stations/NMBS/008889011",
"id": "BE.NMBS.008889011",
"name": "Mouscron-Frontiere",
"locationX": "3.196086",
"locationY": "50.721716",
"standardname": "Mouscron-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008861150",
"id": "BE.NMBS.008861150",
"name": "Moustier",
"locationX": "4.693807",
"locationY": "50.452748",
"standardname": "Moustier"
},
{
"@id": "http://irail.be/stations/NMBS/008811403",
"id": "BE.NMBS.008811403",
"name": "Mouterij",
"locationX": "4.37866",
"locationY": "50.829929",
"standardname": "Mouterij/Germoir"
},
{
"@id": "http://irail.be/stations/NMBS/008774172",
"id": "BE.NMBS.008774172",
"name": "Moûtiers-Salins-Brides-les-Bai",
"locationX": "6.531454",
"locationY": "45.486693",
"standardname": "Moûtiers-Salins-Brides-les-Bai"
},
{
"@id": "http://irail.be/stations/NMBS/008822426",
"id": "BE.NMBS.008822426",
"name": "Muizen",
"locationX": "4.513843",
"locationY": "51.008201",
"standardname": "Muizen"
},
{
"@id": "http://irail.be/stations/NMBS/008718206",
"id": "BE.NMBS.008718206",
"name": "Mulhouse",
"locationX": "7.333336",
"locationY": "47.749998",
"standardname": "Mulhouse"
},
{
"@id": "http://irail.be/stations/NMBS/008895232",
"id": "BE.NMBS.008895232",
"name": "Munkzwalm",
"locationX": "3.733238",
"locationY": "50.875673",
"standardname": "Munkzwalm"
},
{
"@id": "http://irail.be/stations/NMBS/008842648",
"id": "BE.NMBS.008842648",
"name": "Méry",
"locationX": "5.587236",
"locationY": "50.54762",
"standardname": "Méry"
},
{
"@id": "http://irail.be/stations/NMBS/008863008",
"id": "BE.NMBS.008863008",
"name": "Namur",
"locationX": "4.86222",
"locationY": "50.468794",
"standardname": "Namur"
},
{
"@id": "http://irail.be/stations/NMBS/008863453",
"id": "BE.NMBS.008863453",
"name": "Namêche",
"locationX": "4.997939",
"locationY": "50.47043",
"standardname": "Namêche"
},
{
"@id": "http://irail.be/stations/NMBS/008864964",
"id": "BE.NMBS.008864964",
"name": "Naninne",
"locationX": "4.929756",
"locationY": "50.419695",
"standardname": "Naninne"
},
{
"@id": "http://irail.be/stations/NMBS/008748100",
"id": "BE.NMBS.008748100",
"name": "Nantes",
"locationX": "-1.542356",
"locationY": "47.216148",
"standardname": "Nantes"
},
{
"@id": "http://irail.be/stations/NMBS/008778110",
"id": "BE.NMBS.008778110",
"name": "Narbonne",
"locationX": "3.00601",
"locationY": "43.190399",
"standardname": "Narbonne"
},
{
"@id": "http://irail.be/stations/NMBS/008864915",
"id": "BE.NMBS.008864915",
"name": "Natoye",
"locationX": "5.06116",
"locationY": "50.343296",
"standardname": "Natoye"
},
{
"@id": "http://irail.be/stations/NMBS/008832615",
"id": "BE.NMBS.008832615",
"name": "Neerpelt",
"locationX": "5.43717",
"locationY": "51.222369",
"standardname": "Neerpelt"
},
{
"@id": "http://irail.be/stations/NMBS/008833670",
"id": "BE.NMBS.008833670",
"name": "Neerwinden",
"locationX": "5.036323",
"locationY": "50.763964",
"standardname": "Neerwinden"
},
{
"@id": "http://irail.be/stations/NMBS/008844230",
"id": "BE.NMBS.008844230",
"name": "Nessonvaux",
"locationX": "5.741581",
"locationY": "50.572089",
"standardname": "Nessonvaux"
},
{
"@id": "http://irail.be/stations/NMBS/008866258",
"id": "BE.NMBS.008866258",
"name": "Neufchâteau",
"locationX": "5.452559",
"locationY": "49.854318",
"standardname": "Neufchâteau"
},
{
"@id": "http://irail.be/stations/NMBS/008883121",
"id": "BE.NMBS.008883121",
"name": "Neufvilles",
"locationX": "4.010672",
"locationY": "50.543602",
"standardname": "Neufvilles"
},
{
"@id": "http://irail.be/stations/NMBS/008775605",
"id": "BE.NMBS.008775605",
"name": "Nice Ville",
"locationX": "7.261928",
"locationY": "43.704605",
"standardname": "Nice Ville"
},
{
"@id": "http://irail.be/stations/NMBS/008824240",
"id": "BE.NMBS.008824240",
"name": "Niel",
"locationX": "4.338589",
"locationY": "51.111595",
"standardname": "Niel"
},
{
"@id": "http://irail.be/stations/NMBS/008894714",
"id": "BE.NMBS.008894714",
"name": "Nieuwkerken-Waas",
"locationX": "4.185907",
"locationY": "51.185612",
"standardname": "Nieuwkerken-Waas"
},
{
"@id": "http://irail.be/stations/NMBS/008821667",
"id": "BE.NMBS.008821667",
"name": "Nijlen",
"locationX": "4.666588",
"locationY": "51.15984",
"standardname": "Nijlen"
},
{
"@id": "http://irail.be/stations/NMBS/008881315",
"id": "BE.NMBS.008881315",
"name": "Nimy",
"locationX": "3.956089",
"locationY": "50.471644",
"standardname": "Nimy"
},
{
"@id": "http://irail.be/stations/NMBS/008895760",
"id": "BE.NMBS.008895760",
"name": "Ninove",
"locationX": "4.026133",
"locationY": "50.839509",
"standardname": "Ninove"
},
{
"@id": "http://irail.be/stations/NMBS/008814209",
"id": "BE.NMBS.008814209",
"name": "Nivelles",
"locationX": "4.335065",
"locationY": "50.599641",
"standardname": "Nivelles"
},
{
"@id": "http://irail.be/stations/NMBS/008821105",
"id": "BE.NMBS.008821105",
"name": "Noorderkempen (brecht)",
"locationX": "4.632204",
"locationY": "51.356838",
"standardname": "Noorderkempen"
},
{
"@id": "http://irail.be/stations/NMBS/008811247",
"id": "BE.NMBS.008811247",
"name": "Nossegem",
"locationX": "4.506112",
"locationY": "50.883314",
"standardname": "Nossegem"
},
{
"@id": "http://irail.be/stations/NMBS/008777500",
"id": "BE.NMBS.008777500",
"name": "Nîmes",
"locationX": "4.365997",
"locationY": "43.832602",
"standardname": "Nîmes"
},
{
"@id": "http://irail.be/stations/NMBS/008871332",
"id": "BE.NMBS.008871332",
"name": "Obaix-Buzet",
"locationX": "4.36357",
"locationY": "50.535206",
"standardname": "Obaix-Buzet"
},
{
"@id": "http://irail.be/stations/NMBS/008881406",
"id": "BE.NMBS.008881406",
"name": "Obourg",
"locationX": "4.007804",
"locationY": "50.469873",
"standardname": "Obourg"
},
{
"@id": "http://irail.be/stations/NMBS/008895778",
"id": "BE.NMBS.008895778",
"name": "Okegem",
"locationX": "4.054557",
"locationY": "50.857712",
"standardname": "Okegem"
},
{
"@id": "http://irail.be/stations/NMBS/008832458",
"id": "BE.NMBS.008832458",
"name": "Olen",
"locationX": "4.9025",
"locationY": "51.17403",
"standardname": "Olen"
},
{
"@id": "http://irail.be/stations/NMBS/008891116",
"id": "BE.NMBS.008891116",
"name": "Oostkamp",
"locationX": "3.257466",
"locationY": "51.154114",
"standardname": "Oostkamp"
},
{
"@id": "http://irail.be/stations/NMBS/008812146",
"id": "BE.NMBS.008812146",
"name": "Opwijk",
"locationX": "4.187319",
"locationY": "50.974779",
"standardname": "Opwijk"
},
{
"@id": "http://irail.be/stations/NMBS/008891702",
"id": "BE.NMBS.008891702",
"name": "Ostend",
"locationX": "2.925809",
"locationY": "51.228212",
"standardname": "Oostende"
},
{
"@id": "http://irail.be/stations/NMBS/008811601",
"id": "BE.NMBS.008811601",
"name": "Ottignies",
"locationX": "4.56936",
"locationY": "50.673667",
"standardname": "Ottignies"
},
{
"@id": "http://irail.be/stations/NMBS/008833134",
"id": "BE.NMBS.008833134",
"name": "Oud-Heverlee",
"locationX": "4.653311",
"locationY": "50.835931",
"standardname": "Oud-Heverlee"
},
{
"@id": "http://irail.be/stations/NMBS/008893518",
"id": "BE.NMBS.008893518",
"name": "Oudegem",
"locationX": "4.064472",
"locationY": "51.01523",
"standardname": "Oudegem"
},
{
"@id": "http://irail.be/stations/NMBS/008892601",
"id": "BE.NMBS.008892601",
"name": "Oudenaarde",
"locationX": "3.600386",
"locationY": "50.850116",
"standardname": "Oudenaarde"
},
{
"@id": "http://irail.be/stations/NMBS/008843174",
"id": "BE.NMBS.008843174",
"name": "Ougrée",
"locationX": "5.536972",
"locationY": "50.605396",
"standardname": "Ougrée"
},
{
"@id": "http://irail.be/stations/NMBS/008832573",
"id": "BE.NMBS.008832573",
"name": "Overpelt",
"locationX": "5.422751",
"locationY": "51.215618",
"standardname": "Overpelt"
},
{
"@id": "http://irail.be/stations/NMBS/008865540",
"id": "BE.NMBS.008865540",
"name": "Paliseul",
"locationX": "5.118349",
"locationY": "49.895408",
"standardname": "Paliseul"
},
{
"@id": "http://irail.be/stations/NMBS/008886561",
"id": "BE.NMBS.008886561",
"name": "Papignies",
"locationX": "3.823408",
"locationY": "50.686585",
"standardname": "Papegem"
},
{
"@id": "http://irail.be/stations/NMBS/008727100",
"id": "BE.NMBS.008727100",
"name": "Paris Nord",
"locationX": "2.354577",
"locationY": "48.88011",
"standardname": "Paris Nord"
},
{
"@id": "http://irail.be/stations/NMBS/008844206",
"id": "BE.NMBS.008844206",
"name": "Pepinster",
"locationX": "5.80615",
"locationY": "50.568179",
"standardname": "Pepinster"
},
{
"@id": "http://irail.be/stations/NMBS/008844313",
"id": "BE.NMBS.008844313",
"name": "Pepinster-Cité",
"locationX": "5.804397",
"locationY": "50.563405",
"standardname": "Pepinster-Cité"
},
{
"@id": "http://irail.be/stations/NMBS/008778400",
"id": "BE.NMBS.008778400",
"name": "Perpignan",
"locationX": "2.879397",
"locationY": "42.695938",
"standardname": "Perpignan"
},
{
"@id": "http://irail.be/stations/NMBS/008200930",
"id": "BE.NMBS.008200930",
"name": "Petange",
"locationX": "5.878681",
"locationY": "49.55425",
"standardname": "Petange"
},
{
"@id": "http://irail.be/stations/NMBS/008200102",
"id": "BE.NMBS.008200102",
"name": "Pfaffenthal-Kirchberg",
"locationX": "6.132853",
"locationY": "49.619126",
"standardname": "Pfaffenthal-Kirchberg"
},
{
"@id": "http://irail.be/stations/NMBS/008873122",
"id": "BE.NMBS.008873122",
"name": "Philippeville",
"locationX": "4.535956",
"locationY": "50.191639",
"standardname": "Philippeville"
},
{
"@id": "http://irail.be/stations/NMBS/008871415",
"id": "BE.NMBS.008871415",
"name": "Piéton",
"locationX": "4.288438",
"locationY": "50.434959",
"standardname": "Piéton"
},
{
"@id": "http://irail.be/stations/NMBS/008865227",
"id": "BE.NMBS.008865227",
"name": "Poix-Saint-Hubert",
"locationX": "5.292641",
"locationY": "50.019504",
"standardname": "Poix-Saint-Hubert"
},
{
"@id": "http://irail.be/stations/NMBS/008728683",
"id": "BE.NMBS.008728683",
"name": "Pont de Bois",
"locationX": "3.1275",
"locationY": "50.624164",
"standardname": "Pont de Bois"
},
{
"@id": "http://irail.be/stations/NMBS/008843141",
"id": "BE.NMBS.008843141",
"name": "Pont-de-Seraing",
"locationX": "5.510162",
"locationY": "50.619651",
"standardname": "Pont-de-Seraing"
},
{
"@id": "http://irail.be/stations/NMBS/008871365",
"id": "BE.NMBS.008871365",
"name": "Pont-à-Celles",
"locationX": "4.355291",
"locationY": "50.513812",
"standardname": "Pont-à-Celles"
},
{
"@id": "http://irail.be/stations/NMBS/008896735",
"id": "BE.NMBS.008896735",
"name": "Poperinge",
"locationX": "2.736343",
"locationY": "50.854449",
"standardname": "Poperinge"
},
{
"@id": "http://irail.be/stations/NMBS/008842689",
"id": "BE.NMBS.008842689",
"name": "Poulseur",
"locationX": "5.578858",
"locationY": "50.509209",
"standardname": "Poulseur"
},
{
"@id": "http://irail.be/stations/NMBS/005457076",
"id": "BE.NMBS.005457076",
"name": "Prague Central Station",
"locationX": "14.436037",
"locationY": "50.083058",
"standardname": "Praha Hlavní Nádraží"
},
{
"@id": "http://irail.be/stations/NMBS/008811544",
"id": "BE.NMBS.008811544",
"name": "Profondsart",
"locationX": "4.545435",
"locationY": "50.699653",
"standardname": "Profondsart"
},
{
"@id": "http://irail.be/stations/NMBS/008873312",
"id": "BE.NMBS.008873312",
"name": "Pry",
"locationX": "4.428805",
"locationY": "50.269278",
"standardname": "Pry"
},
{
"@id": "http://irail.be/stations/NMBS/008822715",
"id": "BE.NMBS.008822715",
"name": "Puurs",
"locationX": "4.282703",
"locationY": "51.07722",
"standardname": "Puurs"
},
{
"@id": "http://irail.be/stations/NMBS/008811775",
"id": "BE.NMBS.008811775",
"name": "Pécrot",
"locationX": "4.651486",
"locationY": "50.778517",
"standardname": "Pécrot"
},
{
"@id": "http://irail.be/stations/NMBS/008884855",
"id": "BE.NMBS.008884855",
"name": "Péruwelz",
"locationX": "3.592772",
"locationY": "50.513704",
"standardname": "Péruwelz"
},
{
"@id": "http://irail.be/stations/NMBS/008884541",
"id": "BE.NMBS.008884541",
"name": "Quaregnon",
"locationX": "3.856543",
"locationY": "50.449827",
"standardname": "Quaregnon"
},
{
"@id": "http://irail.be/stations/NMBS/008881505",
"id": "BE.NMBS.008881505",
"name": "Quevy",
"locationX": "3.909489",
"locationY": "50.341534",
"standardname": "Quevy"
},
{
"@id": "http://irail.be/stations/NMBS/008889003",
"id": "BE.NMBS.008889003",
"name": "Quevy-frontiere",
"locationX": "3.908753",
"locationY": "50.32771",
"standardname": "Quevy-frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008884335",
"id": "BE.NMBS.008884335",
"name": "Quievrain",
"locationX": "3.68608",
"locationY": "50.410103",
"standardname": "Quievrain"
},
{
"@id": "http://irail.be/stations/NMBS/008886587",
"id": "BE.NMBS.008886587",
"name": "Rebaix",
"locationX": "3.793627",
"locationY": "50.661235",
"standardname": "Rebaix"
},
{
"@id": "http://irail.be/stations/NMBS/008841442",
"id": "BE.NMBS.008841442",
"name": "Remicourt",
"locationX": "5.321407",
"locationY": "50.678611",
"standardname": "Remicourt"
},
{
"@id": "http://irail.be/stations/NMBS/008747100",
"id": "BE.NMBS.008747100",
"name": "Rennes",
"locationX": "-1.672744",
"locationY": "48.103517",
"standardname": "Rennes"
},
{
"@id": "http://irail.be/stations/NMBS/008861440",
"id": "BE.NMBS.008861440",
"name": "Rhisnes",
"locationX": "4.801866",
"locationY": "50.499348",
"standardname": "Rhisnes"
},
{
"@id": "http://irail.be/stations/NMBS/008842705",
"id": "BE.NMBS.008842705",
"name": "Rivage",
"locationX": "5.587631",
"locationY": "50.483285",
"standardname": "Rivage"
},
{
"@id": "http://irail.be/stations/NMBS/008811536",
"id": "BE.NMBS.008811536",
"name": "Rixensart",
"locationX": "4.532855",
"locationY": "50.711413",
"standardname": "Rixensart"
},
{
"@id": "http://irail.be/stations/NMBS/008864006",
"id": "BE.NMBS.008864006",
"name": "Rochefort-Jemelle",
"locationX": "5.266698",
"locationY": "50.160401",
"standardname": "Rochefort-Jemelle"
},
{
"@id": "http://irail.be/stations/NMBS/008200940",
"id": "BE.NMBS.008200940",
"name": "Rodange",
"locationX": "5.845028",
"locationY": "49.551283",
"standardname": "Rodange"
},
{
"@id": "http://irail.be/stations/NMBS/008896800",
"id": "BE.NMBS.008896800",
"name": "Roeselare",
"locationX": "3.130412",
"locationY": "50.949025",
"standardname": "Roeselare"
},
{
"@id": "http://irail.be/stations/NMBS/008861119",
"id": "BE.NMBS.008861119",
"name": "Ronet",
"locationX": "4.82842",
"locationY": "50.457737",
"standardname": "Ronet"
},
{
"@id": "http://irail.be/stations/NMBS/008892908",
"id": "BE.NMBS.008892908",
"name": "Ronse/Renaix",
"locationX": "3.602552",
"locationY": "50.742506",
"standardname": "Ronse"
},
{
"@id": "http://irail.be/stations/NMBS/008400526",
"id": "BE.NMBS.008400526",
"name": "Roosendaal",
"locationX": "4.458692",
"locationY": "51.540834",
"standardname": "Roosendaal"
},
{
"@id": "http://irail.be/stations/NMBS/008400530",
"id": "BE.NMBS.008400530",
"name": "Rotterdam CS",
"locationX": "4.469313",
"locationY": "51.92485",
"standardname": "Rotterdam CS"
},
{
"@id": "http://irail.be/stations/NMBS/008728673",
"id": "BE.NMBS.008728673",
"name": "Roubaix",
"locationX": "3.166666",
"locationY": "50.699997",
"standardname": "Roubaix"
},
{
"@id": "http://irail.be/stations/NMBS/008871217",
"id": "BE.NMBS.008871217",
"name": "Roux",
"locationX": "4.393199",
"locationY": "50.443112",
"standardname": "Roux"
},
{
"@id": "http://irail.be/stations/NMBS/008814365",
"id": "BE.NMBS.008814365",
"name": "Ruisbroek",
"locationX": "4.295333",
"locationY": "50.79183",
"standardname": "Ruisbroek"
},
{
"@id": "http://irail.be/stations/NMBS/008822848",
"id": "BE.NMBS.008822848",
"name": "Ruisbroek-Sauvegarde",
"locationX": "4.324998",
"locationY": "51.081022",
"standardname": "Ruisbroek-Sauvegarde"
},
{
"@id": "http://irail.be/stations/NMBS/008861432",
"id": "BE.NMBS.008861432",
"name": "Saint-Denis-Bovesse",
"locationX": "4.767788",
"locationY": "50.5213",
"standardname": "Saint-Denis-Bovesse"
},
{
"@id": "http://irail.be/stations/NMBS/008884004",
"id": "BE.NMBS.008884004",
"name": "Saint-Ghislain",
"locationX": "3.820253",
"locationY": "50.44286",
"standardname": "Saint-Ghislain"
},
{
"@id": "http://irail.be/stations/NMBS/008718213",
"id": "BE.NMBS.008718213",
"name": "Saint-Louis-Haut-Rhin",
"locationX": "7.555316",
"locationY": "47.5907",
"standardname": "Saint-Louis-Haut-Rhin"
},
{
"@id": "http://irail.be/stations/NMBS/008775752",
"id": "BE.NMBS.008775752",
"name": "Saint-Raphaël-Valescure",
"locationX": "6.768825",
"locationY": "43.423456",
"standardname": "Saint-Raphaël-Valescure"
},
{
"@id": "http://irail.be/stations/NMBS/008864956",
"id": "BE.NMBS.008864956",
"name": "Sart-Bernard",
"locationX": "4.949739",
"locationY": "50.406373",
"standardname": "Sart-Bernard"
},
{
"@id": "http://irail.be/stations/NMBS/008721222",
"id": "BE.NMBS.008721222",
"name": "Saverne",
"locationX": "7.362255",
"locationY": "48.744798",
"standardname": "Saverne"
},
{
"@id": "http://irail.be/stations/NMBS/008811007",
"id": "BE.NMBS.008811007",
"name": "Schaarbeek/Schaerbeek",
"locationX": "4.378636",
"locationY": "50.878513",
"standardname": "Schaarbeek/Schaerbeek"
},
{
"@id": "http://irail.be/stations/NMBS/008893070",
"id": "BE.NMBS.008893070",
"name": "Scheldewindeke",
"locationX": "3.777842",
"locationY": "50.937069",
"standardname": "Scheldewindeke"
},
{
"@id": "http://irail.be/stations/NMBS/008824232",
"id": "BE.NMBS.008824232",
"name": "Schelle",
"locationX": "4.340261",
"locationY": "51.12551",
"standardname": "Schelle"
},
{
"@id": "http://irail.be/stations/NMBS/008893542",
"id": "BE.NMBS.008893542",
"name": "Schellebelle",
"locationX": "3.921373",
"locationY": "51.003149",
"standardname": "Schellebelle"
},
{
"@id": "http://irail.be/stations/NMBS/008895711",
"id": "BE.NMBS.008895711",
"name": "Schendelbeke",
"locationX": "3.899286",
"locationY": "50.797844",
"standardname": "Schendelbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008400561",
"id": "BE.NMBS.008400561",
"name": "Schiphol",
"locationX": "4.75",
"locationY": "52.3",
"standardname": "Schiphol"
},
{
"@id": "http://irail.be/stations/NMBS/008893526",
"id": "BE.NMBS.008893526",
"name": "Schoonaarde",
"locationX": "4.011094",
"locationY": "51.003149",
"standardname": "Schoonaarde"
},
{
"@id": "http://irail.be/stations/NMBS/008200716",
"id": "BE.NMBS.008200716",
"name": "Schouweiler",
"locationX": "5.960076",
"locationY": "49.57364",
"standardname": "Schouweiler"
},
{
"@id": "http://irail.be/stations/NMBS/008831088",
"id": "BE.NMBS.008831088",
"name": "Schulen",
"locationX": "5.187405",
"locationY": "50.963758",
"standardname": "Schulen"
},
{
"@id": "http://irail.be/stations/NMBS/008863446",
"id": "BE.NMBS.008863446",
"name": "Sclaigneaux",
"locationX": "5.026363",
"locationY": "50.492247",
"standardname": "Sclaigneaux"
},
{
"@id": "http://irail.be/stations/NMBS/008843133",
"id": "BE.NMBS.008843133",
"name": "Sclessin",
"locationX": "5.558911",
"locationY": "50.609844",
"standardname": "Sclessin"
},
{
"@id": "http://irail.be/stations/NMBS/008721405",
"id": "BE.NMBS.008721405",
"name": "Selestat",
"locationX": "7.449999",
"locationY": "48.26667",
"standardname": "Selestat"
},
{
"@id": "http://irail.be/stations/NMBS/008843067",
"id": "BE.NMBS.008843067",
"name": "Seraing",
"locationX": "5.513777",
"locationY": "50.6089",
"standardname": "Seraing"
},
{
"@id": "http://irail.be/stations/NMBS/008893583",
"id": "BE.NMBS.008893583",
"name": "Serskamp",
"locationX": "3.959361",
"locationY": "50.984397",
"standardname": "Serskamp"
},
{
"@id": "http://irail.be/stations/NMBS/008015588",
"id": "BE.NMBS.008015588",
"name": "Siegburg",
"locationX": "7.203029",
"locationY": "50.793916",
"standardname": "Siegburg"
},
{
"@id": "http://irail.be/stations/NMBS/008883436",
"id": "BE.NMBS.008883436",
"name": "Silly",
"locationX": "3.935863",
"locationY": "50.662386",
"standardname": "Silly"
},
{
"@id": "http://irail.be/stations/NMBS/008812013",
"id": "BE.NMBS.008812013",
"name": "Simonis",
"locationX": "4.32898",
"locationY": "50.863645",
"standardname": "Simonis"
},
{
"@id": "http://irail.be/stations/NMBS/008894425",
"id": "BE.NMBS.008894425",
"name": "Sinaai",
"locationX": "4.06894",
"locationY": "51.143398",
"standardname": "Sinaai"
},
{
"@id": "http://irail.be/stations/NMBS/008812211",
"id": "BE.NMBS.008812211",
"name": "Sint-Agatha-Berchem/Berchem-Sainte-Agathe",
"locationX": "4.289895",
"locationY": "50.872625",
"standardname": "Sint-Agatha-Berchem/Berchem-Sainte-Agathe"
},
{
"@id": "http://irail.be/stations/NMBS/008892692",
"id": "BE.NMBS.008892692",
"name": "Sint-Denijs-Boekel",
"locationX": "3.698395",
"locationY": "50.874297",
"standardname": "Sint-Denijs-Boekel"
},
{
"@id": "http://irail.be/stations/NMBS/008893443",
"id": "BE.NMBS.008893443",
"name": "Sint-Gillis-Dendermonde",
"locationX": "4.117832",
"locationY": "51.021693",
"standardname": "Sint-Gillis-Dendermonde"
},
{
"@id": "http://irail.be/stations/NMBS/008814449",
"id": "BE.NMBS.008814449",
"name": "Sint-Job/Saint-Job",
"locationX": "4.362761",
"locationY": "50.79441",
"standardname": "Sint-Job"
},
{
"@id": "http://irail.be/stations/NMBS/008833159",
"id": "BE.NMBS.008833159",
"name": "Sint-Joris-Weert",
"locationX": "4.651728",
"locationY": "50.800631",
"standardname": "Sint-Joris-Weert"
},
{
"@id": "http://irail.be/stations/NMBS/008822228",
"id": "BE.NMBS.008822228",
"name": "Sint-Katelijne-Waver",
"locationX": "4.496116",
"locationY": "51.069975",
"standardname": "Sint-Katelijne-Waver"
},
{
"@id": "http://irail.be/stations/NMBS/008821543",
"id": "BE.NMBS.008821543",
"name": "Sint-Mariaburg",
"locationX": "4.4349",
"locationY": "51.291658",
"standardname": "Sint-Mariaburg"
},
{
"@id": "http://irail.be/stations/NMBS/008812245",
"id": "BE.NMBS.008812245",
"name": "Sint-Martens-Bodegem",
"locationX": "4.205081",
"locationY": "50.86716",
"standardname": "Sint-Martens-Bodegem"
},
{
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
{
"@id": "http://irail.be/stations/NMBS/008831807",
"id": "BE.NMBS.008831807",
"name": "Sint-Truiden",
"locationX": "5.176654",
"locationY": "50.81762",
"standardname": "Sint-Truiden"
},
{
"@id": "http://irail.be/stations/NMBS/008893260",
"id": "BE.NMBS.008893260",
"name": "Sleidinge",
"locationX": "3.667526",
"locationY": "51.126607",
"standardname": "Sleidinge"
},
{
"@id": "http://irail.be/stations/NMBS/008883113",
"id": "BE.NMBS.008883113",
"name": "Soignies",
"locationX": "4.067519",
"locationY": "50.572763",
"standardname": "Soignies"
},
{
"@id": "http://irail.be/stations/NMBS/008871662",
"id": "BE.NMBS.008871662",
"name": "Solre-sur-Sambre",
"locationX": "4.158427",
"locationY": "50.312642",
"standardname": "Solre-sur-Sambre"
},
{
"@id": "http://irail.be/stations/NMBS/008844404",
"id": "BE.NMBS.008844404",
"name": "Spa",
"locationX": "5.855096",
"locationY": "50.490305",
"standardname": "Spa"
},
{
"@id": "http://irail.be/stations/NMBS/008844420",
"id": "BE.NMBS.008844420",
"name": "Spa-Géronstère",
"locationX": "5.866207",
"locationY": "50.489307",
"standardname": "Spa-Géronstère"
},
{
"@id": "http://irail.be/stations/NMBS/008814167",
"id": "BE.NMBS.008814167",
"name": "St.-Genesius-Rode/Rhode-St.-Genese",
"locationX": "4.361997",
"locationY": "50.74781",
"standardname": "Sint-Genesius-Rode"
},
{
"@id": "http://irail.be/stations/NMBS/008843406",
"id": "BE.NMBS.008843406",
"name": "Statte",
"locationX": "5.219676",
"locationY": "50.528276",
"standardname": "Statte"
},
{
"@id": "http://irail.be/stations/NMBS/008869054",
"id": "BE.NMBS.008869054",
"name": "Sterpenich-Frontiere",
"locationX": "5.90415",
"locationY": "49.64396",
"standardname": "Sterpenich-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008862018",
"id": "BE.NMBS.008862018",
"name": "Stockem",
"locationX": "5.769115",
"locationY": "49.690939",
"standardname": "Stockem"
},
{
"@id": "http://irail.be/stations/NMBS/008721202",
"id": "BE.NMBS.008721202",
"name": "Strasbourg",
"locationX": "7.733905",
"locationY": "48.585437",
"standardname": "Strasbourg"
},
{
"@id": "http://irail.be/stations/NMBS/008842853",
"id": "BE.NMBS.008842853",
"name": "Sy",
"locationX": "5.523565",
"locationY": "50.403254",
"standardname": "Sy"
},
{
"@id": "http://irail.be/stations/NMBS/008777320",
"id": "BE.NMBS.008777320",
"name": "Sète",
"locationX": "3.696535",
"locationY": "43.41281",
"standardname": "Sète"
},
{
"@id": "http://irail.be/stations/NMBS/008874609",
"id": "BE.NMBS.008874609",
"name": "Tamines",
"locationX": "4.608823",
"locationY": "50.432235",
"standardname": "Tamines"
},
{
"@id": "http://irail.be/stations/NMBS/008894672",
"id": "BE.NMBS.008894672",
"name": "Temse",
"locationX": "4.221352",
"locationY": "51.126085",
"standardname": "Temse"
},
{
"@id": "http://irail.be/stations/NMBS/008895448",
"id": "BE.NMBS.008895448",
"name": "Terhagen",
"locationX": "3.896653",
"locationY": "50.901643",
"standardname": "Terhagen"
},
{
"@id": "http://irail.be/stations/NMBS/008812252",
"id": "BE.NMBS.008812252",
"name": "Ternat",
"locationX": "4.16534",
"locationY": "50.874522",
"standardname": "Ternat"
},
{
"@id": "http://irail.be/stations/NMBS/008833266",
"id": "BE.NMBS.008833266",
"name": "Testelt",
"locationX": "4.945829",
"locationY": "51.009864",
"standardname": "Testelt"
},
{
"@id": "http://irail.be/stations/NMBS/008844339",
"id": "BE.NMBS.008844339",
"name": "Theux",
"locationX": "5.815031",
"locationY": "50.536159",
"standardname": "Theux"
},
{
"@id": "http://irail.be/stations/NMBS/008881455",
"id": "BE.NMBS.008881455",
"name": "Thieu",
"locationX": "4.098523",
"locationY": "50.46954",
"standardname": "Thieu"
},
{
"@id": "http://irail.be/stations/NMBS/008719100",
"id": "BE.NMBS.008719100",
"name": "Thionville",
"locationX": "6.166663",
"locationY": "49.366663",
"standardname": "Thionville"
},
{
"@id": "http://irail.be/stations/NMBS/008871811",
"id": "BE.NMBS.008871811",
"name": "Thuin",
"locationX": "4.288906",
"locationY": "50.342738",
"standardname": "Thuin"
},
{
"@id": "http://irail.be/stations/NMBS/008884350",
"id": "BE.NMBS.008884350",
"name": "Thulin",
"locationX": "3.744708",
"locationY": "50.423335",
"standardname": "Thulin"
},
{
"@id": "http://irail.be/stations/NMBS/008815016",
"id": "BE.NMBS.008815016",
"name": "Thurn en Taxis",
"locationX": "4.341090917587279",
"locationY": "50.87175167644673",
"standardname": "Thurn en Taxis/Tour et Taxis"
},
{
"@id": "http://irail.be/stations/NMBS/008821964",
"id": "BE.NMBS.008821964",
"name": "Tielen",
"locationX": "4.893089",
"locationY": "51.241021",
"standardname": "Tielen"
},
{
"@id": "http://irail.be/stations/NMBS/008892254",
"id": "BE.NMBS.008892254",
"name": "Tielt",
"locationX": "3.330341",
"locationY": "50.990842",
"standardname": "Tielt"
},
{
"@id": "http://irail.be/stations/NMBS/008833308",
"id": "BE.NMBS.008833308",
"name": "Tienen",
"locationX": "4.92581",
"locationY": "50.80802",
"standardname": "Tienen"
},
{
"@id": "http://irail.be/stations/NMBS/008842630",
"id": "BE.NMBS.008842630",
"name": "Tilff",
"locationX": "5.583937",
"locationY": "50.570624",
"standardname": "Tilff"
},
{
"@id": "http://irail.be/stations/NMBS/008872553",
"id": "BE.NMBS.008872553",
"name": "Tilly",
"locationX": "4.552676",
"locationY": "50.558084",
"standardname": "Tilly"
},
{
"@id": "http://irail.be/stations/NMBS/008895638",
"id": "BE.NMBS.008895638",
"name": "Tollembeek",
"locationX": "3.992828",
"locationY": "50.735522",
"standardname": "Tollembeek"
},
{
"@id": "http://irail.be/stations/NMBS/008831310",
"id": "BE.NMBS.008831310",
"name": "Tongeren",
"locationX": "5.47328",
"locationY": "50.784405",
"standardname": "Tongeren"
},
{
"@id": "http://irail.be/stations/NMBS/008891314",
"id": "BE.NMBS.008891314",
"name": "Torhout",
"locationX": "3.105871",
"locationY": "51.064707",
"standardname": "Torhout"
},
{
"@id": "http://irail.be/stations/NMBS/008775500",
"id": "BE.NMBS.008775500",
"name": "Toulon",
"locationX": "5.9326648",
"locationY": "43.1274781",
"standardname": "Toulon"
},
{
"@id": "http://irail.be/stations/NMBS/008728654",
"id": "BE.NMBS.008728654",
"name": "Tourcoing",
"locationX": "3.15",
"locationY": "50.716667",
"standardname": "Tourcoing"
},
{
"@id": "http://irail.be/stations/NMBS/008885001",
"id": "BE.NMBS.008885001",
"name": "Tournai",
"locationX": "3.396942",
"locationY": "50.613134",
"standardname": "Tournai"
},
{
"@id": "http://irail.be/stations/NMBS/008845203",
"id": "BE.NMBS.008845203",
"name": "Trois-Ponts",
"locationX": "5.873578",
"locationY": "50.368214",
"standardname": "Trois-Ponts"
},
{
"@id": "http://irail.be/stations/NMBS/008200136",
"id": "BE.NMBS.008200136",
"name": "Troisvierges",
"locationX": "6.000281",
"locationY": "50.121109",
"standardname": "Troisvierges"
},
{
"@id": "http://irail.be/stations/NMBS/008844271",
"id": "BE.NMBS.008844271",
"name": "Trooz",
"locationX": "5.688346",
"locationY": "50.573213",
"standardname": "Trooz"
},
{
"@id": "http://irail.be/stations/NMBS/008883808",
"id": "BE.NMBS.008883808",
"name": "Tubize",
"locationX": "4.205729",
"locationY": "50.691708",
"standardname": "Tubize"
},
{
"@id": "http://irail.be/stations/NMBS/008821907",
"id": "BE.NMBS.008821907",
"name": "Turnhout",
"locationX": "4.937415",
"locationY": "51.322032",
"standardname": "Turnhout"
},
{
"@id": "http://irail.be/stations/NMBS/008814134",
"id": "BE.NMBS.008814134",
"name": "Ukkel-Kalevoet/Uccle-Calevoet",
"locationX": "4.332207",
"locationY": "50.791749",
"standardname": "Ukkel-Kalevoet/Uccle-Calevoet"
},
{
"@id": "http://irail.be/stations/NMBS/008814126",
"id": "BE.NMBS.008814126",
"name": "Ukkel-Stalle/Uccle-Stalle",
"locationX": "4.323901",
"locationY": "50.802411",
"standardname": "Ukkel-Stalle/Uccle-Stalle"
},
{
"@id": "http://irail.be/stations/NMBS/008400621",
"id": "BE.NMBS.008400621",
"name": "Utrecht Centraal",
"locationX": "5.109722",
"locationY": "52.089167",
"standardname": "Utrecht Centraal"
},
{
"@id": "http://irail.be/stations/NMBS/008776302",
"id": "BE.NMBS.008776302",
"name": "Valence TGV",
"locationX": "4.9",
"locationY": "44.93333",
"standardname": "Valence TGV"
},
{
"@id": "http://irail.be/stations/NMBS/008400632",
"id": "BE.NMBS.008400632",
"name": "Valkenburg",
"locationX": "5.832888",
"locationY": "50.86928",
"standardname": "Valkenburg"
},
{
"@id": "http://irail.be/stations/NMBS/008811270",
"id": "BE.NMBS.008811270",
"name": "Veltem",
"locationX": "4.633516",
"locationY": "50.900519",
"standardname": "Veltem"
},
{
"@id": "http://irail.be/stations/NMBS/008302593",
"id": "BE.NMBS.008302593",
"name": "Venezia Santa Lucia",
"locationX": "12.321039",
"locationY": "45.440975",
"standardname": "Venezia Santa Lucia"
},
{
"@id": "http://irail.be/stations/NMBS/008833050",
"id": "BE.NMBS.008833050",
"name": "Vertrijk",
"locationX": "4.835522",
"locationY": "50.836282",
"standardname": "Vertrijk"
},
{
"@id": "http://irail.be/stations/NMBS/008844008",
"id": "BE.NMBS.008844008",
"name": "Verviers-Central",
"locationX": "5.854917",
"locationY": "50.588135",
"standardname": "Verviers-Central"
},
{
"@id": "http://irail.be/stations/NMBS/008844057",
"id": "BE.NMBS.008844057",
"name": "Verviers-Palais",
"locationX": "5.865335",
"locationY": "50.590921",
"standardname": "Verviers-Palais"
},
{
"@id": "http://irail.be/stations/NMBS/008892304",
"id": "BE.NMBS.008892304",
"name": "Veurne",
"locationX": "2.66994",
"locationY": "51.073867",
"standardname": "Veurne"
},
{
"@id": "http://irail.be/stations/NMBS/008895612",
"id": "BE.NMBS.008895612",
"name": "Viane-Moerbeke",
"locationX": "3.917337",
"locationY": "50.751981",
"standardname": "Viane-Moerbeke"
},
{
"@id": "http://irail.be/stations/NMBS/008896230",
"id": "BE.NMBS.008896230",
"name": "Vichte",
"locationX": "3.39163",
"locationY": "50.833657",
"standardname": "Vichte"
},
{
"@id": "http://irail.be/stations/NMBS/008845146",
"id": "BE.NMBS.008845146",
"name": "Vielsalm",
"locationX": "5.909211",
"locationY": "50.278933",
"standardname": "Vielsalm"
},
{
"@id": "http://irail.be/stations/NMBS/008101003",
"id": "BE.NMBS.008101003",
"name": "Vienna Main Station",
"locationX": "16.375864",
"locationY": "48.184923",
"standardname": "Wien Hbf"
},
{
"@id": "http://irail.be/stations/NMBS/008895489",
"id": "BE.NMBS.008895489",
"name": "Vijfhuizen",
"locationX": "3.98125",
"locationY": "50.943254",
"standardname": "Vijfhuizen"
},
{
"@id": "http://irail.be/stations/NMBS/008884632",
"id": "BE.NMBS.008884632",
"name": "Ville-Pommerœul",
"locationX": "3.724248",
"locationY": "50.464542",
"standardname": "Ville-Pommerœul"
},
{
"@id": "http://irail.be/stations/NMBS/008872579",
"id": "BE.NMBS.008872579",
"name": "Villers-la-Ville",
"locationX": "4.533349",
"locationY": "50.578103",
"standardname": "Villers-la-Ville"
},
{
"@id": "http://irail.be/stations/NMBS/008811189",
"id": "BE.NMBS.008811189",
"name": "Vilvoorde",
"locationX": "4.432823",
"locationY": "50.924583",
"standardname": "Vilvoorde"
},
{
"@id": "http://irail.be/stations/NMBS/008866407",
"id": "BE.NMBS.008866407",
"name": "Virton",
"locationX": "5.519125",
"locationY": "49.560821",
"standardname": "Virton"
},
{
"@id": "http://irail.be/stations/NMBS/008849064",
"id": "BE.NMBS.008849064",
"name": "Vise-Frontiere",
"locationX": "5.702903",
"locationY": "50.758413",
"standardname": "Vise-Frontiere"
},
{
"@id": "http://irail.be/stations/NMBS/008846201",
"id": "BE.NMBS.008846201",
"name": "Visé",
"locationX": "5.692544",
"locationY": "50.73776",
"standardname": "Visé"
},
{
"@id": "http://irail.be/stations/NMBS/008866118",
"id": "BE.NMBS.008866118",
"name": "Viville",
"locationX": "5.786527",
"locationY": "49.688243",
"standardname": "Viville"
},
{
"@id": "http://irail.be/stations/NMBS/008841327",
"id": "BE.NMBS.008841327",
"name": "Voroux",
"locationX": "5.429556",
"locationY": "50.66181",
"standardname": "Voroux"
},
{
"@id": "http://irail.be/stations/NMBS/008814118",
"id": "BE.NMBS.008814118",
"name": "Vorst-Oost/Forest-Est",
"locationX": "4.320943",
"locationY": "50.810195",
"standardname": "Vorst-Oost/Forest-Est"
},
{
"@id": "http://irail.be/stations/NMBS/008814373",
"id": "BE.NMBS.008814373",
"name": "Vorst-Zuid/Forest-Midi",
"locationX": "4.309167",
"locationY": "50.809215",
"standardname": "Vorst-Zuid/Forest-Midi"
},
{
"@id": "http://irail.be/stations/NMBS/008893815",
"id": "BE.NMBS.008893815",
"name": "Waarschoot",
"locationX": "3.615353",
"locationY": "51.154608",
"standardname": "Waarschoot"
},
{
"@id": "http://irail.be/stations/NMBS/008873007",
"id": "BE.NMBS.008873007",
"name": "Walcourt",
"locationX": "4.435879",
"locationY": "50.259219",
"standardname": "Walcourt"
},
{
"@id": "http://irail.be/stations/NMBS/008896149",
"id": "BE.NMBS.008896149",
"name": "Waregem",
"locationX": "3.42551",
"locationY": "50.892456",
"standardname": "Waregem"
},
{
"@id": "http://irail.be/stations/NMBS/008841400",
"id": "BE.NMBS.008841400",
"name": "Waremme",
"locationX": "5.249475",
"locationY": "50.694549",
"standardname": "Waremme"
},
{
"@id": "http://irail.be/stations/NMBS/008814266",
"id": "BE.NMBS.008814266",
"name": "Waterloo",
"locationX": "4.383481",
"locationY": "50.715422",
"standardname": "Waterloo"
},
{
"@id": "http://irail.be/stations/NMBS/008811429",
"id": "BE.NMBS.008811429",
"name": "Watermaal/Watermael",
"locationX": "4.399887",
"locationY": "50.80917",
"standardname": "Watermaal/Watermael"
},
{
"@id": "http://irail.be/stations/NMBS/008811726",
"id": "BE.NMBS.008811726",
"name": "Wavre",
"locationX": "4.604778",
"locationY": "50.716267",
"standardname": "Wavre"
},
{
"@id": "http://irail.be/stations/NMBS/008822251",
"id": "BE.NMBS.008822251",
"name": "Weerde",
"locationX": "4.470937",
"locationY": "50.977449",
"standardname": "Weerde"
},
{
"@id": "http://irail.be/stations/NMBS/008844503",
"id": "BE.NMBS.008844503",
"name": "Welkenraedt",
"locationX": "5.975381",
"locationY": "50.659707",
"standardname": "Welkenraedt"
},
{
"@id": "http://irail.be/stations/NMBS/008895851",
"id": "BE.NMBS.008895851",
"name": "Welle",
"locationX": "4.05062",
"locationY": "50.903279",
"standardname": "Welle"
},
{
"@id": "http://irail.be/stations/NMBS/008896396",
"id": "BE.NMBS.008896396",
"name": "Wervik",
"locationX": "3.046983",
"locationY": "50.781861",
"standardname": "Wervik"
},
{
"@id": "http://irail.be/stations/NMBS/008822525",
"id": "BE.NMBS.008822525",
"name": "Wespelaar-Tildonk",
"locationX": "4.638011",
"locationY": "50.958544",
"standardname": "Wespelaar-Tildonk"
},
{
"@id": "http://irail.be/stations/NMBS/008893559",
"id": "BE.NMBS.008893559",
"name": "Wetteren",
"locationX": "3.881883",
"locationY": "51.001603",
"standardname": "Wetteren"
},
{
"@id": "http://irail.be/stations/NMBS/008896370",
"id": "BE.NMBS.008896370",
"name": "Wevelgem",
"locationX": "3.18352",
"locationY": "50.811526",
"standardname": "Wevelgem"
},
{
"@id": "http://irail.be/stations/NMBS/008833233",
"id": "BE.NMBS.008833233",
"name": "Wezemaal",
"locationX": "4.747679",
"locationY": "50.956261",
"standardname": "Wezemaal"
},
{
"@id": "http://irail.be/stations/NMBS/008893534",
"id": "BE.NMBS.008893534",
"name": "Wichelen",
"locationX": "3.969195",
"locationY": "51.001962",
"standardname": "Wichelen"
},
{
"@id": "http://irail.be/stations/NMBS/008833175",
"id": "BE.NMBS.008833175",
"name": "Wijgmaal",
"locationX": "4.701475",
"locationY": "50.92274",
"standardname": "Wijgmaal"
},
{
"@id": "http://irail.be/stations/NMBS/008821436",
"id": "BE.NMBS.008821436",
"name": "Wildert",
"locationX": "4.46335",
"locationY": "51.428087",
"standardname": "Wildert"
},
{
"@id": "http://irail.be/stations/NMBS/008822608",
"id": "BE.NMBS.008822608",
"name": "Willebroek",
"locationX": "4.356019",
"locationY": "51.066343",
"standardname": "Willebroek"
},
{
"@id": "http://irail.be/stations/NMBS/008200132",
"id": "BE.NMBS.008200132",
"name": "Wilwerwiltz",
"locationX": "5.999166",
"locationY": "49.988887",
"standardname": "Wilwerwiltz"
},
{
"@id": "http://irail.be/stations/NMBS/008821709",
"id": "BE.NMBS.008821709",
"name": "Wolfstee",
"locationX": "4.786144",
"locationY": "51.168361",
"standardname": "Wolfstee"
},
{
"@id": "http://irail.be/stations/NMBS/008893211",
"id": "BE.NMBS.008893211",
"name": "Wondelgem",
"locationX": "3.719071",
"locationY": "51.088357",
"standardname": "Wondelgem"
},
{
"@id": "http://irail.be/stations/NMBS/008847258",
"id": "BE.NMBS.008847258",
"name": "Y.renory",
"locationX": "5.55788",
"locationY": "50.604856",
"standardname": "Y.renory"
},
{
"@id": "http://irail.be/stations/NMBS/008896503",
"id": "BE.NMBS.008896503",
"name": "Ypres",
"locationX": "2.876593",
"locationY": "50.847402",
"standardname": "Ieper"
},
{
"@id": "http://irail.be/stations/NMBS/008873239",
"id": "BE.NMBS.008873239",
"name": "Yves-Gomezée",
"locationX": "4.500404",
"locationY": "50.23698",
"standardname": "Yves-Gomezée"
},
{
"@id": "http://irail.be/stations/NMBS/008863545",
"id": "BE.NMBS.008863545",
"name": "Yvoir",
"locationX": "4.878643",
"locationY": "50.32084",
"standardname": "Yvoir"
},
{
"@id": "http://irail.be/stations/NMBS/008895737",
"id": "BE.NMBS.008895737",
"name": "Zandbergen",
"locationX": "3.957653",
"locationY": "50.806986",
"standardname": "Zandbergen"
},
{
"@id": "http://irail.be/stations/NMBS/008811221",
"id": "BE.NMBS.008811221",
"name": "Zaventem",
"locationX": "4.469886",
"locationY": "50.885723",
"standardname": "Zaventem"
},
{
"@id": "http://irail.be/stations/NMBS/008891264",
"id": "BE.NMBS.008891264",
"name": "Zedelgem",
"locationX": "3.16414",
"locationY": "51.127047",
"standardname": "Zedelgem"
},
{
"@id": "http://irail.be/stations/NMBS/008891553",
"id": "BE.NMBS.008891553",
"name": "Zeebrugge-Dorp",
"locationX": "3.19517",
"locationY": "51.326383",
"standardname": "Zeebrugge-Dorp"
},
{
"@id": "http://irail.be/stations/NMBS/008891173",
"id": "BE.NMBS.008891173",
"name": "Zeebrugge-Strand",
"locationX": "3.184028",
"locationY": "51.330503",
"standardname": "Zeebrugge-Strand"
},
{
"@id": "http://irail.be/stations/NMBS/008894235",
"id": "BE.NMBS.008894235",
"name": "Zele",
"locationX": "4.041999",
"locationY": "51.073256",
"standardname": "Zele"
},
{
"@id": "http://irail.be/stations/NMBS/008812062",
"id": "BE.NMBS.008812062",
"name": "Zellik",
"locationX": "4.274541",
"locationY": "50.890028",
"standardname": "Zellik"
},
{
"@id": "http://irail.be/stations/NMBS/008833274",
"id": "BE.NMBS.008833274",
"name": "Zichem",
"locationX": "4.987359",
"locationY": "51.00669",
"standardname": "Zichem"
},
{
"@id": "http://irail.be/stations/NMBS/008892635",
"id": "BE.NMBS.008892635",
"name": "Zingem",
"locationX": "3.646384",
"locationY": "50.908025",
"standardname": "Zingem"
},
{
"@id": "http://irail.be/stations/NMBS/008832250",
"id": "BE.NMBS.008832250",
"name": "Zolder",
"locationX": "5.3299",
"locationY": "51.033548",
"standardname": "Zolder"
},
{
"@id": "http://irail.be/stations/NMBS/008832334",
"id": "BE.NMBS.008832334",
"name": "Zonhoven",
"locationX": "5.348815",
"locationY": "50.989557",
"standardname": "Zonhoven"
},
{
"@id": "http://irail.be/stations/NMBS/008895208",
"id": "BE.NMBS.008895208",
"name": "Zottegem",
"locationX": "3.81441",
"locationY": "50.869102",
"standardname": "Zottegem"
},
{
"@id": "http://irail.be/stations/NMBS/008891611",
"id": "BE.NMBS.008891611",
"name": "Zwankendamme",
"locationX": "3.191557",
"locationY": "51.306409",
"standardname": "Zwankendamme"
},
{
"@id": "http://irail.be/stations/NMBS/008894821",
"id": "BE.NMBS.008894821",
"name": "Zwijndrecht",
"locationX": "4.32978",
"locationY": "51.214108",
"standardname": "Zwijndrecht"
},
{
"@id": "http://irail.be/stations/NMBS/008800252",
"id": "BE.NMBS.008800252",
"name": "Zwijndrecht-Dorp",
"locationX": "4.3256707",
"locationY": "51.2191653",
"standardname": "Zwijndrecht-Dorp"
},
{
"@id": "http://irail.be/stations/NMBS/000000252",
"id": "BE.NMBS.000000252",
"name": "Zwijndrecht-Dorp",
"locationX": "4.3256707",
"locationY": "51.2191653",
"standardname": "Zwijndrecht-Dorp"
},
{
"@id": "http://irail.be/stations/NMBS/008883212",
"id": "BE.NMBS.008883212",
"name": "Écaussinnes",
"locationX": "4.156639",
"locationY": "50.56239",
"standardname": "Écaussinnes"
}
]
} tjorim-pyrail-4c4ba2c/examples/vehicle.json 0000664 0000000 0000000 00000051177 14755342216 0021154 0 ustar 00root root 0000000 0000000 {
"version": "1.3",
"timestamp": "1736203520",
"vehicle": "BE.NMBS.IC3033",
"vehicleinfo": {
"name": "BE.NMBS.IC3033",
"shortname": "IC 3033",
"number": "3033",
"type": "IC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/IC3033"
},
"stops": {
"number": "16",
"stop": [
{
"id": "0",
"station": "De Panne",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892338",
"id": "BE.NMBS.008892338",
"name": "De Panne",
"locationX": "2.601963",
"locationY": "51.0774",
"standardname": "De Panne"
},
"time": "1736157120",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736157120",
"scheduledArrivalTime": "1736157120",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "0",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892338/20250106/IC3033"
},
{
"id": "1",
"station": "Koksijde",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892320",
"id": "BE.NMBS.008892320",
"name": "Koksijde",
"locationX": "2.65277",
"locationY": "51.079197",
"standardname": "Koksijde"
},
"time": "1736157360",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736157360",
"scheduledArrivalTime": "1736157300",
"delay": "60",
"canceled": "0",
"departureDelay": "60",
"departureCanceled": "0",
"arrivalDelay": "60",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892320/20250106/IC3033"
},
{
"id": "2",
"station": "Veurne",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892304",
"id": "BE.NMBS.008892304",
"name": "Veurne",
"locationX": "2.66994",
"locationY": "51.073867",
"standardname": "Veurne"
},
"time": "1736157660",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736157660",
"scheduledArrivalTime": "1736157540",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "0",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892304/20250106/IC3033"
},
{
"id": "3",
"station": "Diksmuide",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892452",
"id": "BE.NMBS.008892452",
"name": "Diksmuide",
"locationX": "2.868943",
"locationY": "51.032723",
"standardname": "Diksmuide"
},
"time": "1736158380",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736158380",
"scheduledArrivalTime": "1736158260",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "0",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892452/20250106/IC3033"
},
{
"id": "4",
"station": "Kortemark",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892403",
"id": "BE.NMBS.008892403",
"name": "Kortemark",
"locationX": "3.043459",
"locationY": "51.025244",
"standardname": "Kortemark"
},
"time": "1736158980",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736158980",
"scheduledArrivalTime": "1736158920",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "-60",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
},
"departureConnection": "http://irail.be/connections/8892403/20250106/IC3033"
},
{
"id": "5",
"station": "Lichtervelde",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892205",
"id": "BE.NMBS.008892205",
"name": "Lichtervelde",
"locationX": "3.127212",
"locationY": "51.025163",
"standardname": "Lichtervelde"
},
"time": "1736159400",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736159400",
"scheduledArrivalTime": "1736159280",
"delay": "120",
"canceled": "0",
"departureDelay": "120",
"departureCanceled": "0",
"arrivalDelay": "120",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892205/20250106/IC3033"
},
{
"id": "6",
"station": "Tielt",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892254",
"id": "BE.NMBS.008892254",
"name": "Tielt",
"locationX": "3.330341",
"locationY": "50.990842",
"standardname": "Tielt"
},
"time": "1736160120",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736160120",
"scheduledArrivalTime": "1736160060",
"delay": "180",
"canceled": "0",
"departureDelay": "180",
"departureCanceled": "0",
"arrivalDelay": "120",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/medium",
"name": "medium"
},
"departureConnection": "http://irail.be/connections/8892254/20250106/IC3033"
},
{
"id": "7",
"station": "Deinze",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892106",
"id": "BE.NMBS.008892106",
"name": "Deinze",
"locationX": "3.534432",
"locationY": "50.978258",
"standardname": "Deinze"
},
"time": "1736160780",
"platform": "5",
"platforminfo": {
"name": "5",
"normal": "1"
},
"scheduledDepartureTime": "1736160780",
"scheduledArrivalTime": "1736160720",
"delay": "180",
"canceled": "0",
"departureDelay": "180",
"departureCanceled": "0",
"arrivalDelay": "120",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892106/20250106/IC3033"
},
{
"id": "8",
"station": "De Pinte",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892080",
"id": "BE.NMBS.008892080",
"name": "De Pinte",
"locationX": "3.650465",
"locationY": "50.997063",
"standardname": "De Pinte"
},
"time": "1736161260",
"platform": "4",
"platforminfo": {
"name": "4",
"normal": "1"
},
"scheduledDepartureTime": "1736161260",
"scheduledArrivalTime": "1736161140",
"delay": "60",
"canceled": "0",
"departureDelay": "60",
"departureCanceled": "0",
"arrivalDelay": "120",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892080/20250106/IC3033"
},
{
"id": "9",
"station": "Ghent-Sint-Pieters",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008892007",
"id": "BE.NMBS.008892007",
"name": "Ghent-Sint-Pieters",
"locationX": "3.710675",
"locationY": "51.035896",
"standardname": "Gent-Sint-Pieters"
},
"time": "1736161800",
"platform": "1",
"platforminfo": {
"name": "1",
"normal": "1"
},
"scheduledDepartureTime": "1736161800",
"scheduledArrivalTime": "1736161620",
"delay": "60",
"canceled": "0",
"departureDelay": "60",
"departureCanceled": "0",
"arrivalDelay": "120",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8892007/20250106/IC3033"
},
{
"id": "10",
"station": "Ghent-Dampoort",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008893120",
"id": "BE.NMBS.008893120",
"name": "Ghent-Dampoort",
"locationX": "3.740591",
"locationY": "51.056365",
"standardname": "Gent-Dampoort"
},
"time": "1736162340",
"platform": "2",
"platforminfo": {
"name": "2",
"normal": "1"
},
"scheduledDepartureTime": "1736162340",
"scheduledArrivalTime": "1736162280",
"delay": "60",
"canceled": "0",
"departureDelay": "60",
"departureCanceled": "0",
"arrivalDelay": "-60",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8893120/20250106/IC3033"
},
{
"id": "11",
"station": "Lokeren",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894201",
"id": "BE.NMBS.008894201",
"name": "Lokeren",
"locationX": "3.987794",
"locationY": "51.108062",
"standardname": "Lokeren"
},
"time": "1736163180",
"platform": "2",
"platforminfo": {
"name": "2",
"normal": "1"
},
"scheduledDepartureTime": "1736163180",
"scheduledArrivalTime": "1736163120",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "-60",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8894201/20250106/IC3033"
},
{
"id": "12",
"station": "Sint-Niklaas",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008894508",
"id": "BE.NMBS.008894508",
"name": "Sint-Niklaas",
"locationX": "4.142966",
"locationY": "51.171472",
"standardname": "Sint-Niklaas"
},
"time": "1736163900",
"platform": "4",
"platforminfo": {
"name": "4",
"normal": "1"
},
"scheduledDepartureTime": "1736163900",
"scheduledArrivalTime": "1736163720",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "0",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8894508/20250106/IC3033"
},
{
"id": "13",
"station": "Antwerp-South",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821196",
"id": "BE.NMBS.008821196",
"name": "Antwerp-South",
"locationX": "4.390259",
"locationY": "51.197828",
"standardname": "Antwerpen-Zuid"
},
"time": "1736164800",
"platform": "2",
"platforminfo": {
"name": "2",
"normal": "1"
},
"scheduledDepartureTime": "1736164800",
"scheduledArrivalTime": "1736164680",
"delay": "0",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "60",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/low",
"name": "low"
},
"departureConnection": "http://irail.be/connections/8821196/20250106/IC3033"
},
{
"id": "14",
"station": "Antwerp-Berchem",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821121",
"id": "BE.NMBS.008821121",
"name": "Antwerp-Berchem",
"locationX": "4.432221",
"locationY": "51.19923",
"standardname": "Antwerpen-Berchem"
},
"time": "1736165100",
"platform": "7",
"platforminfo": {
"name": "7",
"normal": "1"
},
"scheduledDepartureTime": "1736165100",
"scheduledArrivalTime": "1736165040",
"delay": "180",
"canceled": "0",
"departureDelay": "180",
"departureCanceled": "0",
"arrivalDelay": "120",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
},
"departureConnection": "http://irail.be/connections/8821121/20250106/IC3033"
},
{
"id": "15",
"station": "Antwerp-Central",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008821006",
"id": "BE.NMBS.008821006",
"name": "Antwerp-Central",
"locationX": "4.421101",
"locationY": "51.2172",
"standardname": "Antwerpen-Centraal"
},
"time": "1736165340",
"platform": "11",
"platforminfo": {
"name": "11",
"normal": "0"
},
"scheduledDepartureTime": "1736165340",
"scheduledArrivalTime": "1736165340",
"delay": "180",
"canceled": "0",
"departureDelay": "0",
"departureCanceled": "0",
"arrivalDelay": "180",
"arrivalCanceled": "0",
"left": "0",
"arrived": "0",
"isExtraStop": "0"
}
]
}
} tjorim-pyrail-4c4ba2c/poetry.lock 0000664 0000000 0000000 00000275264 14755342216 0017225 0 ustar 00root root 0000000 0000000 # This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
[[package]]
name = "aiohappyeyeballs"
version = "2.4.4"
description = "Happy Eyeballs for asyncio"
optional = false
python-versions = ">=3.8"
files = [
{file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"},
{file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"},
]
[[package]]
name = "aiohttp"
version = "3.11.12"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.9"
files = [
{file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f"},
{file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854"},
{file = "aiohttp-3.11.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:584096938a001378484aa4ee54e05dc79c7b9dd933e271c744a97b3b6f644957"},
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392432a2dde22b86f70dd4a0e9671a349446c93965f261dbaecfaf28813e5c42"},
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d385b8e7f3a870146bf5ea31786ef7463e99eb59e31db56e2315535d811f55"},
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b10a47e5390c4b30a0d58ee12581003be52eedd506862ab7f97da7a66805befb"},
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5263dcede17b6b0c41ef0c3ccce847d82a7da98709e75cf7efde3e9e3b5cae"},
{file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50c5c7b8aa5443304c55c262c5693b108c35a3b61ef961f1e782dd52a2f559c7"},
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1c031a7572f62f66f1257db37ddab4cb98bfaf9b9434a3b4840bf3560f5e788"},
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e44eba534381dd2687be50cbd5f2daded21575242ecfdaf86bbeecbc38dae8e"},
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:145a73850926018ec1681e734cedcf2716d6a8697d90da11284043b745c286d5"},
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2c311e2f63e42c1bf86361d11e2c4a59f25d9e7aabdbdf53dc38b885c5435cdb"},
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ea756b5a7bac046d202a9a3889b9a92219f885481d78cd318db85b15cc0b7bcf"},
{file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:526c900397f3bbc2db9cb360ce9c35134c908961cdd0ac25b1ae6ffcaa2507ff"},
{file = "aiohttp-3.11.12-cp310-cp310-win32.whl", hash = "sha256:b8d3bb96c147b39c02d3db086899679f31958c5d81c494ef0fc9ef5bb1359b3d"},
{file = "aiohttp-3.11.12-cp310-cp310-win_amd64.whl", hash = "sha256:7fe3d65279bfbee8de0fb4f8c17fc4e893eed2dba21b2f680e930cc2b09075c5"},
{file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb"},
{file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9"},
{file = "aiohttp-3.11.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933"},
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1"},
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94"},
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6"},
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5"},
{file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204"},
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58"},
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef"},
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420"},
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df"},
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804"},
{file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b"},
{file = "aiohttp-3.11.12-cp311-cp311-win32.whl", hash = "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16"},
{file = "aiohttp-3.11.12-cp311-cp311-win_amd64.whl", hash = "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6"},
{file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250"},
{file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1"},
{file = "aiohttp-3.11.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c"},
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df"},
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259"},
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d"},
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e"},
{file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0"},
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0"},
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9"},
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f"},
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9"},
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef"},
{file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9"},
{file = "aiohttp-3.11.12-cp312-cp312-win32.whl", hash = "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a"},
{file = "aiohttp-3.11.12-cp312-cp312-win_amd64.whl", hash = "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802"},
{file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9"},
{file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c"},
{file = "aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0"},
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2"},
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1"},
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7"},
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e"},
{file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed"},
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484"},
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65"},
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb"},
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00"},
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a"},
{file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce"},
{file = "aiohttp-3.11.12-cp313-cp313-win32.whl", hash = "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f"},
{file = "aiohttp-3.11.12-cp313-cp313-win_amd64.whl", hash = "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287"},
{file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c3623053b85b4296cd3925eeb725e386644fd5bc67250b3bb08b0f144803e7b"},
{file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67453e603cea8e85ed566b2700efa1f6916aefbc0c9fcb2e86aaffc08ec38e78"},
{file = "aiohttp-3.11.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6130459189e61baac5a88c10019b21e1f0c6d00ebc770e9ce269475650ff7f73"},
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9060addfa4ff753b09392efe41e6af06ea5dd257829199747b9f15bfad819460"},
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34245498eeb9ae54c687a07ad7f160053911b5745e186afe2d0c0f2898a1ab8a"},
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8dc0fba9a74b471c45ca1a3cb6e6913ebfae416678d90529d188886278e7f3f6"},
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a478aa11b328983c4444dacb947d4513cb371cd323f3845e53caeda6be5589d5"},
{file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c160a04283c8c6f55b5bf6d4cad59bb9c5b9c9cd08903841b25f1f7109ef1259"},
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:edb69b9589324bdc40961cdf0657815df674f1743a8d5ad9ab56a99e4833cfdd"},
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ee84c2a22a809c4f868153b178fe59e71423e1f3d6a8cd416134bb231fbf6d3"},
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bf4480a5438f80e0f1539e15a7eb8b5f97a26fe087e9828e2c0ec2be119a9f72"},
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e6b2732ef3bafc759f653a98881b5b9cdef0716d98f013d376ee8dfd7285abf1"},
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f752e80606b132140883bb262a457c475d219d7163d996dc9072434ffb0784c4"},
{file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab3247d58b393bda5b1c8f31c9edece7162fc13265334217785518dd770792b8"},
{file = "aiohttp-3.11.12-cp39-cp39-win32.whl", hash = "sha256:0d5176f310a7fe6f65608213cc74f4228e4f4ce9fd10bcb2bb6da8fc66991462"},
{file = "aiohttp-3.11.12-cp39-cp39-win_amd64.whl", hash = "sha256:74bd573dde27e58c760d9ca8615c41a57e719bff315c9adb6f2a4281a28e8798"},
{file = "aiohttp-3.11.12.tar.gz", hash = "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0"},
]
[package.dependencies]
aiohappyeyeballs = ">=2.3.0"
aiosignal = ">=1.1.2"
attrs = ">=17.3.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
propcache = ">=0.2.0"
yarl = ">=1.17.0,<2.0"
[package.extras]
speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"]
[[package]]
name = "aiosignal"
version = "1.3.2"
description = "aiosignal: a list of registered asynchronous callbacks"
optional = false
python-versions = ">=3.9"
files = [
{file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"},
{file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"},
]
[package.dependencies]
frozenlist = ">=1.1.0"
[[package]]
name = "attrs"
version = "24.3.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.8"
files = [
{file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"},
{file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"},
]
[package.extras]
benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "frozenlist"
version = "1.5.0"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.8"
files = [
{file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"},
{file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"},
{file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"},
{file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"},
{file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"},
{file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"},
{file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"},
{file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"},
{file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"},
{file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"},
{file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"},
{file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"},
{file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"},
{file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"},
{file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"},
{file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"},
{file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"},
{file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"},
{file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"},
{file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"},
{file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"},
{file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"},
{file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"},
{file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"},
{file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"},
{file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"},
{file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"},
{file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"},
{file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"},
{file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"},
{file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"},
{file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"},
{file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"},
{file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"},
{file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"},
{file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"},
{file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"},
{file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"},
{file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"},
{file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"},
{file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"},
{file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"},
{file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"},
{file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"},
]
[[package]]
name = "idna"
version = "3.10"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.6"
files = [
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
]
[package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
optional = false
python-versions = ">=3.7"
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "mashumaro"
version = "3.15"
description = "Fast and well tested serialization library"
optional = false
python-versions = ">=3.9"
files = [
{file = "mashumaro-3.15-py3-none-any.whl", hash = "sha256:cdd45ef5a4d09860846a3ee37a4c2f5f4bc70eb158caa55648c4c99451ca6c4c"},
{file = "mashumaro-3.15.tar.gz", hash = "sha256:32a2a38a1e942a07f2cbf9c3061cb2a247714ee53e36a5958548b66bd116d0a9"},
]
[package.dependencies]
orjson = {version = "*", optional = true, markers = "extra == \"orjson\""}
typing-extensions = ">=4.1.0"
[package.extras]
msgpack = ["msgpack (>=0.5.6)"]
orjson = ["orjson"]
toml = ["tomli (>=1.1.0)", "tomli-w (>=1.0)"]
yaml = ["pyyaml (>=3.13)"]
[[package]]
name = "multidict"
version = "6.1.0"
description = "multidict implementation"
optional = false
python-versions = ">=3.8"
files = [
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"},
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"},
{file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"},
{file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"},
{file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"},
{file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"},
{file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"},
{file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"},
{file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"},
{file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"},
{file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"},
{file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"},
{file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"},
{file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"},
{file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"},
{file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"},
{file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"},
{file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"},
{file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"},
{file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"},
{file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"},
{file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"},
{file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"},
{file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"},
{file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"},
{file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"},
{file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"},
{file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"},
{file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"},
{file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"},
{file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"},
{file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"},
]
[[package]]
name = "mypy"
version = "1.15.0"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.9"
files = [
{file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"},
{file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"},
{file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"},
{file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"},
{file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"},
{file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"},
{file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"},
{file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"},
{file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"},
{file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"},
{file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"},
{file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"},
{file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"},
{file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"},
{file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"},
{file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"},
{file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"},
{file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"},
{file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"},
{file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"},
{file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"},
{file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"},
{file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"},
{file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"},
{file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"},
{file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"},
{file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"},
{file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"},
{file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"},
{file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"},
{file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"},
{file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"},
]
[package.dependencies]
mypy_extensions = ">=1.0.0"
typing_extensions = ">=4.6.0"
[package.extras]
dmypy = ["psutil (>=4.0)"]
faster-cache = ["orjson"]
install-types = ["pip"]
mypyc = ["setuptools (>=50)"]
reports = ["lxml"]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
optional = false
python-versions = ">=3.5"
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
[[package]]
name = "orjson"
version = "3.10.13"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false
python-versions = ">=3.8"
files = [
{file = "orjson-3.10.13-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1232c5e873a4d1638ef957c5564b4b0d6f2a6ab9e207a9b3de9de05a09d1d920"},
{file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d26a0eca3035619fa366cbaf49af704c7cb1d4a0e6c79eced9f6a3f2437964b6"},
{file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d4b6acd7c9c829895e50d385a357d4b8c3fafc19c5989da2bae11783b0fd4977"},
{file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1884e53c6818686891cc6fc5a3a2540f2f35e8c76eac8dc3b40480fb59660b00"},
{file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a428afb5720f12892f64920acd2eeb4d996595bf168a26dd9190115dbf1130d"},
{file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba5b13b8739ce5b630c65cb1c85aedbd257bcc2b9c256b06ab2605209af75a2e"},
{file = "orjson-3.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cab83e67f6aabda1b45882254b2598b48b80ecc112968fc6483fa6dae609e9f0"},
{file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:62c3cc00c7e776c71c6b7b9c48c5d2701d4c04e7d1d7cdee3572998ee6dc57cc"},
{file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:dc03db4922e75bbc870b03fc49734cefbd50fe975e0878327d200022210b82d8"},
{file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:22f1c9a30b43d14a041a6ea190d9eca8a6b80c4beb0e8b67602c82d30d6eec3e"},
{file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b42f56821c29e697c68d7d421410d7c1d8f064ae288b525af6a50cf99a4b1200"},
{file = "orjson-3.10.13-cp310-cp310-win32.whl", hash = "sha256:0dbf3b97e52e093d7c3e93eb5eb5b31dc7535b33c2ad56872c83f0160f943487"},
{file = "orjson-3.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:46c249b4e934453be4ff2e518cd1adcd90467da7391c7a79eaf2fbb79c51e8c7"},
{file = "orjson-3.10.13-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a36c0d48d2f084c800763473020a12976996f1109e2fcb66cfea442fdf88047f"},
{file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0065896f85d9497990731dfd4a9991a45b0a524baec42ef0a63c34630ee26fd6"},
{file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92b4ec30d6025a9dcdfe0df77063cbce238c08d0404471ed7a79f309364a3d19"},
{file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a94542d12271c30044dadad1125ee060e7a2048b6c7034e432e116077e1d13d2"},
{file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3723e137772639af8adb68230f2aa4bcb27c48b3335b1b1e2d49328fed5e244c"},
{file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f00c7fb18843bad2ac42dc1ce6dd214a083c53f1e324a0fd1c8137c6436269b"},
{file = "orjson-3.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0e2759d3172300b2f892dee85500b22fca5ac49e0c42cfff101aaf9c12ac9617"},
{file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee948c6c01f6b337589c88f8e0bb11e78d32a15848b8b53d3f3b6fea48842c12"},
{file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:aa6fe68f0981fba0d4bf9cdc666d297a7cdba0f1b380dcd075a9a3dd5649a69e"},
{file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbcd7aad6bcff258f6896abfbc177d54d9b18149c4c561114f47ebfe74ae6bfd"},
{file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2149e2fcd084c3fd584881c7f9d7f9e5ad1e2e006609d8b80649655e0d52cd02"},
{file = "orjson-3.10.13-cp311-cp311-win32.whl", hash = "sha256:89367767ed27b33c25c026696507c76e3d01958406f51d3a2239fe9e91959df2"},
{file = "orjson-3.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:dca1d20f1af0daff511f6e26a27354a424f0b5cf00e04280279316df0f604a6f"},
{file = "orjson-3.10.13-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a3614b00621c77f3f6487792238f9ed1dd8a42f2ec0e6540ee34c2d4e6db813a"},
{file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c976bad3996aa027cd3aef78aa57873f3c959b6c38719de9724b71bdc7bd14b"},
{file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f74d878d1efb97a930b8a9f9898890067707d683eb5c7e20730030ecb3fb930"},
{file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33ef84f7e9513fb13b3999c2a64b9ca9c8143f3da9722fbf9c9ce51ce0d8076e"},
{file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd2bcde107221bb9c2fa0c4aaba735a537225104173d7e19cf73f70b3126c993"},
{file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:064b9dbb0217fd64a8d016a8929f2fae6f3312d55ab3036b00b1d17399ab2f3e"},
{file = "orjson-3.10.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0044b0b8c85a565e7c3ce0a72acc5d35cda60793edf871ed94711e712cb637d"},
{file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7184f608ad563032e398f311910bc536e62b9fbdca2041be889afcbc39500de8"},
{file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d36f689e7e1b9b6fb39dbdebc16a6f07cbe994d3644fb1c22953020fc575935f"},
{file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:54433e421618cd5873e51c0e9d0b9fb35f7bf76eb31c8eab20b3595bb713cd3d"},
{file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e1ba0c5857dd743438acecc1cd0e1adf83f0a81fee558e32b2b36f89e40cee8b"},
{file = "orjson-3.10.13-cp312-cp312-win32.whl", hash = "sha256:a42b9fe4b0114b51eb5cdf9887d8c94447bc59df6dbb9c5884434eab947888d8"},
{file = "orjson-3.10.13-cp312-cp312-win_amd64.whl", hash = "sha256:3a7df63076435f39ec024bdfeb4c9767ebe7b49abc4949068d61cf4857fa6d6c"},
{file = "orjson-3.10.13-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2cdaf8b028a976ebab837a2c27b82810f7fc76ed9fb243755ba650cc83d07730"},
{file = "orjson-3.10.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a946796e390cbb803e069472de37f192b7a80f4ac82e16d6eb9909d9e39d56"},
{file = "orjson-3.10.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d64f1db5ecbc21eb83097e5236d6ab7e86092c1cd4c216c02533332951afc"},
{file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:711878da48f89df194edd2ba603ad42e7afed74abcd2bac164685e7ec15f96de"},
{file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:cf16f06cb77ce8baf844bc222dbcb03838f61d0abda2c3341400c2b7604e436e"},
{file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8257c3fb8dd7b0b446b5e87bf85a28e4071ac50f8c04b6ce2d38cb4abd7dff57"},
{file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9c3a87abe6f849a4a7ac8a8a1dede6320a4303d5304006b90da7a3cd2b70d2c"},
{file = "orjson-3.10.13-cp313-cp313-win32.whl", hash = "sha256:527afb6ddb0fa3fe02f5d9fba4920d9d95da58917826a9be93e0242da8abe94a"},
{file = "orjson-3.10.13-cp313-cp313-win_amd64.whl", hash = "sha256:b5f7c298d4b935b222f52d6c7f2ba5eafb59d690d9a3840b7b5c5cda97f6ec5c"},
{file = "orjson-3.10.13-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e49333d1038bc03a25fdfe11c86360df9b890354bfe04215f1f54d030f33c342"},
{file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:003721c72930dbb973f25c5d8e68d0f023d6ed138b14830cc94e57c6805a2eab"},
{file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63664bf12addb318dc8f032160e0f5dc17eb8471c93601e8f5e0d07f95003784"},
{file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6066729cf9552d70de297b56556d14b4f49c8f638803ee3c90fd212fa43cc6af"},
{file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8a1152e2761025c5d13b5e1908d4b1c57f3797ba662e485ae6f26e4e0c466388"},
{file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b21d91c5c5ef8a201036d207b1adf3aa596b930b6ca3c71484dd11386cf6c3"},
{file = "orjson-3.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b12a63f48bb53dba8453d36ca2661f2330126d54e26c1661e550b32864b28ce3"},
{file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a5a7624ab4d121c7e035708c8dd1f99c15ff155b69a1c0affc4d9d8b551281ba"},
{file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:0fee076134398d4e6cb827002468679ad402b22269510cf228301b787fdff5ae"},
{file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ae537fcf330b3947e82c6ae4271e092e6cf16b9bc2cef68b14ffd0df1fa8832a"},
{file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f81b26c03f5fb5f0d0ee48d83cea4d7bc5e67e420d209cc1a990f5d1c62f9be0"},
{file = "orjson-3.10.13-cp38-cp38-win32.whl", hash = "sha256:0bc858086088b39dc622bc8219e73d3f246fb2bce70a6104abd04b3a080a66a8"},
{file = "orjson-3.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:3ca6f17467ebbd763f8862f1d89384a5051b461bb0e41074f583a0ebd7120e8e"},
{file = "orjson-3.10.13-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4a11532cbfc2f5752c37e84863ef8435b68b0e6d459b329933294f65fa4bda1a"},
{file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c96d2fb80467d1d0dfc4d037b4e1c0f84f1fe6229aa7fea3f070083acef7f3d7"},
{file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dda4ba4d3e6f6c53b6b9c35266788053b61656a716a7fef5c884629c2a52e7aa"},
{file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4f998bbf300690be881772ee9c5281eb9c0044e295bcd4722504f5b5c6092ff"},
{file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1cc42ed75b585c0c4dc5eb53a90a34ccb493c09a10750d1a1f9b9eff2bd12"},
{file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03b0f29d485411e3c13d79604b740b14e4e5fb58811743f6f4f9693ee6480a8f"},
{file = "orjson-3.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:233aae4474078d82f425134bb6a10fb2b3fc5a1a1b3420c6463ddd1b6a97eda8"},
{file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e384e330a67cf52b3597ee2646de63407da6f8fc9e9beec3eaaaef5514c7a1c9"},
{file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4222881d0aab76224d7b003a8e5fdae4082e32c86768e0e8652de8afd6c4e2c1"},
{file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e400436950ba42110a20c50c80dff4946c8e3ec09abc1c9cf5473467e83fd1c5"},
{file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f47c9e7d224b86ffb086059cdcf634f4b3f32480f9838864aa09022fe2617ce2"},
{file = "orjson-3.10.13-cp39-cp39-win32.whl", hash = "sha256:a9ecea472f3eb653e1c0a3d68085f031f18fc501ea392b98dcca3e87c24f9ebe"},
{file = "orjson-3.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:5385935a73adce85cc7faac9d396683fd813566d3857fa95a0b521ef84a5b588"},
{file = "orjson-3.10.13.tar.gz", hash = "sha256:eb9bfb14ab8f68d9d9492d4817ae497788a15fd7da72e14dfabc289c3bb088ec"},
]
[[package]]
name = "packaging"
version = "24.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
]
[[package]]
name = "pluggy"
version = "1.5.0"
description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=3.8"
files = [
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "propcache"
version = "0.2.1"
description = "Accelerated property cache"
optional = false
python-versions = ">=3.9"
files = [
{file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"},
{file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"},
{file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"},
{file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"},
{file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"},
{file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"},
{file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"},
{file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"},
{file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"},
{file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"},
{file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"},
{file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"},
{file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"},
{file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"},
{file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"},
{file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"},
{file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"},
{file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"},
{file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"},
{file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"},
{file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"},
{file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"},
{file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"},
{file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"},
{file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"},
{file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"},
{file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"},
{file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"},
{file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"},
{file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"},
{file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"},
{file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"},
{file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"},
{file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"},
{file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"},
{file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"},
{file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"},
]
[[package]]
name = "pytest"
version = "8.3.4"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
{file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
]
[package.dependencies]
colorama = {version = "*", markers = "sys_platform == \"win32\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=1.5,<2"
[package.extras]
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "pytest-asyncio"
version = "0.25.3"
description = "Pytest support for asyncio"
optional = false
python-versions = ">=3.9"
files = [
{file = "pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"},
{file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"},
]
[package.dependencies]
pytest = ">=8.2,<9"
[package.extras]
docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"]
testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"]
[[package]]
name = "pytest-mock"
version = "3.14.0"
description = "Thin-wrapper around the mock package for easier use with pytest"
optional = false
python-versions = ">=3.8"
files = [
{file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"},
{file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"},
]
[package.dependencies]
pytest = ">=6.2.5"
[package.extras]
dev = ["pre-commit", "pytest-asyncio", "tox"]
[[package]]
name = "ruff"
version = "0.9.6"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"},
{file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"},
{file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"},
{file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"},
{file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"},
{file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"},
{file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"},
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "yarl"
version = "1.18.3"
description = "Yet another URL library"
optional = false
python-versions = ">=3.9"
files = [
{file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"},
{file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"},
{file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"},
{file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"},
{file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"},
{file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"},
{file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"},
{file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"},
{file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"},
{file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"},
{file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"},
{file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"},
{file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"},
{file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"},
{file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"},
{file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"},
{file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"},
{file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"},
{file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"},
{file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"},
{file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"},
{file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"},
{file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"},
{file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"},
{file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"},
{file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"},
{file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"},
{file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"},
{file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"},
{file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"},
{file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"},
{file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"},
{file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"},
{file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"},
{file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"},
{file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"},
{file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"},
]
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
propcache = ">=0.2.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.12"
content-hash = "7fd613c8b8445c1cbbd524ae6267b5f9167653901b9e49f18fb53c53a10cfe85"
tjorim-pyrail-4c4ba2c/pyproject.toml 0000664 0000000 0000000 00000003521 14755342216 0017726 0 ustar 00root root 0000000 0000000 [tool.poetry]
name = "pyrail"
version = "0.4.0"
description = "A Python wrapper for the iRail API"
authors = ["Jorim Tielemans "]
license = "Apache-2.0"
readme = "README.md"
homepage = "https://github.com/tjorim/pyrail"
repository = "https://github.com/tjorim/pyrail"
documentation = "https://github.com/tjorim/pyrail"
keywords = ["irail", "nmbs"]
classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules"
]
packages = [
{ include = "pyrail" },
]
[tool.poetry.dependencies]
python = "^3.12"
aiohttp = "^3.11.11"
mashumaro = {extras = ["orjson"], version = "^3.15"}
[tool.poetry.group.test.dependencies]
pytest = "^8.3.4"
pytest-mock = "^3.14.0"
pytest-asyncio = "^0.25.1"
[tool.poetry.group.dev.dependencies]
ruff = ">=0.8.4,<0.10.0"
mypy = "^1.14.1"
[tool.mypy]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
exclude = ["^tests/"]
no_implicit_optional = true
python_version = "3.12"
show_error_codes = true
strict = true
strict_equality = true
warn_return_any = true
warn_unused_configs = true
[tool.ruff]
line-length = 120
[tool.ruff.lint]
select = [
"C", # complexity
"D", # docstrings
"E", # pycodestyle
"F", # pyflakes
"G", # flake8-logging-format
"I", # isort
"W", # pycodestyle warnings
]
ignore = [
"D203", # vs D211 (no blank line before class)
"D213", # vs D212 (multi line summary first line)
"E501", # line too long
"W191", # indentation contains tabs
]
[tool.ruff.lint.isort]
force-sort-within-sections = true
combine-as-imports = true
split-on-trailing-comma = false
[tool.ruff.lint.pydocstyle]
property-decorators = ["propcache.cached_property"]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
tjorim-pyrail-4c4ba2c/pyrail/ 0000775 0000000 0000000 00000000000 14755342216 0016311 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/pyrail/__init__.py 0000664 0000000 0000000 00000000127 14755342216 0020422 0 ustar 00root root 0000000 0000000 """Package initialization for pyrail."""
from .irail import iRail
__all__ = ["iRail"]
tjorim-pyrail-4c4ba2c/pyrail/irail.py 0000664 0000000 0000000 00000055611 14755342216 0017773 0 ustar 00root root 0000000 0000000 """Module providing the iRail class for interacting with the iRail API."""
import asyncio
from asyncio import Lock
from datetime import datetime
import logging
import time
from types import TracebackType
from typing import Any, Type
from aiohttp import ClientError, ClientResponse, ClientSession
from pyrail.models import (
CompositionApiResponse,
ConnectionsApiResponse,
DisturbancesApiResponse,
LiveboardApiResponse,
StationsApiResponse,
VehicleApiResponse,
)
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger: logging.Logger = logging.getLogger(__name__)
class iRail:
"""A Python wrapper for the iRail API, handling rate limiting and endpoint requests.
Attributes:
lang (str): The language for API responses ('nl', 'fr', 'en', 'de').
session (ClientSession, optional): The HTTP session used for API requests.
If not provided, a new session will be created and managed internally.
If provided, the session lifecycle must be managed externally.
Endpoints:
stations: Retrieve all stations.
liveboard: Retrieve a liveboard for a station or ID.
connections: Retrieve connections between two stations.
vehicle: Retrieve information about a specific train.
composition: Retrieve the composition of a train.
disturbances: Retrieve information about current disturbances on the rail network.
"""
# Available iRail API endpoints and their parameter requirements.
# Each endpoint is configured with required parameters, optional parameters, and XOR
# parameter groups (where exactly one parameter from the group must be provided).
endpoints: dict[str, dict[str, Any]] = {
"stations": {},
"liveboard": {"xor": ["station", "id"], "optional": ["date", "time", "arrdep", "alerts"]},
"connections": {
"required": ["from", "to"],
"optional": ["date", "time", "timesel", "typeOfTransport"],
},
"vehicle": {"required": ["id"], "optional": ["date", "alerts"]},
"composition": {"required": ["id"], "optional": ["data"]},
"disturbances": {"optional": ["lineBreakCharacter"]},
}
def __init__(self, lang: str = "en", session: ClientSession | None = None) -> None:
"""Initialize the iRail API client.
Args:
lang (str): The language for API responses. Default is 'en'.
session (ClientSession, optional): An existing aiohttp session. Defaults to None.
"""
self.lang: str = lang
self.tokens: int = 3
self.burst_tokens: int = 5
self.last_request_time: float = time.time()
self.lock: Lock = Lock()
self.session: ClientSession | None = session
self._owns_session = session is None # Track ownership
self.etag_cache: dict[str, str] = {}
logger.info("iRail instance created")
async def __aenter__(self) -> "iRail":
"""Initialize the aiohttp client session when entering the async context."""
if self.session and not self.session.closed:
logger.debug("Using externally provided session")
elif not self.session:
logger.debug("Creating new internal aiohttp session")
self.session = ClientSession()
return self
async def __aexit__(
self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None
) -> None:
"""Close the aiohttp client session when exiting the async context."""
if self.session:
if self.session.closed:
logger.debug("Session is already closed, skipping closure")
elif not self._owns_session:
logger.debug("Session is externally provided; not closing it")
else:
logger.debug("Closing aiohttp session")
try:
await self.session.close()
except Exception as e:
logger.error("Error while closing aiohttp session: %s", e)
@property
def lang(self) -> str:
"""Get the language setting for API requests.
Returns:
str: The current language setting ('nl', 'fr', 'en', 'de').
"""
return self.__lang
@lang.setter
def lang(self, value: str) -> None:
"""Set the language for API requests.
Args:
value (str): The language to use. Must be one of: 'nl', 'fr', 'en', 'de'.
If an invalid value is provided, defaults to 'en'.
"""
if value in ["nl", "fr", "en", "de"]:
self.__lang = value
else:
self.__lang = "en"
def clear_etag_cache(self) -> None:
"""Clear the ETag cache."""
self.etag_cache.clear()
logger.info("ETag cache cleared")
def _refill_tokens(self) -> None:
"""Refill tokens for rate limiting using a token bucket algorithm.
- Standard tokens: Refill rate of 3 tokens/second, max 3 tokens.
- Burst tokens: Refilled only when standard tokens are full, max 5 tokens.
"""
logger.debug("Refilling tokens")
current_time: float = time.time()
elapsed: float = current_time - self.last_request_time
self.last_request_time = current_time
# Refill tokens, 3 tokens per second, cap tokens at 3
self.tokens = min(3, self.tokens + int(elapsed * 3))
# Refill burst tokens only if the request rate is below 3 requests per second
if self.tokens == 3:
self.burst_tokens = min(5, self.burst_tokens + int(elapsed * 3))
async def _handle_rate_limit(self) -> None:
"""Handle rate limiting using a token bucket algorithm.
- Standard tokens: 3 requests/second.
- Burst tokens: Additional 5 requests/second for spikes.
- Waits and refills tokens if both are exhausted.
"""
logger.debug("Handling rate limit")
self._refill_tokens()
if self.tokens < 1:
if self.burst_tokens >= 1:
self.burst_tokens -= 1
else:
logger.warning("Rate limiting active, waiting for tokens")
wait_time = max(0, 1 - (time.time() - self.last_request_time))
await asyncio.sleep(wait_time)
self._refill_tokens()
self.tokens -= 1
else:
self.tokens -= 1
def _add_etag_header(self, method: str) -> dict[str, str]:
"""Add ETag header for the given method if a cached ETag is available.
Args:
method (str): The API endpoint for which the header is being generated.
Returns:
dict[str, str]: A dictionary containing HTTP headers, including the ETag header
if a cached value exists.
"""
headers: dict[str, str] = {"User-Agent": "pyRail (https://github.com/tjorim/pyrail; tielemans.jorim@gmail.com)"}
if method in self.etag_cache:
logger.debug("Adding If-None-Match header with value: %s", self.etag_cache[method])
headers["If-None-Match"] = self.etag_cache[method]
return headers
def _validate_date(self, date: str | None) -> bool:
"""Validate the date format (DDMMYY).
Args:
date (str, optional): The date string to validate. Expected format is DDMMYY,
e.g., '150923' for September 15, 2023.
Returns:
bool: True if the date is valid or None is provided, False otherwise.
"""
if not date:
return True
try:
datetime.strptime(date, "%d%m%y")
return True
except ValueError:
logger.error("Invalid date format. Expected DDMMYY (e.g., 150923 for September 15, 2023), got: %s", date)
return False
def _validate_time(self, time: str | None) -> bool:
"""Validate the time format (HHMM).
Args:
time (str, optional): The time string to validate. Expected format is HHMM,
e.g., '1430' for 2:30 PM.
Returns:
bool: True if the time is valid or None is provided, False otherwise.
"""
if not time:
return True
try:
datetime.strptime(time, "%H%M")
return True
except ValueError:
logger.error("Invalid time format. Expected HHMM (e.g., 1430 for 2:30 PM), got: %s", time)
return False
def _validate_params(self, method: str, params: dict[str, Any] | None = None) -> bool:
"""Validate parameters for a specific iRail API endpoint based on predefined requirements.
Args:
method (str): The API endpoint method to validate parameters for.
params (dict[str, Any], optional): Dictionary of parameters to validate. Defaults to None.
Returns:
bool: True if parameters are valid, False otherwise.
Raises:
No explicit exceptions raised. Uses logging to report validation errors.
Validates the following conditions:
1. Checks if the method is a known endpoint
2. Ensures all required parameters are present
3. Enforces XOR (exclusive OR) parameter logic where applicable
4. Prevents unexpected parameters from being included
Example:
# Validates parameters for a 'get_liveboard' method
is_valid = self.validate_params('get_liveboard', {'station': 'Brussels', 'date': '2025-01-15'})
"""
if method not in self.endpoints:
logger.error("Unknown API endpoint: %s", method)
return False
endpoint = self.endpoints[method]
required = endpoint.get("required", [])
xor = endpoint.get("xor", [])
optional = endpoint.get("optional", [])
params = params or {}
# Validate date and time formats if present
if "date" in params and not self._validate_date(params["date"]):
return False
if "time" in params and not self._validate_time(params["time"]):
return False
# Ensure all required parameters are present
for param in required:
if param not in params or params[param] is None:
logger.error("Missing required parameter: %s for endpoint: %s", param, method)
return False
# Check XOR logic (only one of XOR parameters can be set)
if xor:
xor_values = [params.get(param) is not None for param in xor]
if sum(xor_values) != 1:
logger.error("Exactly one of the XOR parameters %s must be provided for endpoint: %s", xor, method)
return False
# Ensure no unexpected parameters are included
all_params = required + xor + optional
for param in params.keys():
if param not in all_params:
logger.error("Unexpected parameter: %s for endpoint: %s", param, method)
return False
return True
async def _handle_success_response(self, response: ClientResponse, method: str) -> dict[str, Any] | None:
"""Handle a successful API response."""
if "Etag" in response.headers:
self.etag_cache[method] = response.headers["Etag"]
try:
json_data: dict[str, Any] | None = await response.json()
if not json_data:
logger.warning("Empty response received")
return json_data
except ValueError:
logger.error("Failed to parse JSON response")
return None
async def _handle_response(
self, response: ClientResponse, method: str, args: dict[str, Any] | None = None
) -> dict[str, Any] | None:
"""Handle the API response based on status code."""
if response.status == 429:
retry_after: int = int(response.headers.get("Retry-After", 1))
logger.warning("Rate limited, retrying after %d seconds", retry_after)
await asyncio.sleep(retry_after)
return await self._do_request(method, args)
elif response.status == 400:
logger.error("Bad request: %s", await response.text())
return None
elif response.status == 404:
logger.error("Endpoint %s not found, response: %s", method, await response.text())
return None
elif response.status == 200:
return await self._handle_success_response(response, method)
elif response.status == 304:
logger.info("Data not modified, using cached data for method %s", method)
return None
else:
logger.error("Request failed with status code: %s, response: %s", response.status, await response.text())
return None
async def _do_request(self, method: str, args: dict[str, Any] | None = None) -> dict[str, Any] | None:
"""Send an asynchronous request to the specified iRail API endpoint.
This method handles API requests with rate limiting, parameter validation,
and ETag-based caching. It supports conditional requests and manages
various HTTP response scenarios.
Args:
method (str): The iRail API endpoint method to request.
args (dict, optional): Additional query parameters for the request.
Defaults to None.
Returns:
dict or None: Parsed JSON response from the API if successful,
None if the request fails or encounters an error.
Raises:
No explicit exceptions, but logs errors for various failure scenarios.
Notes:
- Implements rate limiting using a token-based mechanism
- Supports ETag-based conditional requests
- Handles rate limit (429) responses with automatic retry
- Logs detailed information about request processing
"""
logger.info("Starting request to endpoint: %s", method)
if self.session is None:
logger.error("Session not initialized. Use 'async with' context manager to initialize the client.")
return None
if not self._validate_params(method, args or {}):
logger.error("Validation failed for method: %s with args: %s", method, args)
return None
async with self.lock:
await self._handle_rate_limit()
# Construct the request URL and parameters
url: str = "https://api.irail.be/{}/".format(method)
params = {"format": "json", "lang": self.lang}
if args:
params.update(args)
request_headers: dict[str, str] = self._add_etag_header(method)
try:
async with self.session.get(url, params=params, headers=request_headers) as response:
return await self._handle_response(response, method, args)
except ClientError as e:
logger.error("Request failed due to an exception: %s", e)
return None
async def get_stations(self) -> StationsApiResponse | None:
"""Retrieve a list of all train stations from the iRail API.
This method fetches the complete list of available train stations without any additional filtering parameters.
Returns:
StationsApiResponse or None: A StationsApiResponse object containing a list of all train stations and their details, or None if the request fails.
Example:
async with iRail() as client:
stations = await client.get_stations()
if stations:
print(f"Total stations: {len(stations)}")
"""
stations_response_dict = await self._do_request("stations")
if stations_response_dict is None:
return None
return StationsApiResponse.from_dict(stations_response_dict)
async def get_liveboard(
self,
station: str | None = None,
id: str | None = None,
date: str | None = None,
time: str | None = None,
arrdep: str = "departure",
alerts: bool = False,
) -> LiveboardApiResponse | None:
"""Retrieve a liveboard for a specific train station.
Asynchronously fetches live departure or arrival information for a given station.
Provide exactly one of 'station' or 'id'.
Args:
station (str): Name of the train station.
id (str): Unique identifier of the train station.
date (str, optional): Date for the liveboard in format 'DDMMYY'. Defaults to current date.
time (str, optional): Time for the liveboard in format 'HHMM'. Defaults to current time.
arrdep (str, optional): Type of board to retrieve. Either 'departure' (default) or 'arrival'.
alerts (bool, optional): Whether to include service alerts. Defaults to False.
Returns:
LiveboardApiResponse or None: A LiveboardApiResponse object containing liveboard information, or None if the request fails.
Example:
async with iRail() as client:
liveboard = await client.get_liveboard(station='Brussels-South')
if liveboard:
print(f"Liveboard for Brussels-South: {liveboard}")
"""
extra_params: dict[str, Any] = {
"station": station,
"id": id,
"date": date,
"time": time,
"arrdep": arrdep,
"alerts": "true" if alerts else "false",
}
liveboard_response_dict = await self._do_request(
"liveboard", {k: v for k, v in extra_params.items() if v is not None}
)
if liveboard_response_dict is None:
return None
return LiveboardApiResponse.from_dict(liveboard_response_dict)
async def get_connections(
self,
from_station: str,
to_station: str,
date: str | None = None,
time: str | None = None,
timesel: str = "departure",
type_of_transport: str = "automatic",
) -> ConnectionsApiResponse | None:
"""Retrieve train connections between two stations using the iRail API.
Args:
from_station (str): Name or ID of the departure station
to_station (str): Name or ID of the arrival station
date (str, optional): Date of travel in format 'DDMMYY' (default: current date)
time (str, optional): Time of travel in format 'HH:MM' (default: current time)
timesel (str, optional): Time selection type, either 'departure' or 'arrival' (default: 'departure')
type_of_transport (str, optional): Type of transport, options include 'automatic', 'trains', 'nointernationaltrains' or 'all' (default: 'automatic')
Returns:
ConnectionsApiResponse or None: A ConnectionsApiResponse object containing connection details, or None if the request fails or no connections are found.
Example:
async with iRail() as client:
connections = await client.get_connections("Antwerpen-Centraal", "Brussel-Centraal")
if connections:
print(f"Connections from Antwerpen-Centraal to Brussel-Centraal: {connections}")
"""
extra_params: dict[str, Any] = {
"from": from_station,
"to": to_station,
"date": date,
"time": time,
"timesel": timesel,
"typeOfTransport": type_of_transport,
}
connections_response_dict = await self._do_request(
"connections", {k: v for k, v in extra_params.items() if v is not None}
)
if connections_response_dict is None:
return None
return ConnectionsApiResponse.from_dict(connections_response_dict)
async def get_vehicle(self, id: str, date: str | None = None, alerts: bool = False) -> VehicleApiResponse | None:
"""Retrieve detailed information about a specific train vehicle.
Args:
id (str): Unique identifier of the train vehicle to retrieve information for.
date (str, optional): Specific date for which vehicle information is requested. Defaults to None (current date).
alerts (bool, optional): Flag to include service alerts for the vehicle. Defaults to False.
Returns:
VehicleApiResponse or None: A VehicleApiResponse object containing vehicle details, or None if the request fails.
Example:
async with iRail() as client:
vehicle_info = await client.get_vehicle("BE.NMBS.IC1832")
"""
extra_params: dict[str, Any] = {"id": id, "date": date, "alerts": "true" if alerts else "false"}
vehicle_response_dict = await self._do_request(
"vehicle", {k: v for k, v in extra_params.items() if v is not None}
)
if vehicle_response_dict is None:
return None
return VehicleApiResponse.from_dict(vehicle_response_dict)
async def get_composition(self, id: str, data: str | None = None) -> CompositionApiResponse | None:
"""Retrieve the composition details of a specific train.
Args:
id (str): The unique identifier of the train for which composition details are requested.
data (str, optional): Additional data parameter to get all raw unfiltered data as iRail fetches it from the NMBS (set to 'all'). Defaults to '' (filtered data).
Returns:
CompositionApiResponse or None: A CompositionApiResponse object containing train composition details, or None if the request fails.
Example:
async with iRail() as client:
composition = await client.get_composition('S51507')
"""
extra_params: dict[str, str | None] = {"id": id, "data": data}
composition_response_dict = await self._do_request(
"composition", {k: v for k, v in extra_params.items() if v is not None}
)
if composition_response_dict is None:
return None
return CompositionApiResponse.from_dict(composition_response_dict)
async def get_disturbances(self, line_break_character: str | None = None) -> DisturbancesApiResponse | None:
"""Retrieve information about current disturbances on the rail network.
Args:
line_break_character (str, optional): A custom character to use for line breaks in the disturbance description. Defaults to ''.
Returns:
DisturbancesApiResponse or None: A DisturbancesApiResponse object containing disturbance information, or None if the request fails or no disturbances are found.
Example:
async with iRail() as client:
disturbances = await client.get_disturbances()
if disturbances:
print(f"Current disturbances: {disturbances}")
"""
extra_params = {"lineBreakCharacter": line_break_character}
disturbances_response_dict = await self._do_request(
"disturbances", {k: v for k, v in extra_params.items() if v is not None}
)
if disturbances_response_dict is None:
return None
return DisturbancesApiResponse.from_dict(disturbances_response_dict)
tjorim-pyrail-4c4ba2c/pyrail/models.py 0000664 0000000 0000000 00000056434 14755342216 0020162 0 ustar 00root root 0000000 0000000 """Module defining data models for the pyrail application."""
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import Any
from mashumaro import field_options
from mashumaro.mixins.orjson import DataClassORJSONMixin
def _timestamp_to_datetime(timestamp: str) -> datetime:
"""Convert an epoch timestamp to a datetime object."""
return datetime.fromtimestamp(int(timestamp), timezone.utc)
def _str_to_bool(strbool: str) -> bool:
"""Convert a string ("0" or "1") to a boolean."""
return strbool == "1"
class DisturbanceType(Enum):
"""Enum for the type of disturbance, either 'disturbance' or 'planned'."""
DISTURBANCE = "disturbance"
PLANNED = "planned"
class OccupancyName(Enum):
"""Enum for the occupancy, either 'low', 'medium', 'high', or 'unknown'."""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
UNKNOWN = "unknown"
class Orientation(Enum):
"""Enum for the orientation of the material type of a train unit, either 'LEFT' or 'RIGHT'."""
LEFT = "LEFT"
RIGHT = "RIGHT"
@dataclass
class ApiResponse(DataClassORJSONMixin):
"""Base class for API responses, including schema version and timestamp."""
version: str # Version of the response schema
timestamp: datetime = field(metadata=field_options(deserialize=_timestamp_to_datetime)) # Timestamp of the response
@dataclass
class StationDetails(DataClassORJSONMixin):
"""Represents a single railway station with location and naming attributes."""
at_id: str = field(metadata=field_options(alias="@id")) # Corresponds to "@id" in the schema
id: str # The (iRail) ID of the station
name: str # Default name of the station
longitude: float = field(metadata=field_options(alias="locationX")) # Longitude of the station
latitude: float = field(metadata=field_options(alias="locationY")) # Latitude of the station
standard_name: str = field(metadata=field_options(alias="standardname")) # Consistent name of the station
@dataclass
class StationsApiResponse(ApiResponse):
"""Holds a list of station objects returned by the 'stations' endpoint."""
stations: list[StationDetails] = field(
metadata=field_options(alias="station"), default_factory=list
) # List of stations information
@dataclass
class VehicleInfo(DataClassORJSONMixin):
"""Represents information about a specific vehicle, including name and location."""
name: str # Name of the vehicle
short_name: str = field(metadata=field_options(alias="shortname")) # Shortened name of the vehicle
number: str # Number of the vehicle
type: str # Type of vehicle (e.g., IC, EC)
longitude: float = field(metadata=field_options(alias="locationX")) # Longitude of the vehicle
latitude: float = field(metadata=field_options(alias="locationY")) # Latitude of the vehicle
at_id: str = field(metadata=field_options(alias="@id")) # ID of the vehicle
@dataclass
class PlatformInfo(DataClassORJSONMixin):
"""Details about the platform, such as name and whether it is the normal one."""
name: str # Platform name
normal: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether it is the normal platform
@dataclass
class Occupancy(DataClassORJSONMixin):
"""Represents occupancy details for a specific departure."""
at_id: str = field(metadata=field_options(alias="@id")) # Identifier for the occupancy level
name: OccupancyName # Occupancy level (e.g., low, high)
@dataclass
class LiveboardDeparture(DataClassORJSONMixin):
"""Details of a single departure in the liveboard response."""
id: str # ID of the departure
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
time: datetime = field(metadata=field_options(deserialize=_timestamp_to_datetime)) # Departure time (timestamp)
delay: int # Delay in seconds
canceled: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the departure is canceled
left: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the train has left
is_extra: bool = field(
metadata=field_options(alias="isExtra", deserialize=_str_to_bool)
) # Whether the train is extra
vehicle: str # Vehicle identifier
vehicle_info: VehicleInfo = field(metadata=field_options(alias="vehicleinfo")) # Vehicle details
platform: str # Platform name
platform_info: PlatformInfo = field(metadata=field_options(alias="platforminfo")) # Detailed platform info
occupancy: Occupancy # Occupancy level
departure_connection: str = field(metadata=field_options(alias="departureConnection")) # Departure connection link
@dataclass
class LiveboardArrival(DataClassORJSONMixin):
"""Details of a single arrival in the liveboard response."""
id: str # ID of the arrival
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
time: datetime = field(metadata=field_options(deserialize=_timestamp_to_datetime)) # Arrival time (timestamp)
delay: int # Delay in seconds
canceled: bool # Whether the arrival is canceled
arrived: bool # Whether the train has arrived
is_extra: bool = field(metadata=field_options(alias="isExtra")) # Whether the train is extra
vehicle: str # Vehicle identifier
vehicle_info: VehicleInfo = field(metadata=field_options(alias="vehicleinfo")) # Vehicle details
platform: str # Platform name
platform_info: PlatformInfo = field(metadata=field_options(alias="platforminfo")) # Detailed platform info
departure_connection: str = field(metadata=field_options(alias="departureConnection")) # Departure connection link
@dataclass
class LiveboardApiResponse(ApiResponse):
"""Represents a liveboard response containing station details and departure/arrival information."""
station: str # Name of the station
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
departures: list[LiveboardDeparture] | None = field(default=None) # Departures information
arrivals: list[LiveboardArrival] | None = field(default=None) # Arrivals information
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Pre-deserialization hook to safely flatten departures and arrivals."""
# Safely flatten departures
if "departures" in d and d["departures"] is not None:
d["departures"] = d["departures"].get("departure", [])
else:
d["departures"] = None # Set to None if missing or null
# Safely flatten arrivals
if "arrivals" in d and d["arrivals"] is not None:
d["arrivals"] = d["arrivals"].get("arrival", [])
else:
d["arrivals"] = None # Set to None if missing or null
return d
@dataclass
class ConnectionStop(DataClassORJSONMixin):
"""Represents a single stop in a journey for connections."""
id: str # Stop ID
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
scheduled_arrival_time: datetime = field(
metadata=field_options(alias="scheduledArrivalTime", deserialize=_timestamp_to_datetime)
) # Scheduled arrival time
arrival_canceled: bool = field(
metadata=field_options(alias="arrivalCanceled", deserialize=_str_to_bool)
) # Arrival cancellation status
arrived: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Arrival status
scheduled_departure_time: datetime = field(
metadata=field_options(alias="scheduledDepartureTime", deserialize=_timestamp_to_datetime)
) # Scheduled departure time
arrival_delay: int = field(metadata=field_options(alias="arrivalDelay")) # Arrival delay
departure_delay: int = field(metadata=field_options(alias="departureDelay")) # Departure delay
departure_canceled: bool = field(
metadata=field_options(alias="departureCanceled", deserialize=_str_to_bool)
) # Departure cancellation status
left: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Departure status
is_extra_stop: bool = field(
metadata=field_options(alias="isExtraStop", deserialize=_str_to_bool)
) # Whether the stop is an extra one
platform: str # Platform name
platform_info: PlatformInfo = field(metadata=field_options(alias="platforminfo")) # Detailed platform info
@dataclass
class Direction(DataClassORJSONMixin):
"""Represents the direction of a train connection."""
name: str # Direction name
@dataclass
class ConnectionDeparture(DataClassORJSONMixin):
"""Details of a single departure in the connections response."""
delay: int # Delay in seconds
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
time: datetime = field(metadata=field_options(deserialize=_timestamp_to_datetime)) # Departure time (timestamp)
vehicle: str # Vehicle identifier
vehicle_info: VehicleInfo = field(metadata=field_options(alias="vehicleinfo")) # Vehicle details
platform: str # Platform name
platform_info: PlatformInfo = field(metadata=field_options(alias="platforminfo")) # Detailed platform info
canceled: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the departure is canceled
departure_connection: str = field(metadata=field_options(alias="departureConnection")) # Departure connection link
direction: Direction # Direction of the connection
left: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the train has left
walking: bool = field(
metadata=field_options(deserialize=_str_to_bool)
) # Indicates if the connection requires walking
occupancy: Occupancy # Occupancy level
stops: list[ConnectionStop] = field(default_factory=list) # List of stop along the journey
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Extract 'stop' list from 'stops' before deserialization."""
d["stops"] = d["stops"]["stop"]
return d
@dataclass
class ConnectionArrival(DataClassORJSONMixin):
"""Details of a single arrival, including timing, delay, and vehicle information."""
delay: int # Delay in seconds
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
time: datetime = field(metadata=field_options(deserialize=_timestamp_to_datetime)) # Arrival time (timestamp)
vehicle: str # Vehicle identifier
vehicle_info: VehicleInfo = field(metadata=field_options(alias="vehicleinfo")) # Vehicle details
platform: str # Platform name
platform_info: PlatformInfo = field(metadata=field_options(alias="platforminfo")) # Detailed platform info
canceled: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the arrival is canceled
direction: Direction # Direction of the connection
arrived: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the train has arrived
walking: bool = field(
metadata=field_options(deserialize=_str_to_bool)
) # Indicates if the connection requires walking
departure_connection: str = field(metadata=field_options(alias="departureConnection")) # Departure connection link
@dataclass
class Via(DataClassORJSONMixin):
"""Represents a single via station in a train connection."""
id: str # Via ID
arrival: ConnectionArrival
departure: ConnectionDeparture
timebetween: int # Time between arrival and departure (assuming in seconds)
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
vehicle: str # Vehicle identifier
vehicle_info: VehicleInfo = field(metadata=field_options(alias="vehicleinfo")) # Vehicle details
@dataclass
class Remark(DataClassORJSONMixin):
"""Represents a single remark for a train connection, including type and content."""
id: str # Remark ID
# Unsure about the content of a remark, so using a generic type for now
content: str # Remark content
@dataclass
class Alert(DataClassORJSONMixin):
"""Represents a single alert for a train connection, including type and content."""
id: str # Alert ID
header: str # Alert header
description: str # Alert description
lead: str # Alert lead
start_time: datetime = field(
metadata=field_options(alias="startTime", deserialize=_timestamp_to_datetime)
) # Start time of the alert
end_time: datetime = field(
metadata=field_options(alias="endTime", deserialize=_timestamp_to_datetime)
) # End time of the alert
link: str | None = field(default=None) # Link to more information
@dataclass
class ConnectionDetails(DataClassORJSONMixin):
"""Details of a single connection, including departure and arrival information."""
id: str # Connection ID
departure: ConnectionDeparture # Departure details
arrival: ConnectionArrival # Arrival details
duration: int # Duration of the connection in minutes
remarks: list[Remark] = field(default_factory=list) # List of remarks for the connection
alerts: list[Alert] = field(default_factory=list) # List of alerts for the connection
vias: list[Via] | None = field(default=None) # List of via details
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Flatten the structure of the 'connections' response by extracting lists of remarks, alerts, and optionally flatten vias before deserialization."""
# Extract 'remark' and 'alert' list from 'remarks' and 'alerts' before deserialization.
d["remarks"] = d["remarks"]["remark"]
d["alerts"] = d["alerts"]["alert"]
# Safely flatten vias
if "vias" in d and d["vias"] is not None:
d["vias"] = d["vias"].get("via", [])
else:
d["vias"] = None # Set to None if missing or null
return d
@dataclass
class ConnectionsApiResponse(ApiResponse):
"""Holds a list of connections returned by the connections endpoint."""
connections: list[ConnectionDetails] = field(
metadata=field_options(alias="connection"), default_factory=list
) # List of connections
@dataclass
class VehicleStop(DataClassORJSONMixin):
"""Represents a single stop in a journey for vehicles."""
id: str # Stop ID
station: str # Station name
station_info: StationDetails = field(metadata=field_options(alias="stationinfo")) # Detailed station info
time: datetime = field(
metadata=field_options(deserialize=_timestamp_to_datetime)
) # Scheduled stop time (timestamp)
platform: str # Platform name
platform_info: PlatformInfo = field(metadata=field_options(alias="platforminfo")) # Detailed platform info
scheduled_departure_time: datetime = field(
metadata=field_options(alias="scheduledDepartureTime", deserialize=_timestamp_to_datetime)
) # Scheduled departure time
scheduled_arrival_time: datetime = field(
metadata=field_options(alias="scheduledArrivalTime", deserialize=_timestamp_to_datetime)
) # Scheduled arrival time
delay: int # Delay in minutes
canceled: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the stop is canceled
departure_delay: int = field(metadata=field_options(alias="departureDelay")) # Departure delay
departure_canceled: bool = field(
metadata=field_options(alias="departureCanceled", deserialize=_str_to_bool)
) # Departure cancellation status
arrival_delay: int = field(metadata=field_options(alias="arrivalDelay")) # Arrival delay
arrival_canceled: bool = field(
metadata=field_options(alias="arrivalCanceled", deserialize=_str_to_bool)
) # Arrival cancellation status
left: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the train has left
arrived: bool = field(metadata=field_options(deserialize=_str_to_bool)) # Whether the train has arrived
is_extra_stop: bool = field(
metadata=field_options(alias="isExtraStop", deserialize=_str_to_bool)
) # Whether this is an extra stop
occupancy: Occupancy | None = field(default=None) # Occupancy level, not present in last stop
departure_connection: str | None = field(
default=None, metadata=field_options(alias="departureConnection")
) # Departure connection link, not present in the last stop
@dataclass
class VehicleApiResponse(ApiResponse):
"""Provides detailed data about a particular vehicle, including a list of its stops."""
vehicle: str # Vehicle identifier
vehicle_info: VehicleInfo = field(metadata=field_options(alias="vehicleinfo")) # Vehicle information
stops: list[VehicleStop] = field(default_factory=list) # List of stop details
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Extract 'stop' list from 'stops' before deserialization."""
d["stops"] = d["stops"]["stop"]
return d
@dataclass
class MaterialType(DataClassORJSONMixin):
"""Represents the material type of a train unit."""
parent_type: str # Parent material type
sub_type: str # Sub material type
orientation: Orientation # Orientation of the material type
@dataclass
class Unit(DataClassORJSONMixin):
"""Represents a single train unit, including its type and location."""
id: str # Unit ID
material_type: MaterialType = field(metadata=field_options(alias="materialType")) # Material type of the unit
has_toilets: bool = field(
metadata=field_options(alias="hasToilets", deserialize=_str_to_bool)
) # Whether the unit has toilets
has_second_class_outlets: bool = field(
metadata=field_options(alias="hasSecondClassOutlets", deserialize=_str_to_bool)
) # Whether the unit has power outlets in second class
has_first_class_outlets: bool = field(
metadata=field_options(alias="hasFirstClassOutlets", deserialize=_str_to_bool)
) # Whether the unit has power outlets in first class
has_heating: bool = field(
metadata=field_options(alias="hasHeating", deserialize=_str_to_bool)
) # Whether the unit has heating
has_airco: bool = field(
metadata=field_options(alias="hasAirco", deserialize=_str_to_bool)
) # Whether the unit has air conditioning
traction_type: str = field(metadata=field_options(alias="tractionType")) # Traction type of the unit
can_pass_to_next_unit: bool = field(
metadata=field_options(alias="canPassToNextUnit", deserialize=_str_to_bool)
) # Whether the unit can pass to the next
seats_first_class: int = field(metadata=field_options(alias="seatsFirstClass")) # Number of seats in first class
seats_coupe_first_class: int = field(
metadata=field_options(alias="seatsCoupeFirstClass")
) # Number of seats in coupe in first class
standing_places_first_class: int = field(
metadata=field_options(alias="standingPlacesFirstClass")
) # Number of standing places in first class
seats_second_class: int = field(metadata=field_options(alias="seatsSecondClass")) # Number of seats in second class
seats_coupe_second_class: int = field(
metadata=field_options(alias="seatsCoupeSecondClass")
) # Number of seats in coupe in second class
standing_places_second_class: int = field(
metadata=field_options(alias="standingPlacesSecondClass")
) # Number of standing places in second class
length_in_meter: int = field(metadata=field_options(alias="lengthInMeter")) # Length of the unit in meters
has_semi_automatic_interior_doors: bool = field(
metadata=field_options(alias="hasSemiAutomaticInteriorDoors", deserialize=_str_to_bool)
) # Whether the unit has semi-automatic interior doors
traction_position: int = field(metadata=field_options(alias="tractionPosition")) # Traction position of the unit
has_prm_section: bool = field(
metadata=field_options(alias="hasPrmSection", deserialize=_str_to_bool)
) # Whether the unit has a PRM section
has_priority_places: bool = field(
metadata=field_options(alias="hasPriorityPlaces", deserialize=_str_to_bool)
) # Whether the unit has priority places
has_bike_section: bool = field(
metadata=field_options(alias="hasBikeSection", deserialize=_str_to_bool)
) # Whether the unit has a bike section
@dataclass
class SegmentComposition(DataClassORJSONMixin):
"""Describes a collection of train units and related metadata."""
source: str # Source of the composition
units: list[Unit] = field(default_factory=list) # List of units
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Extract 'unit' list from 'units' before deserialization."""
d["units"] = d["units"]["unit"]
return d
@dataclass
class Segment(DataClassORJSONMixin):
"""Defines a single segment within a journey, including composition details."""
id: str # ID of the segment
origin: StationDetails # Origin station information
destination: StationDetails # Destination station information
composition: SegmentComposition # Composition details of the segment
@dataclass
class CompositionApiResponse(ApiResponse):
"""Encapsulates the response containing composition details of a specific train."""
composition: list[Segment] = field(default_factory=list) # Composition details of the train
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Pre-deserialization hook to safely flatten composition segments."""
d["composition"] = d["composition"]["segments"]["segment"]
return d
@dataclass
class DescriptionLink(DataClassORJSONMixin):
"""Represents a single link within a disturbance description."""
id: str # Link ID
link: str # URL of the link
text: str # Text displayed for the link
@dataclass
class Disturbance(DataClassORJSONMixin):
"""Represents a railway system disturbance, including description and metadata."""
id: str # ID of the disturbance
title: str # Title of the disturbance
description: str # Description of the disturbance
type: DisturbanceType # Type of disturbance (e.g., "disturbance", "planned")
link: str # Link to more information
timestamp: datetime = field(
metadata=field_options(deserialize=_timestamp_to_datetime)
) # Timestamp of the disturbance
richtext: str # Rich-text description (HTML-like)
description_links: list[DescriptionLink] = field(
metadata=field_options(alias="descriptionLinks"), default_factory=list
) # List of description links
@classmethod
def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]:
"""Extract 'descriptionLink' list from 'descriptionLinks' before deserialization."""
d["descriptionLinks"] = d["descriptionLinks"]["descriptionLink"]
return d
@dataclass
class DisturbancesApiResponse(ApiResponse):
"""Encapsulates multiple disturbances returned by the disturbances endpoint."""
disturbances: list[Disturbance] = field(
metadata=field_options(alias="disturbance"), default_factory=list
) # List of disturbances
tjorim-pyrail-4c4ba2c/pyrail/py.typed 0000664 0000000 0000000 00000000000 14755342216 0017776 0 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/tests/ 0000775 0000000 0000000 00000000000 14755342216 0016153 5 ustar 00root root 0000000 0000000 tjorim-pyrail-4c4ba2c/tests/test_irail.py 0000664 0000000 0000000 00000050621 14755342216 0020670 0 ustar 00root root 0000000 0000000 """Unit tests for the iRail API wrapper."""
from datetime import datetime, timedelta, timezone
from unittest.mock import AsyncMock, patch
from aiohttp import ClientSession
import pytest
from pyrail.irail import iRail
from pyrail.models import (
Alert,
ApiResponse,
CompositionApiResponse,
ConnectionDetails,
ConnectionsApiResponse,
Disturbance,
DisturbancesApiResponse,
DisturbanceType,
LiveboardApiResponse,
LiveboardDeparture,
Occupancy,
PlatformInfo,
StationDetails,
StationsApiResponse,
VehicleApiResponse,
VehicleInfo,
_str_to_bool,
_timestamp_to_datetime,
)
@pytest.mark.asyncio
@patch("pyrail.irail.ClientSession.get")
async def test_successful_request(mock_get):
"""Test a successful API request by mocking the iRail response."""
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = AsyncMock(return_value={"data": "some_data"})
mock_get.return_value.__aenter__.return_value = mock_response
async with iRail() as api:
assert api.session is not None
response = await api._do_request("stations")
mock_get.assert_called_once_with(
"https://api.irail.be/stations/",
params={"format": "json", "lang": "en"},
headers={"User-Agent": "pyRail (https://github.com/tjorim/pyrail; tielemans.jorim@gmail.com)"},
)
assert response == {"data": "some_data"}
assert mock_response.status == 200
@pytest.mark.asyncio
async def test_irail_context_manager():
"""Ensure that the async context manager sets up and tears down the session properly."""
async with iRail() as irail:
assert irail.session is not None
assert isinstance(irail.session, ClientSession)
@pytest.mark.asyncio
async def test_get_stations():
"""Test the get_stations endpoint.
Verifies that:
- The response is not None
- The response is a dictionary
- The response contains a 'station' key
- The station list is non-empty
"""
async with iRail() as api:
stations = await api.get_stations()
# Ensure the response is not None
assert stations is not None, "The response should not be None"
# Validate that the response is a StationsApiResponse object
assert isinstance(stations, StationsApiResponse), "Expected the response to be a StationsApiResponse object"
# Validate the structure of station data
station_list = stations.stations
assert isinstance(station_list, list), "Expected 'station' to be a list"
assert len(station_list) > 0, "Expected at least one station in the response"
assert isinstance(station_list[0], StationDetails), "Expected the first station to be a StationDetails object"
@pytest.mark.asyncio
async def test_get_liveboard():
"""Test the get_liveboard endpoint.
Verifies that:
- The response is not None
- The response is a LiveboardApiResponse object
- The response contains a 'departures' key
- The departure list is non-empty
"""
async with iRail() as api:
liveboard = await api.get_liveboard("Brussels-Central")
# Ensure the response is not None
assert liveboard is not None, "The response should not be None"
# Validate that the response is a LiveboardApiResponse object
assert isinstance(liveboard, LiveboardApiResponse), "Expected response to be a dictionary"
# Validate the structure of departure data
departure_list = liveboard.departures
assert isinstance(departure_list, list), "Expected 'departure' to be a list"
assert len(departure_list) > 0, "Expected at least one departure in the response"
assert isinstance(departure_list[0], LiveboardDeparture), (
"Expected the first departure to be a LiveboardDeparture object"
)
# Test VehicleInfo dataclass
assert isinstance(departure_list[0].vehicle_info, VehicleInfo), (
"Expected vehicle_info to be a VehicleInfo object"
)
@pytest.mark.asyncio
async def test_get_connections():
"""Test the get_connections endpoint.
Verifies that:
- The response is not None
- The response is a ConnectionsApiResponse object
- The response contains a 'connections' key
- The connection list is non-empty
"""
async with iRail() as api:
connections = await api.get_connections("Antwerpen-Centraal", "Brussel-Centraal")
# Ensure the response is not None
assert connections is not None, "The response should not be None"
# Validate that the response is a ConnectionsApiResponse object
assert isinstance(connections, ConnectionsApiResponse), "Expected response to be a dictionary"
# Validate the structure of connection data
connection_list = connections.connections
assert isinstance(connection_list, list), "Expected 'connection' to be a list"
assert len(connection_list) > 0, "Expected at least one connection in the response"
assert isinstance(connection_list[0], ConnectionDetails), (
"Expected the first connection to be a ConnectionDetails object"
)
@pytest.mark.asyncio
async def test_get_vehicle():
"""Test the get_vehicle endpoint.
Verifies that:
- The response is not None
- The response is a dictionary
- The response contains a 'vehicle' key
- The vehicle list is non-empty
"""
async with iRail() as api:
vehicle = await api.get_vehicle("IC538")
assert vehicle is not None, "The response should not be None"
assert isinstance(vehicle, VehicleApiResponse), "Expected response to be a VehicleApiResponse object"
assert isinstance(vehicle.vehicle_info, VehicleInfo), "Expected vehicle_info to be a VehicleInfo object"
assert isinstance(vehicle.stops, list), "Expected 'stop' to be a list"
assert len(vehicle.stops) > 0, "Expected at least one stop"
if len(vehicle.stops) > 0:
stop = vehicle.stops[0]
assert isinstance(stop.platform_info, PlatformInfo), "Expected platform_info to be a PlatformInfo object"
assert isinstance(stop.occupancy, Occupancy), "Expected occupancy to be an Occupancy object"
@pytest.mark.asyncio
async def test_get_composition():
"""Test the get_composition endpoint.
Verifies that:
- The response is not None
- The response is a CompositionApiResponse object
- The response contains a 'composition' key
- The composition segments list is non-empty
- The segment has valid attributes
- The composition units list is non-empty
- The unit has valid attributes
"""
async with iRail() as api:
composition = await api.get_composition("IC538")
assert composition is not None, "The response should not be None"
assert isinstance(composition, CompositionApiResponse), (
"Expected response to be a CompositionApiResponse object"
)
# Test segments structure
segments = composition.composition
assert isinstance(segments, list), "Expected 'segments' to be a list"
assert len(segments) > 0, "Expected 'number' to be a non-negative integer"
if len(segments) > 0:
segment = segments[0]
assert isinstance(segment.origin, StationDetails), "Expected origin to be a StationDetails object"
assert isinstance(segment.destination, StationDetails), "Expected destination to be a StationDetails object"
# Test units in composition
units = segment.composition.units
assert len(units) > 0, "Expected 'number' to be a non-negative integer"
if len(units) > 0:
unit = units[0]
assert isinstance(unit.has_toilets, bool), "Expected 'has_toilets' to be a boolean"
assert isinstance(unit.seats_first_class, int), "Expected 'seats_first_class' to be an integer"
assert isinstance(unit.length_in_meter, int), "Expected 'length_in_meter' to be an integer"
@pytest.mark.asyncio
async def test_get_disturbances():
"""Test the get_disturbances endpoint.
Verifies that:
- The response is not None
- The response is a DisturbancesApiResponse object
- The response contains a 'disturbances' key
- The disturbances list is non-empty
- The disturbance has valid attributes
"""
async with iRail() as api:
disturbances = await api.get_disturbances()
assert disturbances is not None, "The response should not be None"
assert isinstance(disturbances, DisturbancesApiResponse), (
"Expected response to be a DisturbancesApiResponse object"
)
assert isinstance(disturbances.disturbances, list), "Expected 'disturbances' to be a list"
# Test disturbance attributes
if len(disturbances.disturbances) > 0:
disturbance = disturbances.disturbances[0]
assert isinstance(disturbance.title, str), "Expected 'title' to be a string"
assert isinstance(disturbance.description, str), "Expected 'description' to be a string"
assert disturbance.type in DisturbanceType, "Expected 'type' to be 'disturbance' or 'planned'"
@pytest.mark.asyncio
async def test_date_time_validation():
"""Test date and time format validation."""
async with iRail() as api:
# Valid date examples
assert api._validate_date("150923") # September 15, 2023
assert api._validate_date("010124") # January 1, 2024
assert api._validate_date(None) # None is valid (uses current date)
assert api._validate_date("290224") # Leap year 2024
# Invalid date examples
assert not api._validate_date("320923") # Invalid day
assert not api._validate_date("151323") # Invalid month
assert not api._validate_date("abcdef") # Not numeric
assert not api._validate_date("15092023") # Too long
assert not api._validate_date("0") # Too short
assert not api._validate_date("290223") # Invalid leap year 2023
# Valid time examples
assert api._validate_time("1430") # 2:30 PM
assert api._validate_time("0000") # Midnight
assert api._validate_time("2359") # 11:59 PM
assert api._validate_time(None) # None is valid (uses current time)
assert api._validate_time("0001") # 12:01 AM
# Invalid time examples
assert not api._validate_time("2460") # Invalid hour
assert not api._validate_time("2361") # Invalid minute
assert not api._validate_time("abcd") # Not numeric
assert not api._validate_time("143000") # Too long
assert not api._validate_time("1") # Too short
@pytest.mark.asyncio
async def test_liveboard_with_date_time():
"""Test liveboard request with date and time parameters."""
async with iRail() as api:
# Valid date/time
result = await api.get_liveboard(
station="Brussels-Central",
date=datetime.now().strftime("%d%m%y"),
time="1430", # 2:30 PM
)
assert result is not None
# Test with future date
result = await api.get_liveboard(
station="Brussels-Central",
date=(datetime.now() + timedelta(days=1)).strftime("%d%m%y"),
)
assert result is not None
# Invalid date
result = await api.get_liveboard(
station="Brussels-Central",
date="320923", # Invalid day 32
)
assert result is None
# Invalid time
result = await api.get_liveboard(
station="Brussels-Central",
time="2460", # Invalid hour 24
)
assert result is None
@pytest.mark.asyncio
async def test_error_handling():
"""Test error handling for various API endpoints with invalid data.
Verifies that:
- The response is None for invalid data
"""
async with iRail() as api:
# Test with invalid vehicle ID
vehicle = await api.get_vehicle("INVALID_ID")
assert vehicle is None, "Expected None for invalid vehicle ID"
# Test with invalid station for liveboard
liveboard = await api.get_liveboard("INVALID_STATION")
assert liveboard is None, "Expected None for invalid station"
# Test with invalid train ID for composition
composition = await api.get_composition("INVALID_TRAIN")
assert composition is None, "Expected None for invalid train ID"
# Test with invalid station for connections
connections = await api.get_connections("InvalidStation1", "InvalidStation2")
assert connections is None, "Expected None for invalid stations"
@pytest.mark.asyncio
async def test_timestamp_to_datetime():
"""Test the timestamp_to_datetime function."""
# Test valid timestamps
assert _timestamp_to_datetime("1705593600") == datetime(
2024, 1, 18, 16, 0, tzinfo=timezone.utc
) # 2024-01-18 16:00:00
assert _timestamp_to_datetime("0") == datetime(1970, 1, 1, 0, 0, tzinfo=timezone.utc) # Unix epoch
@pytest.mark.asyncio
async def test_timestamp_field_deserialization():
"""Test timestamp field deserialization in various models."""
# Test ApiResponse timestamp
api_response = ApiResponse.from_dict({"version": "1.0", "timestamp": "1705593600"})
assert api_response.timestamp == datetime(2024, 1, 18, 16, 0, tzinfo=timezone.utc)
# Test LiveboardDeparture time
departure = LiveboardDeparture.from_dict(
{
"id": "0",
"station": "Brussels-South/Brussels-Midi",
"stationinfo": {
"@id": "http://irail.be/stations/NMBS/008814001",
"id": "BE.NMBS.008814001",
"name": "Brussels-South/Brussels-Midi",
"locationX": "4.336531",
"locationY": "50.835707",
"standardname": "Brussel-Zuid/Bruxelles-Midi",
},
"time": "1705593600",
"delay": "0",
"canceled": "0",
"left": "0",
"isExtra": "0",
"vehicle": "BE.NMBS.EC9272",
"vehicleinfo": {
"name": "BE.NMBS.EC9272",
"shortname": "EC 9272",
"number": "9272",
"type": "EC",
"locationX": "0",
"locationY": "0",
"@id": "http://irail.be/vehicle/EC9272",
},
"platform": "23",
"platforminfo": {"name": "23", "normal": "1"},
"occupancy": {"@id": "http://api.irail.be/terms/low", "name": "low"},
"departureConnection": "http://irail.be/connections/8821006/20250106/EC9272",
}
)
assert departure.time == datetime(2024, 1, 18, 16, 0, tzinfo=timezone.utc)
# Test Alert start_time and end_time
alert = Alert.from_dict(
{
"id": "0",
"header": "Anvers-Central / Antwerpen-Centraal - Anvers-Berchem / Antwerpen-Berchem",
"description": "During the weekends, from 4 to 19/01 Infrabel is working on the track. The departure times of this train change. The travel planner takes these changes into account.",
"lead": "During the weekends, from 4 to 19/01 Infrabel is working on the track",
"startTime": "1705593600",
"endTime": "1705597200",
}
)
assert alert.start_time == datetime(2024, 1, 18, 16, 0, tzinfo=timezone.utc)
assert alert.end_time == datetime(2024, 1, 18, 17, 0, tzinfo=timezone.utc)
# Test Disturbance timestamp
disturbance = Disturbance.from_dict(
{
"id": "1",
"title": "Mouscron / Moeskroen - Lille Flandres (FR)",
"description": "On weekdays from 6 to 17/01 works will take place on the French rail network.An SNCB bus replaces some IC trains Courtrai / Kortrijk - Mouscron / Moeskroen - Lille Flandres (FR) between Mouscron / Moeskroen and Lille Flandres (FR).The travel planner takes these changes into account.Meer info over de NMBS-bussen (FAQ)En savoir plus sur les bus SNCB (FAQ)Où prendre mon bus ?Waar is mijn bushalte?",
"type": "planned",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"timestamp": "1705593600",
"richtext": "On weekdays from 6 to 17/01 works will take place on the French rail network.An SNCB bus replaces some IC trains Courtrai / Kortrijk - Mouscron / Moeskroen - Lille Flandres (FR) between Mouscron / Moeskroen and Lille Flandres (FR).The travel planner takes these changes into account.
Meer info over de NMBS-bussen (FAQ)
En savoir plus sur les bus SNCB (FAQ)
Où prendre mon bus ?
Waar is mijn bushalte?",
"descriptionLinks": {
"number": "4",
"descriptionLink": [
{
"id": "0",
"link": "https://www.belgiantrain.be/nl/support/faq/faq-routes-schedules/faq-bus",
"text": "Meer info over de NMBS-bussen (FAQ)",
},
{
"id": "1",
"link": "https://www.belgiantrain.be/fr/support/faq/faq-routes-schedules/faq-bus",
"text": "En savoir plus sur les bus SNCB (FAQ)",
},
{
"id": "2",
"link": "https://www.belgianrail.be/jp/download/brail_him/1736172333792_FR_2501250_S.pdf",
"text": "Où prendre mon bus ?",
},
{
"id": "3",
"link": "https://www.belgianrail.be/jp/download/brail_him/1736172333804_NL_2501250_S.pdf",
"text": "Waar is mijn bushalte?",
},
],
},
}
)
assert disturbance.timestamp == datetime(2024, 1, 18, 16, 0, tzinfo=timezone.utc)
@pytest.mark.asyncio
async def test_str_to_bool():
"""Test the str_to_bool function that converts string values to boolean."""
# Test valid inputs
assert _str_to_bool("1") is True, "String '1' should convert to True"
assert _str_to_bool("0") is False, "String '0' should convert to False"
@pytest.mark.asyncio
async def test_boolean_field_deserialization():
"""Test the deserialization of boolean fields in models."""
# Test PlatformInfo boolean field
platform = PlatformInfo.from_dict({"name": "1", "normal": "1"})
assert platform.normal is True, "Platform normal field should be True when '1'"
platform = PlatformInfo.from_dict({"name": "1", "normal": "0"})
assert platform.normal is False, "Platform normal field should be False when '0'"
# Test LiveboardDeparture multiple boolean fields
departure = LiveboardDeparture.from_dict(
{
"id": "1",
"station": "Brussels",
"stationinfo": {
"@id": "1",
"id": "1",
"name": "Brussels",
"locationX": 4.3517,
"locationY": 50.8503,
"standardname": "Brussels-Central",
},
"time": "1705593600", # Example timestamp
"delay": 0,
"canceled": "1",
"left": "0",
"isExtra": "1",
"vehicle": "BE.NMBS.IC1234",
"vehicleinfo": {
"name": "IC1234",
"shortname": "IC1234",
"number": "1234",
"type": "IC",
"locationX": 4.3517,
"locationY": 50.8503,
"@id": "1",
},
"platform": "1",
"platforminfo": {"name": "1", "normal": "1"},
"occupancy": {"@id": "http://api.irail.be/terms/low", "name": "low"},
"departureConnection": "1",
}
)
# Verify boolean fields are correctly deserialized
assert departure.canceled is True, "Departure canceled field should be True when '1'"
assert departure.left is False, "Departure left field should be False when '0'"
assert departure.is_extra is True, "Departure is_extra field should be True when '1'"
assert departure.platform_info.normal is True, "Platform normal field should be True when '1'"