pax_global_header00006660000000000000000000000064147553422160014523gustar00rootroot0000000000000052 comment=4c4ba2cfcd104fa7f319e870ea821a925996e394 tjorim-pyrail-4c4ba2c/000077500000000000000000000000001475534221600150115ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/.devcontainer/000077500000000000000000000000001475534221600175505ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/.devcontainer/devcontainer.json000066400000000000000000000026021475534221600231240ustar00rootroot00000000000000// 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/.gitattributes000066400000000000000000000000231475534221600176770ustar00rootroot00000000000000* text=auto eol=lf tjorim-pyrail-4c4ba2c/.github/000077500000000000000000000000001475534221600163515ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/.github/dependabot.yml000066400000000000000000000003151475534221600212000ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" tjorim-pyrail-4c4ba2c/.github/workflows/000077500000000000000000000000001475534221600204065ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/.github/workflows/build.yml000066400000000000000000000006751475534221600222400ustar00rootroot00000000000000name: 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.yml000066400000000000000000000006771475534221600221110ustar00rootroot00000000000000name: 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.yml000066400000000000000000000023231475534221600225770ustar00rootroot00000000000000name: 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.yml000066400000000000000000000006651475534221600221170ustar00rootroot00000000000000name: 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/.gitignore000066400000000000000000000014431475534221600170030ustar00rootroot00000000000000# 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/LICENSE000066400000000000000000000261351475534221600160250ustar00rootroot00000000000000 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.md000066400000000000000000000144201475534221600162710ustar00rootroot00000000000000# 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/000077500000000000000000000000001475534221600166275ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/examples/composition.json000066400000000000000000000472241475534221600220760ustar00rootroot00000000000000{ "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.json000066400000000000000000001677331475534221600220650ustar00rootroot00000000000000{ "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.json000066400000000000000000001724401475534221600222200ustar00rootroot00000000000000{ "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.json000066400000000000000000000214231475534221600214730ustar00rootroot00000000000000{ "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.json000066400000000000000000002130641475534221600234020ustar00rootroot00000000000000{ "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.json000066400000000000000000005742101475534221600213770ustar00rootroot00000000000000{ "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.json000066400000000000000000000511771475534221600211540ustar00rootroot00000000000000{ "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.lock000066400000000000000000002752641475534221600172250ustar00rootroot00000000000000# 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.toml000066400000000000000000000035211475534221600177260ustar00rootroot00000000000000[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/000077500000000000000000000000001475534221600163115ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/pyrail/__init__.py000066400000000000000000000001271475534221600204220ustar00rootroot00000000000000"""Package initialization for pyrail.""" from .irail import iRail __all__ = ["iRail"] tjorim-pyrail-4c4ba2c/pyrail/irail.py000066400000000000000000000556111475534221600177730ustar00rootroot00000000000000"""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.py000066400000000000000000000564341475534221600201620ustar00rootroot00000000000000"""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.typed000066400000000000000000000000001475534221600177760ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/tests/000077500000000000000000000000001475534221600161535ustar00rootroot00000000000000tjorim-pyrail-4c4ba2c/tests/test_irail.py000066400000000000000000000506211475534221600206700ustar00rootroot00000000000000"""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'"