pax_global_header00006660000000000000000000000064144234373720014523gustar00rootroot0000000000000052 comment=2a867437a053ee79a53bd9fb3795088668281756 pygti-0.10.0/000077500000000000000000000000001442343737200127355ustar00rootroot00000000000000pygti-0.10.0/.devcontainer/000077500000000000000000000000001442343737200154745ustar00rootroot00000000000000pygti-0.10.0/.devcontainer/Dockerfile000066400000000000000000000017171442343737200174740ustar00rootroot00000000000000# [Choice] Python version: 3, 3.8, 3.7, 3.6 ARG VARIANT=3 FROM mcr.microsoft.com/vscode/devcontainers/python:${VARIANT} # [Option] Install Node.js ARG INSTALL_NODE="true" ARG NODE_VERSION="lts/*" RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi # [Optional] If your pip requirements rarely change, uncomment this section to add them to the image. # COPY requirements.txt /tmp/pip-tmp/ # RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ # && rm -rf /tmp/pip-tmp # [Optional] Uncomment this section to install additional OS packages. # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # && apt-get -y install --no-install-recommends # [Optional] Uncomment this line to install global node packages. # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1pygti-0.10.0/.devcontainer/base.Dockerfile000066400000000000000000000046461442343737200204110ustar00rootroot00000000000000# [Choice] Python version: 3, 3.8, 3.7, 3.6 ARG VARIANT=3 FROM python:${VARIANT} # [Option] Install zsh ARG INSTALL_ZSH="true" # [Option] Upgrade OS packages to their latest versions ARG UPGRADE_PACKAGES="true" # Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies. ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=$USER_UID COPY .devcontainer/library-scripts/common-debian.sh /tmp/library-scripts/ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # Remove imagemagick due to https://security-tracker.debian.org/tracker/CVE-2019-10131 && apt-get purge -y imagemagick imagemagick-6-common \ # Install common packages, non-root user && bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \ && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts # Setup default python tools in a venv via pipx to avoid conflicts ENV PIPX_HOME=/usr/local/py-utils \ PIPX_BIN_DIR=/usr/local/py-utils/bin ENV PATH=${PATH}:${PIPX_BIN_DIR} COPY .devcontainer/library-scripts/python-debian.sh /tmp/library-scripts/ RUN bash /tmp/library-scripts/python-debian.sh "none" "/usr/local" "${PIPX_HOME}" "${USERNAME}" "false" \ && apt-get clean -y && rm -rf /tmp/library-scripts # [Option] Install Node.js ARG INSTALL_NODE="true" ARG NODE_VERSION="none" ENV NVM_DIR=/usr/local/share/nvm ENV NVM_SYMLINK_CURRENT=true \ PATH=${NVM_DIR}/current/bin:${PATH} COPY .devcontainer/library-scripts/node-debian.sh /tmp/library-scripts/ RUN if [ "$INSTALL_NODE" = "true" ]; then bash /tmp/library-scripts/node-debian.sh "${NVM_DIR}" "${NODE_VERSION}" "${USERNAME}"; fi \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts # [Optional] If your pip requirements rarely change, uncomment this section to add them to the image. # COPY requirements.txt /tmp/pip-tmp/ # RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ # && rm -rf /tmp/pip-tmp # [Optional] Uncomment this section to install additional OS packages. # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # && apt-get -y install --no-install-recommends # [Optional] Uncomment this line to install global node packages. # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 pygti-0.10.0/.devcontainer/devcontainer.json000066400000000000000000000031541442343737200210530ustar00rootroot00000000000000{ "name": "Python 3", "build": { "dockerfile": "Dockerfile", "context": "..", "args": { // Update 'VARIANT' to pick a Python version: 3, 3.6, 3.7, 3.8 "VARIANT": "3", // Options "INSTALL_NODE": "true", "NODE_VERSION": "lts/*" } }, // Set *default* container specific settings.json values on container create. "settings": { "terminal.integrated.shell.linux": "/bin/bash", "python.pythonPath": "/usr/local/bin/python", "python.linting.enabled": true, "python.linting.pylintEnabled": true, "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", "python.formatting.blackPath": "/usr/local/py-utils/bin/black", "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint" }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ "ms-python.python" ] // 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": "pip3 install --user -r requirements.txt", // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. // "remoteUser": "vscode" } pygti-0.10.0/.devcontainer/library-scripts/000077500000000000000000000000001442343737200206255ustar00rootroot00000000000000pygti-0.10.0/.devcontainer/library-scripts/README.md000066400000000000000000000007431442343737200221100ustar00rootroot00000000000000# Warning: Folder contents may be replaced The contents of this folder will be automatically replaced with a file of the same name in the [vscode-dev-containers](https://github.com/microsoft/vscode-dev-containers) repository's [script-library folder](https://github.com/microsoft/vscode-dev-containers/tree/master/script-library) whenever the repository is packaged. To retain your edits, move the file to a different location. You may also delete the files if they are not needed.pygti-0.10.0/.devcontainer/library-scripts/common-debian.sh000066400000000000000000000145061442343737200236770ustar00rootroot00000000000000#!/usr/bin/env bash #------------------------------------------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- # Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag] INSTALL_ZSH=${1:-"true"} USERNAME=${2:-"vscode"} USER_UID=${3:-1000} USER_GID=${4:-1000} UPGRADE_PACKAGES=${5:-"true"} set -e if [ "$(id -u)" -ne 0 ]; then echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' exit 1 fi # Treat a user name of "none" as root if [ "${USERNAME}" = "none" ] || [ "${USERNAME}" = "root" ]; then USERNAME=root USER_UID=0 USER_GID=0 fi # Load markers to see which steps have already run MARKER_FILE="/usr/local/etc/vscode-dev-containers/common" if [ -f "${MARKER_FILE}" ]; then echo "Marker file found:" cat "${MARKER_FILE}" source "${MARKER_FILE}" fi # Ensure apt is in non-interactive to avoid prompts export DEBIAN_FRONTEND=noninteractive # Function to call apt-get if needed apt-get-update-if-needed() { if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then echo "Running apt-get update..." apt-get update else echo "Skipping apt-get update." fi } # Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then apt-get-update-if-needed PACKAGE_LIST="apt-utils \ git \ openssh-client \ gnupg2 \ iproute2 \ procps \ lsof \ htop \ net-tools \ psmisc \ curl \ wget \ rsync \ ca-certificates \ unzip \ zip \ nano \ vim-tiny \ less \ jq \ lsb-release \ apt-transport-https \ dialog \ libc6 \ libgcc1 \ libgssapi-krb5-2 \ libicu[0-9][0-9] \ liblttng-ust0 \ libstdc++6 \ zlib1g \ locales \ sudo \ ncdu \ man-db" # Install libssl1.1 if available if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then PACKAGE_LIST="${PACKAGE_LIST} libssl1.1" fi # Install appropriate version of libssl1.0.x if available LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '') if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then # Debian 9 PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.2" elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then # Ubuntu 18.04, 16.04, earlier PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.0" fi fi echo "Packages to verify are installed: ${PACKAGE_LIST}" apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 ) PACKAGES_ALREADY_INSTALLED="true" fi # Get to latest versions of all packages if [ "${UPGRADE_PACKAGES}" = "true" ]; then apt-get-update-if-needed apt-get -y upgrade --no-install-recommends apt-get autoremove -y fi # Ensure at least the en_US.UTF-8 UTF-8 locale is available. # Common need for both applications and things like the agnoster ZSH theme. if [ "${LOCALE_ALREADY_SET}" != "true" ]; then echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen locale-gen LOCALE_ALREADY_SET="true" fi # Create or update a non-root user to match UID/GID - see https://aka.ms/vscode-remote/containers/non-root-user. if id -u $USERNAME > /dev/null 2>&1; then # User exists, update if needed if [ "$USER_GID" != "$(id -G $USERNAME)" ]; then groupmod --gid $USER_GID $USERNAME usermod --gid $USER_GID $USERNAME fi if [ "$USER_UID" != "$(id -u $USERNAME)" ]; then usermod --uid $USER_UID $USERNAME fi else # Create user groupadd --gid $USER_GID $USERNAME useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME fi # Add add sudo support for non-root user if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME chmod 0440 /etc/sudoers.d/$USERNAME EXISTING_NON_ROOT_USER="${USERNAME}" fi # .bashrc/.zshrc snippet RC_SNIPPET="$(cat << EOF export USER=\$(whoami) export PATH=\$PATH:\$HOME/.local/bin if type code-insiders > /dev/null 2>&1 && ! type code > /dev/null 2>&1; then alias code=code-insiders fi EOF )" # Ensure ~/.local/bin is in the PATH for root and non-root users for bash. (zsh is later) if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then echo "${RC_SNIPPET}" >> /etc/bash.bashrc RC_SNIPPET_ALREADY_ADDED="true" fi # Optionally install and configure zsh if [ "${INSTALL_ZSH}" = "true" ] && [ ! -d "/root/.oh-my-zsh" ] && [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then apt-get-update-if-needed apt-get install -y zsh curl -fsSLo- https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash 2>&1 echo "${RC_SNIPPET}" >> /etc/zsh/zshrc echo -e "DEFAULT_USER=\$USER\nprompt_context(){}" >> /root/.zshrc cp -fR /root/.oh-my-zsh /etc/skel cp -f /root/.zshrc /etc/skel sed -i -e "s/\/root\/.oh-my-zsh/\/home\/\$(whoami)\/.oh-my-zsh/g" /etc/skel/.zshrc if [ "${USERNAME}" != "root" ]; then cp -fR /etc/skel/.oh-my-zsh /etc/skel/.zshrc /home/$USERNAME chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc fi ZSH_ALREADY_INSTALLED="true" fi # Write marker file mkdir -p "$(dirname "${MARKER_FILE}")" echo -e "\ PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\ LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\ EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\ RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\ ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}" echo "Done!"pygti-0.10.0/.devcontainer/library-scripts/node-debian.sh000066400000000000000000000066161442343737200233370ustar00rootroot00000000000000#!/bin/bash #------------------------------------------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- # Syntax: ./node-debian.sh [directory to install nvm] [node version to install (use "none" to skip)] [non-root user] export NVM_DIR=${1:-"/usr/local/share/nvm"} export NODE_VERSION=${2:-"lts/*"} USERNAME=${3:-"vscode"} UPDATE_RC=${4:-"true"} set -e if [ "$(id -u)" -ne 0 ]; then echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' exit 1 fi # Treat a user name of "none" or non-existant user as root if [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then USERNAME=root fi if [ "${NODE_VERSION}" = "none" ]; then export NODE_VERSION= fi # Ensure apt is in non-interactive to avoid prompts export DEBIAN_FRONTEND=noninteractive # Install curl, apt-transport-https, tar, or gpg if missing if ! dpkg -s apt-transport-https curl ca-certificates tar > /dev/null 2>&1 || ! type gpg > /dev/null 2>&1; then if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then apt-get update fi apt-get -y install --no-install-recommends apt-transport-https curl ca-certificates tar gnupg2 fi # Install yarn if type yarn > /dev/null 2>&1; then echo "Yarn already installed." else curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | (OUT=$(apt-key add - 2>&1) || echo $OUT) echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list apt-get update apt-get -y install --no-install-recommends yarn fi # Install the specified node version if NVM directory already exists, then exit if [ -d "${NVM_DIR}" ]; then echo "NVM already installed." if [ "${NODE_VERSION}" != "" ]; then su ${USERNAME} -c "source $NVM_DIR/nvm.sh && nvm install ${NODE_VERSION} && nvm clear-cache" fi exit 0 fi # Run NVM installer as non-root if needed mkdir -p ${NVM_DIR} chown ${USERNAME} ${NVM_DIR} su ${USERNAME} -c "$(cat << EOF set -e # Do not update profile - we'll do this manually export PROFILE=/dev/null curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash source ${NVM_DIR}/nvm.sh if [ "${NODE_VERSION}" != "" ]; then nvm alias default ${NODE_VERSION} fi nvm clear-cache EOF )" 2>&1 if [ "${UPDATE_RC}" = "true" ]; then echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc with NVM scripts..." (cat < /dev/null 2>&1; then echo "Fixing permissions of \"\$NVM_DIR\"..." sudoIf chown -R ${USERNAME}:root \$NVM_DIR else echo "Warning: NVM directory is not owned by ${USERNAME} and sudo is not installed. Unable to correct permissions." fi fi [ -s "\$NVM_DIR/nvm.sh" ] && . "\$NVM_DIR/nvm.sh" [ -s "\$NVM_DIR/bash_completion" ] && . "\$NVM_DIR/bash_completion" EOF ) | tee -a /etc/bash.bashrc >> /etc/zsh/zshrc fi echo "Done!"pygti-0.10.0/.devcontainer/library-scripts/python-debian.sh000066400000000000000000000106231442343737200237240ustar00rootroot00000000000000#!/usr/bin/env bash #------------------------------------------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- # Syntax: ./python-debian.sh [Python Version] [Python intall path] [PIPX_HOME] [non-root user] [Update rc files flag] [install tools] PYTHON_VERSION=${1:-"3.8.3"} PYTHON_INSTALL_PATH=${2:-"/usr/local/python${PYTHON_VERSION}"} export PIPX_HOME=${3:-"/usr/local/py-utils"} USERNAME=${4:-"vscode"} UPDATE_RC=${5:-"true"} INSTALL_PYTHON_TOOLS=${6:-"true"} set -e if [ "$(id -u)" -ne 0 ]; then echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' exit 1 fi # Treat a user name of "none" or non-existant user as root if [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then USERNAME=root fi function updaterc() { if [ "${UPDATE_RC}" = "true" ]; then echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." echo -e "$1" | tee -a /etc/bash.bashrc >> /etc/zsh/zshrc fi } export DEBIAN_FRONTEND=noninteractive # Install python from source if needed if [ "${PYTHON_VERSION}" != "none" ]; then if [ -d "${PYTHON_INSTALL_PATH}" ]; then echo "Path ${PYTHON_INSTALL_PATH} already exists. Assuming Python already installed." else echo "Building Python ${PYTHON_VERSION} from source..." # Install prereqs if missing PREREQ_PKGS="curl ca-certificates tar make build-essential libffi-dev \ libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \ libncurses5-dev libncursesw5-dev xz-utils tk-dev" if ! dpkg -s ${PREREQ_PKGS} > /dev/null 2>&1; then if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then apt-get update fi apt-get -y install --no-install-recommends ${PREREQ_PKGS} fi # Download and build from src mkdir -p /tmp/python-src "${PYTHON_INSTALL_PATH}" cd /tmp/python-src curl -sSL -o /tmp/python-dl.tgz "https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz" tar -xzf /tmp/python-dl.tgz -C "/tmp/python-src" --strip-components=1 ./configure --prefix="${PYTHON_INSTALL_PATH}" --enable-optimizations --with-ensurepip=install make -j 8 make install rm -rf /tmp/python-dl.tgz /tmp/python-src cd /tmp chown -R ${USERNAME} "${PYTHON_INSTALL_PATH}" ln -s ${PYTHON_INSTALL_PATH}/bin/python3 ${PYTHON_INSTALL_PATH}/bin/python ln -s ${PYTHON_INSTALL_PATH}/bin/pip3 ${PYTHON_INSTALL_PATH}/bin/pip ln -s ${PYTHON_INSTALL_PATH}/bin/idle3 ${PYTHON_INSTALL_PATH}/bin/idle ln -s ${PYTHON_INSTALL_PATH}/bin/pydoc3 ${PYTHON_INSTALL_PATH}/bin/pydoc ln -s ${PYTHON_INSTALL_PATH}/bin/python3-config ${PYTHON_INSTALL_PATH}/bin/python-config updaterc "export PATH=${PYTHON_INSTALL_PATH}/bin:\${PATH}" fi fi # If not installing python tools, exit if [ "${INSTALL_PYTHON_TOOLS}" != "true" ]; then echo "Done!" exit 0; fi DEFAULT_UTILS="\ pylint \ flake8 \ autopep8 \ black \ yapf \ mypy \ pydocstyle \ pycodestyle \ bandit \ pipenv \ virtualenv" export PIPX_BIN_DIR=${PIPX_HOME}/bin export PATH=${PYTHON_INSTALL_PATH}/bin:${PIPX_BIN_DIR}:${PATH} mkdir -p ${PIPX_BIN_DIR} chown -R ${USERNAME} ${PIPX_HOME} ${PIPX_BIN_DIR} su ${USERNAME} -c "$(cat << EOF set -e echo "Installing Python tools..." export PIPX_HOME=${PIPX_HOME} export PIPX_BIN_DIR=${PIPX_BIN_DIR} export PYTHONUSERBASE=/tmp/pip-tmp export PIP_CACHE_DIR=/tmp/pip-tmp/cache export PATH=${PATH} pip3 install --disable-pip-version-check --no-warn-script-location --no-cache-dir --user pipx /tmp/pip-tmp/bin/pipx install --pip-args=--no-cache-dir pipx echo "${DEFAULT_UTILS}" | xargs -n 1 /tmp/pip-tmp/bin/pipx install --system-site-packages --pip-args=--no-cache-dir --pip-args=--force-reinstall chown -R ${USERNAME} ${PIPX_HOME} rm -rf /tmp/pip-tmp EOF )" updaterc "export PIPX_HOME=${PIPX_HOME}\nexport PIPX_BIN_DIR=${PIPX_BIN_DIR}\nexport PATH=\${PATH}:\${PIPX_BIN_DIR}" pygti-0.10.0/.github/000077500000000000000000000000001442343737200142755ustar00rootroot00000000000000pygti-0.10.0/.github/release-drafter.yml000066400000000000000000000013671442343737200200740ustar00rootroot00000000000000name-template: v$RESOLVED_VERSION tag-template: v$RESOLVED_VERSION categories: - title: ⚠️ Breaking Changes label: breaking change - title: 🚀 Features label: feature - title: 🐛 Bug Fixes label: fix - title: 🧰 Maintenance label: chore - title: ⬆️ Dependencies label: dependencies - title: 🔁 Continuous Integration label: ci template: | # Changelog $CHANGES --- *Get it on PyPi:* ``` pip install pygti==$RESOLVED_VERSION ``` https://pypi.org/project/pygti/$RESOLVED_VERSION/ version-resolver: major: labels: - 'breaking change' minor: labels: - 'feature' patch: labels: - 'chore' - 'dependencies' - 'fix' - 'ci' default: patch pygti-0.10.0/.github/workflows/000077500000000000000000000000001442343737200163325ustar00rootroot00000000000000pygti-0.10.0/.github/workflows/release-drafter.yml000066400000000000000000000006131442343737200221220ustar00rootroot00000000000000name: Release Drafter on: push: # branches to consider in the event; optional, defaults to all branches: - master jobs: update_release_draft: runs-on: ubuntu-latest steps: # Drafts your next Release notes as Pull Requests are merged into "master" - uses: release-drafter/release-drafter@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} pygti-0.10.0/.gitignore000066400000000000000000000032401442343737200147240ustar00rootroot00000000000000 # Created by https://www.gitignore.io/api/python # Edit at https://www.gitignore.io/?templates=python ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # 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/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # celery beat schedule file celerybeat-schedule # SageMath parsed files *.sage.py # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # Mr Developer .mr.developer.cfg .project .pydevproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # End of https://www.gitignore.io/api/python venv/ .vscode/ .env pygti-0.10.0/.pre-commit-config.yaml000066400000000000000000000005141442343737200172160ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.3.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black rev: 19.3b0 hooks: - id: black - repo: https://github.com/pre-commit/mirrors-isort rev: v4.3.21 hooks: - id: isort pygti-0.10.0/CONTRIBUTING.md000066400000000000000000000033471442343737200151750ustar00rootroot00000000000000# Contribution guidelines Contributing to this project should be as easy and transparent as possible, whether it's: - Reporting a bug - Discussing the current state of the code - Submitting a fix - Proposing new features ## Github is used for everything Github is used to host code, to track issues and feature requests, as well as accept pull requests. Pull requests are the best way to propose changes to the codebase. 1. Fork the repo and create your branch from `master`. 2. If you've changed something, update the documentation. 3. Make sure your code lints (using black). 4. Issue that pull request! ## Any contributions you make will be under the Apache License 2.0 In short, when you submit code changes, your submissions are understood to be under the same [Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/) that covers the project. Feel free to contact the maintainers if that's a concern. ## Report bugs using Github's [issues](../../issues) GitHub issues are used to track public bugs. Report a bug by [opening a new issue](../../issues/new/choose); it's that easy! ## Write bug reports with detail, background, and sample code **Great Bug Reports** tend to have: - A quick summary and/or background - Steps to reproduce - Be specific! - Give sample code if you can. - What you expected would happen - What actually happens - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) People *love* thorough bug reports. I'm not even kidding. ## Use a Consistent Coding Style Use [black](https://github.com/psf/black) to make sure the code follows the style. ## License By contributing, you agree that your contributions will be licensed under its Apache License 2.0. pygti-0.10.0/LICENSE.md000066400000000000000000000261231442343737200143450ustar00rootroot00000000000000 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 [2020] [Tom Schneider] 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. pygti-0.10.0/README.md000066400000000000000000000103441442343737200142160ustar00rootroot00000000000000

HVV Geofox Python Library

Code style: black Hamburg Open Issues Release GTI version: 38 Azure Pipelines status


## About This library is a python wrapper for accessing the geofox api. This api is used to get information about the public transport in Hamburg, Germany. ## How to get the api credentials You have to apply for credentials via the HVV website. You can see their official guide [here](https://www.hvv.de/de/fahrplaene/abruf-fahrplaninfos/datenabruf) (the page is only available in German). They will send you a contract you will have to sign and send back. After about a week, you will receive your api credentials. ## Documentation This library uses the same data types and parameters as specified in the [GTI documentation](https://api-test.geofox.de/gti/doc/index.jsp). It features client side validation of the parameters. ## Installation Install the [package from pypi](https://pypi.org/project/pygti/). ```python pip install pygti ``` ## Usage See the examples on how to use the library at [examples.py](https://github.com/vigonotion/pygti/blob/master/examples.py), and see the [GTI documentation](https://api-test.geofox.de/gti/doc/index.jsp) for in-depth explanation of parameters. There is also a [Glitch example](https://pygti-examples.glitch.me/) available. Try it out and if you want to see how it's done, just [remix the app](https://glitch.com/edit/#!/pygti-examples). A minimal working example is shown below: ```python from pygti.gti import GTI, Auth import asyncio import aiohttp GTI_USER = "" # your api username GTI_PASS = "" # your api password async def main(): async with aiohttp.ClientSession() as session: auth = Auth(session, GTI_USER, GTI_PASS) gti = GTI(auth) ir = await gti.init() # see the examples.py file for more functionality and use of the payloads asyncio.run(main()) ``` > :exclamation: **If using Python 3.8**: Version 3.6.2 of aiohttp uses a different EventLoopPolicy so running this MWE will currently result in an error displayed in the console! It should not affect the functionality. This should be fixed with a newer version of aiohttp. For a workaround look into the [examples.py](https://github.com/vigonotion/pygti/blob/master/examples.py) file. For more information see this [Issue](https://github.com/aio-libs/aiohttp/issues/4324). ## Progress - [x] 1. init - [x] 2. checkName - [x] 3. getRoute - [x] 4. departureList - [x] 5. getTariff - [x] 6. departureCourse - [x] 7. listStations - [x] 8. listLines - [x] 9. getAnnouncements - [x] 10. getIndividualRoute - [x] 11a. getVehicleMap - [x] 11b. getTrackCoordinates - [x] 12. checkPostalCode - [x] 13. getStationInformation - [x] 14. tariffZoneNeighbours - [x] 15. tariffMetaData - [x] 16. singleTicketOptimizer - [x] 17. ticketList ## Developing Some files in this project are generated based on the WADL and XSD schema files from GTI. To generate them, install the dev dependencies and run the script: ```sh pip install -r requirements_dev.txt python script/generate.py ``` ## Contributions are welcome! If you want to contribute to this, please read the [Contribution guidelines](CONTRIBUTING.md) pygti-0.10.0/azure-pipelines.yml000066400000000000000000000015251442343737200165770ustar00rootroot00000000000000trigger: - master - refs/tags/v* pool: vmImage: 'ubuntu-latest' strategy: matrix: Python36: python.version: '3.6' Python38: python.version: '3.8' steps: - task: UsePythonVersion@0 inputs: versionSpec: '$(python.version)' displayName: 'Use Python $(python.version)' - script: pip install tox wheel displayName: 'Install Tox and wheel' - script: tox -e py displayName: 'Run Tox' - script: git diff displayName: 'Diff Before' - script: python setup.py sdist bdist_wheel displayName: 'Create artifact' - task: CopyFiles@2 inputs: contents: dist/** targetFolder: $(Build.ArtifactStagingDirectory) - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' ArtifactName: 'dist' publishLocation: 'Container' - script: git diff displayName: 'Diff After' pygti-0.10.0/examples.py000066400000000000000000000252321442343737200151310ustar00rootroot00000000000000import asyncio import os import sys from datetime import datetime, timedelta import aiohttp from pygti.auth import Auth from pygti.gti import GTI GTI_USER = None GTI_PASS = None try: from dotenv import load_dotenv load_dotenv() GTI_USER = os.getenv("GTI_USER") GTI_PASS = os.getenv("GTI_PASS") except ImportError: pass if not (GTI_USER and GTI_PASS): print("To run the examples, enter your credentials for the GTI API.") GTI_USER = input("GTI Username: ") GTI_PASS = input("GTI Password: ") async def main(): async with aiohttp.ClientSession() as session: auth = Auth(session, GTI_USER, GTI_PASS) gti = GTI(auth) print("Example 1: init()") ir = await gti.init() print(ir) print() print("Example 2: checkName()") cn = await gti.checkName({"theName": {"name": "Wartenau"}}) print(cn) print() print("Example 3: getRoute()") payload = { "language": "de", "start": { "name": "Ritterstraße", "city": "Hamburg", "combinedName": "Ritterstraße", "id": "Master:60904", "type": "STATION", "coordinate": {"x": 10.046196, "y": 53.567617}, }, "dest": { "name": "Wartenau", "city": "Hamburg", "combinedName": "Wartenau", "id": "Master:10901", "type": "STATION", "coordinate": {"x": 10.035515, "y": 53.56478}, }, "time": {"date": "heute", "time": "jetzt"}, "timeIsDeparture": True, "realtime": "REALTIME", } gr = await gti.getRoute(payload) print(gr) print() print("Example 4.1: departureList()") dl = await gti.departureList( { "station": { "name": "Wartenau", "id": "Master:10901", "type": "STATION", }, "time": {"date": "heute", "time": "jetzt"}, "maxList": 5, "maxTimeOffset": 200, "useRealtime": True, } ) print(dl) print() print("Example 4.2: departureList(), return filters") dl = await gti.departureList( { "station": { "name": "Wartenau", "id": "Master:10901", "type": "STATION", }, "time": {"date": "heute", "time": "jetzt"}, "maxList": 5, "maxTimeOffset": 200, "useRealtime": True, "returnFilters": True, } ) print(dl) print() print("Example 5: getTariff()") gT = await gti.getTariff( { "scheduleElements": [ { "departureStationId": "Master:10950", "arrivalStationId": "Master:37979", "lineId": "DB-EFZ:RE8_DB-EFZ_Z", } ], "departure": {"date": "16.02.2020", "time": "8:04"}, "arrival": {"date": "16.02.2020", "time": "8:29"}, } ) print(gT) print() print("Example 6.1: departureCourse() time and direction") gT = await gti.departureCourse( { "lineKey": "VHH:569_VHH", "station": { "name": "Rosenhof", "city": "Ahrensburg", "combinedName": "Ahrensburg, Rosenhof", "id": "Master:35009", "type": "STATION", "coordinate": {"x": 10.240928, "y": 53.683071}, }, "time": datetime.fromisoformat("2020-10-21T10:19:00.000"), "direction": "Ahrensburg, Schulzentrum Am Heimgarten", } ) # print(gT) print( "departureCourse() output is too long, please uncomment only if neccessary" ) # print() # print("Example 6.2: departureCourse() time and serviceId") # gT = await gti.departureCourse( # { # "lineKey": "HHA-U:U1_HHA-U", # "station": { # "name": "Wartenau", # "id": "Master:10901", # "type": "STATION", # }, # "time": datetime.now(), # "serviceId": 1626150555, # } # ) # print(gT) print( "departureCourse() output is too long, please uncomment only if neccessary" ) print("Example 7: listStations()") # used a older dataReleaseID to show changes since then in the response ls = await gti.listStations({"dataReleaseID": "32.17.02"}) print(ls) print() print("Example 8: listLines()") ll = await gti.listLines({"dataReleaseID": "32.17.02"}) print(ll) print("Example 9: AnnouncementRequest") ar = await gti.getAnnouncements( { "names": ["S3"], "timeRange": { "begin": datetime.now() - timedelta(days=2), "end": datetime.now() + timedelta(days=10), }, } ) print(ar) print() print("Example 10: getIndividualRoute()") payload = { "starts": [ {"type": "ADDRESS", "coordinate": {"x": 9.92496, "y": 53.563494}} ], "dests": [ {"type": "ADDRESS", "coordinate": {"x": 9.924269, "y": 53.562925}} ], "maxLength": 10000, "serviceType": "BICYCLE", "profile": "BICYCLE_NORMAL", "speed": "NORMAL", } indRoute = await gti.getIndividualRoute(payload) print(indRoute) print() print("Example 11a: getVehicleMap()") payload = { "boundingBox": { "lowerLeft": {"x": 9.985707, "y": 53.573138, "type": "EPSG_4326"}, "upperRight": {"x": 9.992702, "y": 53.576916, "type": "EPSG_4326"}, }, "periodBegin": int(datetime.timestamp(datetime.now())), "periodEnd": int(datetime.timestamp(datetime.now() + timedelta(minutes=1))), "withoutCoords": True, "coordinateType": "EPSG_31467", "vehicleTypes": ["U_BAHN"], "realtime": False, } vm = await gti.getVehicleMap(payload) print(vm) print() print("Example 11b: getTrackCoordinates()") payload = { "coordinateType": "EPSG_4326", "stopPointKeys": ["HHA-U:909010:1", "HHA-U:119000:1"], } tc = await gti.getTrackCoordinates(payload) print(tc) print() print("Example 12: checkPostalCode()") pc = await gti.checkPostalCode({"postalCode": 20355}) print(pc) print() print("Example 13: stationInformation()") si = await gti.stationInformation( {"station": {"name": "Wartenau", "id": "Master:10901", "type": "STATION"}} ) print(si) print() print("Example 14: tariffZoneNeighbours()") tzn = await gti.tariffZoneNeighbours({}) print(tzn) print() print("Example 15.1: tariffMetaData() in german") tmd = await gti.tariffMetaData({}) print(tmd) print() print("Example 15.2: tariffMetaData() in english") tmd = await gti.tariffMetaData({"language": "en"}) print(tmd) print() print("Example 16.1: singleTicketOptimizer()") sto = await gti.singleTicketOptimizer( { "withReturnJourney": True, "numberOfAdults": 2, "numberOfChildren": 0, "tickets": [], "route": { "trip": [ { "start": {"id": "Master:43063", "name": "Außenmühle"}, "destination": { "id": "Master:49001", "name": "Bf. Harburg", }, "line": {"id": "HHA-B:145_HHA-B", "name": "145"}, "vehicleType": "Bus", }, { "start": {"id": "Master:49950", "name": "Harburg"}, "destination": { "id": "Master:80950", "name": "Landungsbrücken", }, "line": {"id": "SBH:S3_SBH_SBAHNS", "name": "S3"}, "vehicleType": "S", }, { "start": { "id": "Master:80984", "name": "Landungsbrücken Brücke 1", }, "destination": { "id": "Master:80932", "name": "Elbphilharmonie", }, "line": {"id": "ZVU-DB:72_ZVU-DB_HADAGZ", "name": "72"}, "vehicleType": "Schiff", }, ], "departure": datetime.fromisoformat("2020-04-17T18:16:00.000"), "arrival": datetime.fromisoformat("2020-04-17T19:14:00.000"), "tariffRegions": { "zones": [{"regions": ["308", "208", "108", "000"]}], "rings": [{"regions": ["B", "A"]}], "counties": [{"regions": ["HH1", "HH2"]}], }, "singleTicketTariffLevelId": 14, "extraFareType": "NO", }, } ) print(sto) print() print("Example 17: ticketList()") tl = await gti.ticketList({"stationKey": "Master:92903"}) print(tl) # To avoid 'Event loop is closed' RuntimeError due to compatibility issue with aiohttp if sys.platform.startswith("win") and sys.version_info >= (3, 8): try: from asyncio import WindowsSelectorEventLoopPolicy except ImportError: pass else: if not isinstance( asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy ): asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy()) asyncio.run(main()) pygti-0.10.0/notes.md000066400000000000000000000031761442343737200144160ustar00rootroot00000000000000# Line colors ``` this.colors = { bus: 'red', nachtbus: 'black', eilbus: 'green', XpressBus: 'green', S1: 'green', S11: 'green', S2: 'darkred', S21: 'darkred', S3: 'violet', S31: 'violet', S32: 'blue', S4: 'magenta', U1: 'darkblue', U2: 'red', U3: 'yellow', U4: 'turquoise', akn: 'orange', A1: 'orange', A2: 'orange', A3: 'orange', A4: 'orange', RE: 'transparent', RB: 'transparent', faehre: 'lightblue', ferry: 'lightblue', default: 'transparent' }, this.realColors = { darkblue: '#006AB3', red: '#E2001A', yellow: '#FFDD00', turquoise: '#0098A1', green: '#1A962B', darkred: '#B51143', violet: '#622181', blue: '#0089BB', magenta: '#be007c', orange: '#F29400', black: '#000000', lightblue: '#009DD1', grey: 'grey', transparent: '#000000' }, ``` # BaseRequestType ``` language: String version: int UUID: String filterType: FilterType ``` # BaseResponseType ``` UUID: String ``` # Response idea ``` class BaseResponse(): def __init__(self, json): self.returnCode = json.get("returnCode") class InitResponse(BaseResponse): def __init__(self, json): BaseResponse.__init__(json) self.beginOfService = json.get("beginOfService") self.endOfService = json.get("endOfService") self.id = json.get("id") self.dataId = json.get("dataId") self.buildDate = json.get("buildDate") self.buildTime = json.get("buildTime") self.buildText = json.get("buildText") class CNResponse(BaseResponse): def __init__(self, json): BaseResponse.__init__(json) ``` # Fehler für HVV SingleTicketOptimizerRequest.route ist keine Liste SingleTicketOptimizerRequestRoute.trip ist eine Liste pygti-0.10.0/pygti/000077500000000000000000000000001442343737200140715ustar00rootroot00000000000000pygti-0.10.0/pygti/__init__.py000066400000000000000000000000001442343737200161700ustar00rootroot00000000000000pygti-0.10.0/pygti/auth.py000066400000000000000000000046031442343737200154070ustar00rootroot00000000000000import base64 import hashlib import hmac import json from aiohttp import ClientConnectorError, ClientResponse, ClientSession from .exceptions import * GTI_DEFAULT_HOST = "gti.geofox.de" class Auth: """Class to make authenticated requests to the geofox api.""" def __init__( self, websession: ClientSession, username: str, password: str, host: str = GTI_DEFAULT_HOST, ): """Initialize the auth.""" self.websession = websession self.username = username self.password = password self.host = host async def request( self, method: str, path: str, payload=None, **kwargs ) -> ClientResponse: """Make a request.""" headers = kwargs.get("headers") if headers is None: headers = {} else: headers = dict(headers) payload.update({"version": 54}) data = self.websession.json_serialize(payload).encode("UTF-8") signature = base64.b64encode( hmac.new(self.password.encode("UTF-8"), data, hashlib.sha1).digest() ).decode("UTF-8") headers["geofox-auth-signature"] = f"{signature}" headers["geofox-auth-user"] = self.username try: response = await self.websession.request( method, f"https://{self.host}/{path}", json=payload, **kwargs, headers=headers, ) data = await response.json() return_code = data.get("returnCode") error_text = data.get("errorText") error_dev_info = data.get("errorDevInfo") if return_code == "ERROR_CN_TOO_MANY": raise CheckNameTooMany(return_code, error_text, error_dev_info) elif return_code == "ERROR_COMM": raise CommunicationError(return_code, error_text, error_dev_info) elif return_code == "ERROR_ROUTE": raise RouteError(return_code, error_text, error_dev_info) elif return_code == "ERROR_TEXT": if error_dev_info == "Authentication failed!": raise InvalidAuth(return_code, error_text, error_dev_info) raise GTIError(return_code, error_text, error_dev_info) return response except ClientConnectorError as error: raise CannotConnect(error) pygti-0.10.0/pygti/const.py000066400000000000000000000017661442343737200156030ustar00rootroot00000000000000"""Endpoints for the GTI""" ENDPOINT_INIT = "gti/public/init" ENDPOINT_CHECK_NAME = "gti/public/checkName" ENDPOINT_GET_ROUTE = "gti/public/getRoute" ENDPOINT_DEPARTURE_LIST = "gti/public/departureList" ENDPOINT_GET_TARIFF = "gti/public/getTariff" ENDPOINT_DEPARTURE_COURSE = "gti/public/departureCourse" ENDPOINT_LIST_STATIONS = "gti/public/listStations" ENDPOINT_LIST_LINES = "gti/public/listLines" ENDPOINT_GET_ANNOUNCEMENTS = "gti/public/getAnnouncements" ENDPOINT_GET_INDIVIDUAL_ROUTE = "gti/public/getIndividualRoute" ENDPOINT_GET_VEHICLE_MAP = "gti/public/getVehicleMap" ENDPOINT_GET_TRACK_COORDINATES = "gti/public/getTrackCoordinates" ENDPOINT_CHECK_POSTAL_CODE = "gti/public/checkPostalCode" ENDPOINT_GET_STATION_INFORMATION = "gti/public/getStationInformation" ENDPOINT_TARIFF_ZONE_NEIGHBOURS = "gti/public/tariffZoneNeighbours" ENDPOINT_TARIFF_META_DATA = "gti/public/tariffMetaData" ENDPOINT_TICKET_LIST = "gti/public/ticketList" ENDPOINT_SINGLE_TICKET_OPTIMIZER = "gti/public/singleTicketOptimizer" pygti-0.10.0/pygti/exceptions.py000066400000000000000000000014121442343737200166220ustar00rootroot00000000000000class GTIError(Exception): """An exception occured while using the GTI API.""" def __init__(self, return_code, error_text, error_dev_info): self.return_code = return_code self.error_text = error_text self.error_dev_info = error_dev_info class CannotConnect(Exception): """Exception raised if connection could not be established to host.""" pass class InvalidAuth(GTIError): """Exception raised if credentials are incorrent.""" pass class CheckNameTooMany(GTIError): """Check Name returned too many hits. Precise search term.""" pass class CommunicationError(GTIError): """Error while connecting to backend.""" pass class RouteError(GTIError): """Route could not be calculated.""" pass pygti-0.10.0/pygti/gti.py000066400000000000000000000104471442343737200152340ustar00rootroot00000000000000from .auth import Auth from .const import * from .schemas import ( AnnouncementRequest, BaseRequestType, CNRequest, DCRequest, DLRequest, GRRequest, IndividualRouteRequest, LLRequest, LSRequest, PCRequest, SingleTicketOptimizerRequest, StationInformationRequest, TariffRequestType, TariffZoneNeighboursRequest, TicketListRequest, TrackCoordinatesRequest, VehicleMapRequest, ) class GTI: def __init__(self, auth): self.auth = auth async def init(self): response = await self.auth.request("post", ENDPOINT_INIT, {}) return await response.json() async def checkName(self, payload): request = CNRequest(payload) response = await self.auth.request("post", ENDPOINT_CHECK_NAME, request) return await response.json() async def getRoute(self, payload): request = GRRequest(payload) response = await self.auth.request("post", ENDPOINT_GET_ROUTE, request) return await response.json() async def departureList(self, payload): request = DLRequest(payload) response = await self.auth.request("post", ENDPOINT_DEPARTURE_LIST, request) return await response.json() async def getIndividualRoute(self, payload): request = IndividualRouteRequest(payload) response = await self.auth.request( "post", ENDPOINT_GET_INDIVIDUAL_ROUTE, request ) return await response.json() async def listLines(self, payload): request = LLRequest(payload) response = await self.auth.request("post", ENDPOINT_LIST_LINES, request) return await response.json() async def getTariff(self, payload): request = TariffRequestType(payload) response = await self.auth.request("post", ENDPOINT_GET_TARIFF, request) return await response.json() async def departureCourse(self, payload): request = DCRequest(payload) response = await self.auth.request("post", ENDPOINT_DEPARTURE_COURSE, request) return await response.json() async def listStations(self, payload): request = LSRequest(payload) response = await self.auth.request("post", ENDPOINT_LIST_STATIONS, request) return await response.json() async def getVehicleMap(self, payload): request = VehicleMapRequest(payload) response = await self.auth.request("post", ENDPOINT_GET_VEHICLE_MAP, request) return await response.json() async def getTrackCoordinates(self, payload): request = TrackCoordinatesRequest(payload) response = await self.auth.request( "post", ENDPOINT_GET_TRACK_COORDINATES, request ) return await response.json() async def stationInformation(self, payload): request = StationInformationRequest(payload) response = await self.auth.request( "post", ENDPOINT_GET_STATION_INFORMATION, request ) return await response.json() async def getAnnouncements(self, payload): request = AnnouncementRequest(payload) response = await self.auth.request("post", ENDPOINT_GET_ANNOUNCEMENTS, request) return await response.json() async def checkPostalCode(self, payload): request = PCRequest(payload) response = await self.auth.request("post", ENDPOINT_CHECK_POSTAL_CODE, request) return await response.json() async def tariffZoneNeighbours(self, payload): request = TariffZoneNeighboursRequest(payload) response = await self.auth.request( "post", ENDPOINT_TARIFF_ZONE_NEIGHBOURS, request ) return await response.json() async def tariffMetaData(self, payload): request = BaseRequestType(payload) response = await self.auth.request("post", ENDPOINT_TARIFF_META_DATA, request) return await response.json() async def ticketList(self, payload): request = TicketListRequest(payload) response = await self.auth.request("post", ENDPOINT_TICKET_LIST, request) return await response.json() async def singleTicketOptimizer(self, payload): request = SingleTicketOptimizerRequest(payload) response = await self.auth.request( "post", ENDPOINT_SINGLE_TICKET_OPTIMIZER, request ) return await response.json() pygti-0.10.0/pygti/schemas.py000066400000000000000000002371671442343737200161060ustar00rootroot00000000000000""" This file was generated automatically by xsd-to-vol. Do not edit. """ from datetime import datetime import pytz from voluptuous import All, In, Length, Required, Schema, Url def DateTime(dt): dt = pytz.utc.localize(dt) return f"{dt.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3]}{dt.strftime('%z')}" """TariffMetaDataRequest """ TariffMetaDataRequest = Schema({}) """TariffZoneNeighboursRequest Requests all HVV zones and their zone neighbours. """ TariffZoneNeighboursRequest = Schema({}) """TariffRequest """ TariffRequest = Schema({}) """GRRequest """ GRRequest = Schema({}) """ErrorResponse An error occurred on the server side. This type of Response will only be send in combination with the http status code 401 and 403. """ ErrorResponse = Schema({}) """SingleTicketOptimizerRequestLine id: str (None - None) name: str (None - None) """ SingleTicketOptimizerRequestLine = Schema({"id": str, "name": str}) """SingleTicketOptimizerRequestStation id: str (None - None) name: str (None - None) """ SingleTicketOptimizerRequestStation = Schema({"id": str, "name": str}) """SingleTicketOptimizerRequestTrip start: SingleTicketOptimizerRequestStation (None - None) destination: SingleTicketOptimizerRequestStation (None - None) line: SingleTicketOptimizerRequestLine (None - None) vehicleType: str (None - None) """ SingleTicketOptimizerRequestTrip = Schema( { "start": SingleTicketOptimizerRequestStation, "destination": SingleTicketOptimizerRequestStation, "line": SingleTicketOptimizerRequestLine, "vehicleType": str, } ) """TariffRegions regions: str (None - unbounded) """ TariffRegions = Schema({"regions": [str]}) """TariffOptimizerRegions Regions to be covered by tickets zones: TariffRegions (0 - unbounded) rings: TariffRegions (0 - unbounded) counties: TariffRegions (0 - unbounded) """ TariffOptimizerRegions = Schema( {"zones": [TariffRegions], "rings": [TariffRegions], "counties": [TariffRegions]} ) """TariffCounty contains information about a tariff county id: str Unique identifier for this tariff county (None - None) label: str label of the tariff county (None - None) """ TariffCounty = Schema({"id": str, "label": str}) """TimePeriod The ticket is valid within this period. begin: str Begin of the period. Format: HH:mm (This might contain hour values > 24, in case of next day) (None - None) end: str End of the period. Format: HH:mm (This might contain hour values > 24, in case of next day) (None - None) """ TimePeriod = Schema({"begin": str, "end": str}) """TariffZone zone: str Contains a HVV fare zone. (None - None) ring: str Contains a HVV fare ring. (None - None) neighbours: str The neighbouring zones of the current zone. (None - unbounded) """ TariffZone = Schema({"zone": str, "ring": str, "neighbours": [str]}) """Link label: str additional summazied informations about the linked content (e.g. "Ersatzfahrplan"). (None - None) url: str Defines a link providing further information about a actual notice. (None - None) """ Link = Schema({"label": str, "url": str}) """TimeRange begin: DateTime Begin of TimeRange. (Null means "open end") (0 - None) end: DateTime End of TimeRange. (Null means "open end") (0 - None) """ TimeRange = Schema({"begin": DateTime, "end": DateTime}) """StationLight Represents a light version of a station. id: str The unique id of the station (None - None) name: str The name of the station. (0 - None) """ StationLight = Schema({"id": str, "name": str}) """TariffRegionList Holds a list of tariff regions (e.g. tariff-zones, tariff-rings). regions: str list of crossed tariff regions. (0 - unbounded) """ TariffRegionList = Schema({"regions": [str]}) """ScheduleElementLight One element of a schedule with from/to station and line IDs. This is a lighter form of a ScheduleElement. ScheduleElementLights are allways public transport elements (no footpathes allowed). Departure and arrival are allways at a station. departureStationId: str ID of the departure station. (None - None) arrivalStationId: str ID of the arrival station. (None - None) lineId: str ID of the line used between departure and arrivel station. (None - None) """ ScheduleElementLight = Schema( {"departureStationId": str, "arrivalStationId": str, "lineId": str} ) """Property Property which can be part of InitRequest and InitResponse. Is needed for transferring properties from server to client. key: str The key which identifies a property. (None - None) value: str The value of a property which is identified by the key. (0 - None) """ Property = Schema({"key": str, "value": str}) """Ticket The ticket information. DEPRECATED since API Version 13 replaced by "tariffInfos" price: float The price of the ticket. (None - None) reducedPrice: float The reduced price for online shopping. * since version 16 (0 - None) currency: str The currency of the price. Default is Euro. Default: EUR (0 - None) type: str The type information of the ticket. e.g. Einzelfahrt (None - None) level: str The level information of the ticket. e.g. Nahbereich (None - None) tariff: str The tariff information of the ticket. e.g. HVV (None - None) range: str The stations of the ticket. (None - None) ticketRemarks: str Additional information about ticket. For example if it is only valid on a part of the trip. * since version 18 (0 - None) """ Ticket = Schema( { "price": float, "reducedPrice": float, "currency": str, "type": str, "level": str, "tariff": str, "range": str, "ticketRemarks": str, } ) """TariffInfoSelector Returns Ticketinfos (in schedule) for each of this tariffs and kinds, if the given tariff and kind is valid on the returned schedule. tariff: str tariff of HVV or SH? "all" will select all tariffs. Default: HVV (0 - None) tariffRegions: bool also return tariff regions (tariffzones, rings, counties)? Default: true (0 - None) kinds: int Returns Ticketinfos (in schedule) for each of this tariff kinds, if the kind is valid on the returned schedule. An empty list will return cards of every valid kind. (0 - unbounded) """ TariffInfoSelector = Schema({"tariff": str, "tariffRegions": bool, "kinds": [int]}) """Penalty The penalties for a GRRequest. name: str The name of the penalty. (None - None) value: str The value of the penalty. In most cases a single int value. Exception: - DesiredType - string:int (e.g. bus:10) - DesiredLine - string,...,string:int (e.g. U1,S21,U3:3) (None - None) """ Penalty = Schema({"name": str, "value": str}) """DLFilterEntry Filter for DLRequest. * since Version 20 serviceID: str ID of the Departure's service. Either serviceID or stationID must be filled in for Request. (0 - None) stationIDs: str IDs of stations of which one must be on the journey after (before in case of departure=false) the reference station. Either serviceID or stationIDs must be filled for Request. (0 - unbounded) label: str A string that discribes the direction for the user. This field could be empty in DLRequest (server will not evaluate this field) and is allways filled in the list of possible filter entries in DLResponse. (0 - None) serviceName: str A string that represents the public name of the service. (0 - None) """ DLFilterEntry = Schema( {"serviceID": str, "stationIDs": [str], "label": str, "serviceName": str} ) """GTITime date: str The date as string. Format: dd.mm.yyyy (None - None) time: str The time as string. Format: hh:mm (None - None) """ GTITime = Schema({"date": str, "time": str}) """ContSearchByServiceId serviceId: int the service id of the first/last trip part with vehicle (1 - None) lineKey: str the line key of the first/last trip part with vehicle (1 - None) plannedDepArrTime: GTITime the planned departure/arrival time at the start/dest station (1 - None) additionalOffset: int an additional offset for the footway to the start/dest; negative in the dest case (1 - None) """ ContSearchByServiceId = Schema( { Required("serviceId"): int, Required("lineKey"): str, Required("plannedDepArrTime"): GTITime, Required("additionalOffset"): int, } ) """Attribute title: str The title of the attribute. (None - None) isPlanned: bool Is the attribute planned? (None - None) value: str A text to describe the attribute. (None - None) types: str Type of an attribute. Currently used attribute types are: -NORMAL: The default attribute type for simple text attributes. -ANNOUNCEMENT: Attribute for announcement messages -REALTIME: Informations about missed connections, cancelled journeys, etc. -DIRECTION_NAME: Indicates that the attribute value defines a direction name. -ENTRY_PROHIBITED: Indicates that no passenger can enter the vehicle on that station. -EXIT_PROHIBITED: Indicates that the passengers can't exit the vehicle on this station. -STOP_ON_DEMAND: Indicates that the vehicle does not necessarily hold on that station. The vehicle holds only if a passenger wants to exit. -PLATFORM: Indicates that the attribute value defines the platform number where the vehicle holds. -NOCHANGE: Indicates that the change (from fussweg.asc) is not a real change. The passenger can stay in the same vehicle. -POSITION_FRONT: Indicates that the attribute value defines the optimal position in the train (In this case: front). -POSITION_BACK: Indicates that the attribute value defines the optimal position in the train (In this case: back). -POSITION_MIDDLE: Indicates that the attribute value defines the optimal position in the train (In this case: middle). These types could be supplemented with new ones without creating a new interface version. Clients should be prepared to handle unknown types. * since version 3 (0 - unbounded) """ Attribute = Schema({"title": str, "isPlanned": bool, "value": str, "types": [str]}) """TariffDetails Some detailed information about a tariff. innerCity: bool (None - None) city: bool (None - None) cityTraffic: bool (None - None) gratis: bool (None - None) greaterArea: bool (None - None) tariffZones: int (0 - unbounded) regions: int (0 - unbounded) counties: str (0 - unbounded) rings: str (0 - unbounded) fareStage: bool (None - None) fareStageNumber: int (None - None) tariffNames: str (0 - unbounded) uniqueValues: bool (None - None) """ TariffDetails = Schema( { "innerCity": bool, "city": bool, "cityTraffic": bool, "gratis": bool, "greaterArea": bool, "tariffZones": [int], "regions": [int], "counties": [str], "rings": [str], "fareStage": bool, "fareStageNumber": int, "tariffNames": [str], "uniqueValues": bool, } ) """BaseResponseType """ BaseResponseType = Schema({}) """TariffZoneNeighboursResponse Response of the TariffZoneNeighboursRequest, which contains all HVV zones. tariffZones: TariffZone List of all zones. (None - unbounded) """ TariffZoneNeighboursResponse = Schema.extend( BaseResponseType, {"tariffZones": [TariffZone]} ) """PCResponse isHVV: bool Whether the postal code intersects the HVV area (None - None) """ PCResponse = Schema.extend(BaseResponseType, {"isHVV": bool}) """InitResponse beginOfService: str The time when the current timetable started. (None - None) endOfService: str The time when the current timetable will end. (None - None) id: str The ID of the geofox release. (None - None) dataId: str The ID of the data. (None - None) buildDate: str The build date of the Geofox release which is overwritten by build date of the data. (None - None) buildTime: str The build time of the Geofox release which is overwritten by build time of the data. (None - None) buildText: str The build text/name of the data release. (None - None) version: str The version. (None - None) properties: Property An optional list of properties which the client requested. (0 - unbounded) """ InitResponse = Schema.extend( BaseResponseType, { "beginOfService": str, "endOfService": str, "id": str, "dataId": str, "buildDate": str, "buildTime": str, "buildText": str, "version": str, "properties": [Property], }, ) """TariffExtraFareType Specifies wether the route requires any type of ExtraFare """ TariffExtraFareType = In(["NO", "POSSIBLE", "REQUIRED"]) """SingleTicketOptimizerRequestRoute trip: SingleTicketOptimizerRequestTrip (None - unbounded) departure: DateTime Time of departure (None - None) arrival: DateTime Time of arrival (None - None) tariffRegions: TariffOptimizerRegions Regions that need to be covered by tickets (None - None) singleTicketTariffLevelId: int (None - None) extraFareType: TariffExtraFareType Specifies wether the tickets have some type of extra fare (None - None) """ SingleTicketOptimizerRequestRoute = Schema( { "trip": [SingleTicketOptimizerRequestTrip], "departure": DateTime, "arrival": DateTime, "tariffRegions": TariffOptimizerRegions, "singleTicketTariffLevelId": int, "extraFareType": TariffExtraFareType, } ) """TariffPersonType - ALL: Alle - ADULT: Erwachsene - ELDERLY: Senioren - APPRENTICE: Auszubildende - PUPIL: Schüler - STUDENT: Studenten - CHILD: Kinder """ TariffPersonType = In( ["ALL", "ADULT", "ELDERLY", "APPRENTICE", "PUPIL", "STUDENT", "CHILD"] ) """TicketRegionType type of a tariff region - RING: tariff level is based on tariff rings (A, B, ...). - ZONE: tariff level is based on tariff zones (000, 101, ...). - COUNTY tariff level is based on counties (SE, WL, ...). - GH_ZONE: tariff level is "Großbereich Hamburg" + X Zones. (since version 14). """ TicketRegionType = In(["RING", "ZONE", "COUNTY", "GH_ZONE"]) """TariffOptimizerTicket tariffKindId: int (None - None) tariffKindLabel: str (0 - None) tariffLevelId: int (None - None) tariffLevelLabel: str (0 - None) tariffRegions: str Regions covered by this ticket (None - unbounded) regionType: TicketRegionType (None - None) count: int (None - None) extraFare: bool (None - None) personType: TariffPersonType (None - None) centPrice: int (None - None) """ TariffOptimizerTicket = Schema( { "tariffKindId": int, "tariffKindLabel": str, "tariffLevelId": int, "tariffLevelLabel": str, "tariffRegions": [str], "regionType": TicketRegionType, "count": int, "extraFare": bool, "personType": TariffPersonType, "centPrice": int, } ) """SingleTicketOptimizerResponse Response of the TariffOptimizer tickets: TariffOptimizerTicket Tickets the user has to buy for the requested route (0 - unbounded) """ SingleTicketOptimizerResponse = Schema.extend( BaseResponseType, {"tickets": [TariffOptimizerTicket]} ) """TicketType is ticket a single ticket or a season ticket? """ TicketType = In(["OCCASIONAL_TICKET", "SEASON_TICKET"]) """TariffKind Contains information about a tariff kind id: int Unique identifier for this tariff kind (None - None) label: str label of the tariff kind (None - None) requiresPersonType: bool Contains information if further information about the type of person using this card is needed (used in tariff optimizer) Default: false (0 - None) ticketType: TicketType is ticket a single ticket or a season ticket? (0 - None) levelCombinations: int Contains information about which levels this kind can be combined with (0 - unbounded) """ TariffKind = Schema( { "id": int, "label": str, "requiresPersonType": bool, "ticketType": TicketType, "levelCombinations": [int], } ) """ValidityDayType - WEEKDAY: Mo-Fr - WEEKEND: Saturday, Sunday, public holidays """ ValidityDayType = In(["WEEKDAY", "WEEKEND"]) """ValidityPeriod Contains information about the validity of this ticket. day: ValidityDayType The DayType of the validityPeriod (WEEKDAY, WEEKEND) (None - None) timeValidities: TimePeriod The ticket is valid within this period. (0 - unbounded) """ ValidityPeriod = Schema({"day": ValidityDayType, "timeValidities": [TimePeriod]}) """PersonType - ALL: Alle - ELDERLY: Senioren - APPRENTICE: Auszubildende - PUPIL: Schüler - STUDENT: Studenten - CHILD: Kinder """ PersonType = In(["ALL", "ELDERLY", "APPRENTICE", "PUPIL", "STUDENT", "CHILD"]) """PersonInfo Contains information for how many people of a specific type of person the card is for. personType: PersonType Contains the information about the specific type of person. (0 - None) personCount: int Contains information for how many people the card is for. (0 - None) """ PersonInfo = Schema({"personType": PersonType, "personCount": int}) """DiscountType - NONE: kein Rabatt - ONLINE: Onlinerabatt - SOCIAL: Sozialrabatt """ DiscountType = In(["NONE", "ONLINE", "SOCIAL"]) """TicketClass - NONE: classes are not relevant for this ticket. - SECOND: 2nd class - FIRST: 1st class - SCHNELL: ticket includes "Schnellbus" extra fare. """ TicketClass = In(["NONE", "SECOND", "FIRST", "SCHNELL"]) """TicketListTicketVariant Contains informations about one variant of a ticket from the TicketListRequest. ticketId: int Contains a unique ID for this ticket variant. In case of HVV this contains the unique 8 digit HVV ticket ID. (None - None) kaNummer: int The KA-Nummer of this ticket. Might be null if unknown. (0 - None) price: float The ticket price. (None - None) currency: str The currency of the price. Default is Euro. Default: EUR (0 - None) ticketClass: TicketClass Travel class of this ticket (None - None) discount: DiscountType included discount in this ticket (None - None) validityBegin: DateTime The validity start date of the tickets tariff data. (None - None) validityEnd: DateTime The validity end date of the tickets tariff data. (None - None) """ TicketListTicketVariant = Schema( { "ticketId": int, "kaNummer": int, "price": float, "currency": str, "ticketClass": TicketClass, "discount": DiscountType, "validityBegin": DateTime, "validityEnd": DateTime, } ) """ElevatorState Enumeration with all possible elevator states. """ ElevatorState = In(["READY", "OUTOFORDER", "UNKNOWN"]) """ElevatorButtonType Enumeration with all possible elevator button types. """ ElevatorButtonType = In(["BRAILLE", "ACUSTIC", "COMBI", "UNKNOWN"]) """Elevator lines: str The elevator serves the platform for the lines listed here (0 - unbounded) label: str The label of the elevator. (0 - None) cabinWidth: int The width of the cabin (0 - None) cabinLength: int The width of the cabin (0 - None) doorWidth: int The width of the cabin door (0 - None) description: str A description of the elevator (0 - None) elevatorType: str The type of the elevator (0 - None) buttonType: ElevatorButtonType The type of the buttons (0 - None) state: ElevatorState The state of the elevator (0 - None) cause: str Cause of the the elevator's state (0 - None) """ Elevator = Schema( { "lines": [str], "label": str, "cabinWidth": int, "cabinLength": int, "doorWidth": int, "description": str, "elevatorType": str, "buttonType": ElevatorButtonType, "state": ElevatorState, "cause": str, } ) """PartialStation lines: str The partial station is reached by these lines listed here. If this field is not set, all not otherwise mentioned lines that reach the station do that through this partial station (0 - unbounded) stationOutline: Url The outline of the partial station. (0 - None) elevators: Elevator The elevators at this partial station. (0 - unbounded) """ PartialStation = Schema( {"lines": [str], "stationOutline": Url, "elevators": [Elevator]} ) """StationInformationResponse partialStations: PartialStation The station might be divided in different parts. These parts are listed here. (0 - unbounded) lastUpdate: GTITime The last time the dynamic elevator data where updated (0 - None) """ StationInformationResponse = Schema.extend( BaseResponseType, {"partialStations": [PartialStation], "lastUpdate": GTITime} ) """AnnouncementFilterPlannedType Enumeration of all possible types for filtering the announcements concerning their planned-flag - NO_FILTER - default, nothing is filtered - ONLY_PLANNED - only announcements about planned events are returned - ONLY_UNPLANNED - only announcements about unplanned events are returned """ AnnouncementFilterPlannedType = In(["NO_FILTER", "ONLY_PLANNED", "ONLY_UNPLANNED"]) """LocationType Enumeration with possible types of a location. """ LocationType = In(["SINGLE_LINE", "ALL_LINES_OF_CARRIER", "COMPLETE_NET"]) """LineModificationType type of modification. MAIN: Modification of one of the main informations about the object (e.g. name, carrier name). SEQUENCE: Modification of the main station sequence. """ LineModificationType = In(["MAIN", "SEQUENCE"]) """ModificationType type of modification. MAIN: modification of one of the main informations about the object (e.g. name, city). POSITION: object got new coordinates. """ ModificationType = In(["MAIN", "POSITION"]) """VehicleType type of list station entry. AST: Anruf-Sammel-Taxi U_BAHN: U-Bahn Hamburg S_BAHN: S-Bahn Hamburg A_BAHN: AKN Eisenbahn R_BAHN: Regionalbahn (R10, R30, ...) F_BAHN: Fernbahn (IC, ICE, ...) * since API version 17 """ VehicleType = In( [ "REGIONALBUS", "METROBUS", "NACHTBUS", "SCHNELLBUS", "XPRESSBUS", "AST", "SCHIFF", "U_BAHN", "S_BAHN", "A_BAHN", "R_BAHN", "F_BAHN", "EILBUS", ] ) """SublineListEntry One entry of the subline list sublineNumber: str The internal number of this subline. This number may change frequently on each data release. (None - None) vehicleType: VehicleType Type of vehicle of this subline. (None - None) stationSequence: StationLight The station sequence of the subline as station ids. (0 - unbounded) """ SublineListEntry = Schema( { "sublineNumber": str, "vehicleType": VehicleType, "stationSequence": [StationLight], } ) """SegmentSelector Return stations before or after the given station or return all stations. -BEFORE: return stations before the given stations on the given line -AFTER: return stations after the given stations on the given line -ALL: return all stations on the given line """ SegmentSelector = In(["BEFORE", "AFTER", "ALL"]) """TariffRegionType type of a tariff region - ZONE: tariff level is based on tariff zones (000, 101, ...). - GH_ZONE: tariff level is "Großbereich Hamburg" + X Zones. (since version 14) - RING: tariff level is based on tariff rings (A, B, ...). - COUNTY tariff level is based on counties (SE, WL, ...). - GH tariff level is based on Großbereich Hamburg/Hamburg AB. - NET tariff level is valid in complete tariff net. - ZG tariff level is based on payment borders (Zahlgrenzen). - STADTVERKEHR tariff level is based on limits for city tickets. """ TariffRegionType = In( ["ZONE", "GH_ZONE", "RING", "COUNTY", "GH", "NET", "ZG", "STADTVERKEHR"] ) """RequiredRegionType Contains information about the needed information regarding the region type type: TariffRegionType holds information about the type that is required (None - None) count: int holds information about how many regions of the type are required (None - None) """ RequiredRegionType = Schema({"type": TariffRegionType, "count": int}) """TariffLevel Contains information about a tariff level id: int Unique identifier for this tariff level (None - None) label: str label of the tariff level (None - None) requiredRegionType: RequiredRegionType Describes what additional region information is needed to buy the ticket. (e.g. 2 Zones or 1 County) (None - None) """ TariffLevel = Schema( {"id": int, "label": str, "requiredRegionType": RequiredRegionType} ) """TariffMetaDataResponse Contains tariff related meta data tariffKinds: TariffKind Contains the different tariff kinds (0 - unbounded) tariffLevels: TariffLevel Contains the different tariff levels information (0 - unbounded) tariffCounties: TariffCounty Contains the different tariff counties information (0 - unbounded) tariffZones: TariffZone Contains the different tariff zones (0 - unbounded) tariffRings: str Contains the different tariff rings (0 - unbounded) """ TariffMetaDataResponse = Schema.extend( BaseResponseType, { "tariffKinds": [TariffKind], "tariffLevels": [TariffLevel], "tariffCounties": [TariffCounty], "tariffZones": [TariffZone], "tariffRings": [str], }, ) """TicketListTicketInfos Contains infos of a ticket. tariffKindID: int id of the tariff kind (Kartenart). (None - None) tariffKindLabel: str name of the tariff kind (e.g. Einzelkarte). (None - None) tariffLevelID: int id of the tariff level (Tarifstufe). (None - None) tariffLevelLabel: str name of the tariff level (e.g. Kurzstrecke). (None - None) tariffGroupID: int id of the tariff group. (0 - None) tariffGroupLabel: str name of the tariff group (e.g. Allgemeine Zeitkarten). (0 - None) regionType: TariffRegionType if this is not null, the specified TicketInfo needs this type of additional TariffRegionInfos. * since version 14 (0 - None) selectableRegions: int The number of selectable regions with this ticket. (for example with "2 Tarifzonen" this would be 2) Default: 0 (0 - None) requiredStartStation: bool Holds information if the ticket needs start station information to verify validity. Default: false (None - None) personInfos: PersonInfo Contains list of information for how many people of a specific type of person the card is for. (0 - unbounded) validityPeriods: ValidityPeriod Contains information about the validity of this ticket. (0 - unbounded) variants: TicketListTicketVariant Contains information about one variant of this ticket. (for example 2nd class and 1st class) (0 - unbounded) """ TicketListTicketInfos = Schema( { "tariffKindID": int, "tariffKindLabel": str, "tariffLevelID": int, "tariffLevelLabel": str, "tariffGroupID": int, "tariffGroupLabel": str, "regionType": TariffRegionType, "selectableRegions": int, "requiredStartStation": bool, "personInfos": [PersonInfo], "validityPeriods": [ValidityPeriod], "variants": [TicketListTicketVariant], } ) """TicketListResponse Response of the TicketListRequest, which contains all HVV Tickets. ticketInfos: TicketListTicketInfos List of all tickets. (None - unbounded) """ TicketListResponse = Schema.extend( BaseResponseType, {"ticketInfos": [TicketListTicketInfos]} ) """TariffRegionInfo Holds informations about a tariff region (e.g. tariff-zones, tariff-rings). regionType: TariffRegionType Type of tariff region (e.g. tariff-zone, tariff-ring). (could be null if there is no TicketInfo of type GH_ZONE). (None - None) alternatives: TariffRegionList altanatives of crossed tariff regions. Because stations could belong to more than one tariff region, there could be different possible list of crossed regions for the same route. (0 - unbounded) """ TariffRegionInfo = Schema( {"regionType": TariffRegionType, "alternatives": [TariffRegionList]} ) """TicketInfo Holds detail ticket informations. tariffKindID: int id of the tariff kind (Kartenart). (None - None) tariffKindLabel: str name of the tariff kind (e.g. Einzelkarte). (None - None) tariffLevelID: int id of the tariff level (Tarifstufe). (None - None) tariffLevelLabel: str name of the tariff level (e.g. Kurzstrecke). (None - None) tariffGroupID: int id of the tariff group. (0 - None) tariffGroupLabel: str name of the tariff group (e.g. Allgemeine Zeitkarten). (0 - None) basePrice: float base ticket price (without extra fare). (None - None) extraFarePrice: float additional extra fare ticket price. (0 - None) reducedBasePrice: float reduced base ticket price (without extra fare). * since version 16 (0 - None) reducedExtraFarePrice: float reduced additional extra fare ticket price. * since version 16 (0 - None) currency: str The currency of the price. Default is Euro. Default: EUR (0 - None) regionType: TariffRegionType if this is not null, the specified TicketInfo needs this type of additional TariffRegionInfos. * since version 14 (0 - None) notRecommended: bool If set to true, this ticket is valid but not recommended. * since version 32 Default: false (0 - None) shopLinkRegular: str The link to the shop, where you could buy this ticket as a regular ticket. * since version 32 (0 - None) shopLinkExtraFare: str The link to the shop, where you could buy this ticket as an extra fare ticket. * since version 32 (0 - None) """ TicketInfo = Schema( { "tariffKindID": int, "tariffKindLabel": str, "tariffLevelID": int, "tariffLevelLabel": str, "tariffGroupID": int, "tariffGroupLabel": str, "basePrice": float, "extraFarePrice": float, "reducedBasePrice": float, "reducedExtraFarePrice": float, "currency": str, "regionType": TariffRegionType, "notRecommended": bool, "shopLinkRegular": str, "shopLinkExtraFare": str, } ) """ShopType - AST: Anruf-Sammel-Taxi """ ShopType = In(["AST"]) """ShopInfo Information about the shop, where a ticket could be bought. shopType: ShopType Type of Shop (for example Anruf-Sammel-Taxi) (1 - 1) url: str URL of the responsible ticket shop. (1 - 1) """ ShopInfo = Schema({Required("shopType"): ShopType, Required("url"): str}) """RealtimeType Configures the consideration of realtime informations during route calculation. -PLANDATA: only return a result based on plandata. -REALTIME: only return a result based on realtime data. -AUTO: The plandata result (schedules) will allways be returned. Realtime result (realtimeSchedules) will be returned if it is different from plandata result. * since version 19 """ RealtimeType = In(["PLANDATA", "REALTIME", "AUTO"]) """IndividualProfileType Configures requests for routes by different profiles. * since version 25 """ IndividualProfileType = In( [ "BICYCLE_NORMAL", "BICYCLE_RACING", "BICYCLE_QUIET_ROADS", "BICYCLE_MAIN_ROADS", "BICYCLE_BAD_WEATHER", "FOOT_NORMAL", ] ) """SimpleServiceType Enumeration with all simple types of services * BICYCLE since API version 17 """ SimpleServiceType = In( [ "BUS", "TRAIN", "SHIP", "FOOTPATH", "BICYCLE", "AIRPLANE", "CHANGE", "CHANGE_SAME_PLATFORM", ] ) """ServiceType The complex type of a Service. Includes the simple type and additional information. simpleType: SimpleServiceType The simple type of a Service, like BUS or TRAIN. (None - None) shortInfo: str A short information about the vehicle (e.g. Schnellbus). More information see properties in geofox. (0 - None) longInfo: str More detailled information about the vehicle (e.g. Niederflur-Schnellbus). More information see properties in geofox. (0 - None) model: str The specific model of the vehicle if applicable and available. * since API version 24 (0 - None) """ ServiceType = Schema( {"simpleType": SimpleServiceType, "shortInfo": str, "longInfo": str, "model": str} ) """LineListEntry One entry of the line list id: str The unique id of an entry (None - None) name: str Name of the entry. Is null if the line was deleted. (0 - None) carrierNameShort: str Short name of the carrier. Is null if the line was deleted. (0 - None) carrierNameLong: str Long name of the carrier. Is null if the line was deleted. (0 - None) sublines: SublineListEntry List of sublines. Is null if no sublines were requested or if the line was deleted. (0 - unbounded) exists: bool This field is false if the line is deleted. Default: true (0 - None) type: ServiceType The type of the service. For Example: BUS, TRAIN with optional additional information. (None - None) """ LineListEntry = Schema( { "id": str, "name": str, "carrierNameShort": str, "carrierNameLong": str, "sublines": [SublineListEntry], "exists": bool, "type": ServiceType, } ) """LLResponse The response for LLRequest with a list of lines. dataReleaseID: str result was created on this data release. (0 - None) lines: LineListEntry List of lines. This list could be empty if there is no line fitting to the given filter settings. (0 - unbounded) """ LLResponse = Schema.extend( BaseResponseType, {"dataReleaseID": str, "lines": [LineListEntry]} ) """Service The service with type and a name. name: str The name of the service. For Example: S1, U3, 101, etc. (None - None) direction: str The direction where the service is headed. (0 - None) directionId: int The id of the direction. Forward (1), backward (6). (0 - None) origin: str The origin where the service comes from (opposite of direction). * since version 19 (0 - None) type: ServiceType The type of the service. For Example: BUS, TRAIN with optional additional information. (None - None) id: str The id of a service. Is neccessary for TariffRequest. This is NOT the service-id, but the line key * since version 4 (0 - None) """ Service = Schema( { "name": str, "direction": str, "directionId": int, "origin": str, "type": ServiceType, "id": str, } ) """IndividualTrack time: int The time of the IndividualTrack in minutes. (None - None) length: int The length of the IndividualTrack in km. (None - None) type: SimpleServiceType The type of the IndividualTrack. (None - None) """ IndividualTrack = Schema({"time": int, "length": int, "type": SimpleServiceType}) """FilterServiceType To filter departures by service type. * since version 22 """ FilterServiceType = In( [ "ZUG", "UBAHN", "SBAHN", "AKN", "RBAHN", "FERNBAHN", "BUS", "STADTBUS", "METROBUS", "SCHNELLBUS", "NACHTBUS", "XPRESSBUS", "AST", "FAEHRE", "EILBUS", ] ) """CoordinateType type of a coordinate -EPSG_4326 wgs84 -EPSG_31466 Gauss-Kruger zone 2 -EPSG_31467 Gauss-Kruger zone 3 -EPSG_31468 Gauss-Kruger zone 4 -EPSG_31469 Gauss-Kruger zone 5 for explanation of types: http://www.epsg-registry.org/ currently only wgs84 and Gauss-Kruger zone 3 are supported """ CoordinateType = In( ["EPSG_4326", "EPSG_31466", "EPSG_31467", "EPSG_31468", "EPSG_31469"] ) """VehicleMapPath description of a path from a given start to a destination with coordinates and properties. track: float Coordinates of the path, 2 makes one coordinate, coordinateType is declared in "coordinateType" (4 - unbounded) coordinateType: CoordinateType Type of the coordinates (None - None) """ VehicleMapPath = Schema( {Required("track"): All([float], Length(min=4)), "coordinateType": CoordinateType} ) """TrackCoordinatesResponse response for TrackCoordinatesRequest trackIDs: str The IDs of the tracks in tracks (1 - unbounded) tracks: VehicleMapPath The requested coordinates (1 - unbounded) """ TrackCoordinatesResponse = Schema.extend( BaseResponseType, { Required("trackIDs"): All([str], Length(min=1)), Required("tracks"): All([VehicleMapPath], Length(min=1)), }, ) """PathSegment startStopPointKey: str the Key of the startstoppoint of this segment (None - None) endStopPointKey: str the Key of the deststoppoint of this segment (None - None) startStationName: str the name of the startstation of this segment (None - None) startStationKey: str the Key of the startstation of this segment (None - None) startDateTime: int timestamp - this segment begins at the first coordinate of the track at this start date/time (None - None) endStationName: str the name of the endstation of this segment (None - None) endStationKey: str the Key of the endstation of this segment (None - None) endDateTime: int timestamp - this segment ends at the last coordinate of the track at this end date/time (None - None) track: VehicleMapPath The actual coordinate-Track (None - None) destination: str The Destination Display on the Station for this Vehicle (None - None) realtimeDelay: int realtime delay informations in minutes (None - None) isFirst: bool determins if this is the First segment of a Journey (None - None) isLast: bool determins if this is the Last segment of a Journey (None - None) """ PathSegment = Schema( { "startStopPointKey": str, "endStopPointKey": str, "startStationName": str, "startStationKey": str, "startDateTime": int, "endStationName": str, "endStationKey": str, "endDateTime": int, "track": VehicleMapPath, "destination": str, "realtimeDelay": int, "isFirst": bool, "isLast": bool, } ) """Journey journeyID: str Fahrt ID - Unique identifier for this journey (None - None) line: Service unique ID of the line that is doing this journey (None - None) vehicleType: VehicleType journey is done with this type of vehicle (None - None) realtime: bool data is based on realtime informations (None - None) segments: PathSegment each journey is splitted in one segment between two stations (0 - unbounded) """ Journey = Schema( { "journeyID": str, "line": Service, "vehicleType": VehicleType, "realtime": bool, "segments": [PathSegment], } ) """VehicleMapResponse response for VehicleMapRequest journeys: Journey informations about the journeys inside the given bounding box and period (1 - unbounded) """ VehicleMapResponse = Schema.extend( BaseResponseType, {Required("journeys"): All([Journey], Length(min=1))} ) """Coordinate the coordinate of a location with x and y value x: float the x value or longitude of the coordinate (None - None) y: float the y value or latitude of the coordinate (None - None) type: CoordinateType type of a coordinate. default is wgs84 Default: EPSG_4326 (0 - None) """ Coordinate = Schema({"x": float, "y": float, "type": CoordinateType}) """BoundingBox represents a Box by defining the lower-left and the upper-right Corner. Usecases: limiting a request, describing the hull of a geometry, ... lowerLeft: Coordinate the coordinate at lower-left Corner (None - None) upperRight: Coordinate the coordinate at upper-right Corner (None - None) """ BoundingBox = Schema({"lowerLeft": Coordinate, "upperRight": Coordinate}) """StationListEntry One entry of the station list id: str the unique id of an entry (None - None) name: str name of the entry. is null if the station was deleted. (0 - None) city: str entry belongs to this city. is null if the station was deleted. (0 - None) combinedName: str combination of name and city field. In order to reduce response size, this field is null if the combined name can be build by concating city and name in the form: city + ", " + name (0 - None) shortcuts: str list of short names for station. (could be empty or null if there is no shortcut) (0 - unbounded) aliasses: str list of aliasses for station. (could be empty or null if there is no alias) (0 - unbounded) vehicleTypes: VehicleType types of vehicles that depart at this station. (0 - unbounded) coordinate: Coordinate the coordinate of an SDName object. (could be null!) (0 - None) exists: bool this field is false if the station is deleted. Default: true (0 - None) """ StationListEntry = Schema( { "id": str, "name": str, "city": str, "combinedName": str, "shortcuts": [str], "aliasses": [str], "vehicleTypes": [VehicleType], "coordinate": Coordinate, "exists": bool, } ) """LSResponse The response for LSRequest with a list of stations. dataReleaseID: str result was created on this data release. (0 - None) stations: StationListEntry List of stations. This list could be empty if there is no station fitting to the given filter settings. (0 - unbounded) """ LSResponse = Schema.extend( BaseResponseType, {"dataReleaseID": str, "stations": [StationListEntry]} ) """Path description of a path from a given start to a destination with coordinates and properties. track: Coordinate Coordinates of the path (2 - unbounded) attributes: str Attributes of the track * since version 25 (0 - unbounded) """ Path = Schema( {Required("track"): All([Coordinate], Length(min=2)), "attributes": [str]} ) """ExtraFareType type of extra fare - NO extra fare is not possible or required - POSSIBLE extra fare is possible (optional first class ticket) - REQUIRED extra fare is mandatory """ ExtraFareType = In(["NO", "POSSIBLE", "REQUIRED"]) """TariffInfo Holds detail tariff informations. tariffName: str The name of the tariff (HVV, SH). (None - None) tariffRegions: TariffRegionInfo crossed tariffregions of different types (zones, rings, counties). (0 - unbounded) extraFareType: ExtraFareType is extra fare possible? if yes, is it mandatory? Default: NO (0 - None) ticketInfos: TicketInfo detailed informations about the possible and valid tickets (0 - unbounded) ticketRemarks: str Additional information about ticket. For example if it is only valid on a part of the trip. * since version 18 (0 - None) """ TariffInfo = Schema( { "tariffName": str, "tariffRegions": [TariffRegionInfo], "extraFareType": ExtraFareType, "ticketInfos": [TicketInfo], "ticketRemarks": str, } ) """TariffResponse tariffInfos: TariffInfo Tariff informations. (0 - unbounded) """ TariffResponse = Schema.extend(BaseResponseType, {"tariffInfos": [TariffInfo]}) """SDType type of location. * UNKNOWN since version 6 """ SDType = In(["UNKNOWN", "STATION", "ADDRESS", "POI", "COORDINATE"]) """SDName type for representation of starts and destinations name: str string which can be the name of station, address or poi (0 - None) city: str the city of the location (0 - None) combinedName: str combination of name and city field. * since version 6 (0 - None) id: str the unique id of a SDName object (0 - None) type: SDType the type of a SDName object, type can be: UNKNOWN, STATION , ADDRESS, POI, COORDINATE. Unknown type is only for requests. Default: UNKNOWN (0 - None) coordinate: Coordinate the coordinate of a SDName object (0 - None) tariffDetails: TariffDetails Detailed information about the tariff. (0 - None) serviceTypes: str Type of vehicles that stops at this station. (Only filled on SDType Station) * since version 16 (0 - unbounded) hasStationInformation: bool Are additional information about the station available? Can be retrieved by StationInformationRequest * since version 28 (0 - None) """ SDName = Schema( { "name": str, "city": str, "combinedName": str, "id": str, "type": SDType, "coordinate": Coordinate, "tariffDetails": TariffDetails, "serviceTypes": [str], "hasStationInformation": bool, } ) """Location type: LocationType SINGLE_LINE : the announcement concerns a single line that is given with the 'line' field ALL_LINES_OF_CARRIER: the name field contains the short name of the concerned carrier COMPLETE_NET: the name field contains the concerned net (e.g. "HVV") Default: SINGLE_LINE (0 - None) name: str Description of the location. * Isnt filled if there are line elements. (0 - None) line: Service The concerned line. * Only filled if type is SINGLE_LINE. * 'full' must be set to true to fill this element. * since version 22 (0 - None) begin: SDName First Station that is affected on the given line. * Only filled if type is SINGLE_LINE. * 'full' must be set to true to fill this element. * since version 22 (0 - None) end: SDName Last Station that is affected on the given line. * Only filled if type is SINGLE_LINE. * 'full' must be set to true to fill this element. * since version 22 (0 - None) bothDirections: bool if set to true, this announcement concerns both directions of the line. * Only relevant if type is SINGLE_LINE. * 'full' must be set to true to fill this element. * since version 22 Default: true (0 - None) """ Location = Schema( { "type": LocationType, "name": str, "line": Service, "begin": SDName, "end": SDName, "bothDirections": bool, } ) """Announcement id: str a unique announcement id. Announcement updates result in a new announcement with a new ID. (0 - None) version: int a version-number to keep track of the history (0 - None) summary: str a summarized description text if available (e.g. "Streik"). (0 - None) locations: Location a list of concerned locations. this could be a single line, all lines of one carrier or the complete net. (1 - unbounded) description: str A description text of the announcement. (None - None) links: Link Links providing further information, if available. (0 - unbounded) publication: TimeRange Publication Window for announcement. * since version 22 (None - None) validities: TimeRange Overall inclusive period of applicability of announcement. * 'full' must be set to true to fill this element. * since version 22 (None - unbounded) lastModified: DateTime Date/Time of last modification of this announcement. * since version 22 (None - None) planned: bool Is the event planned? * since Version 30 (0 - None) reason: str The reason of the announcement, in key form. Takes at the moment only the following values: - UNDEFINED_PROBLEM - ROADWORKS - CONGESTION - SPECIAL_EVENT - SLIPPERINESS - POLICE_REQUEST - FIRE_BRIGADE_SAFETY_CHECKS - STATION_OVERRUN - SERVICE_FAILURE - ROAD_CLOSED - VEHICLE_ON_THE_LINE - ACCIDENT - DEMONSTRATION - STAFF_ABSENCE - BOMB_ALERT - LOW_WATER_LEVEL - ROUTE_BLOCKAGE - ROUGH_SEA * since Version 30 (0 - None) """ Announcement = Schema( { "id": str, "version": int, "summary": str, Required("locations"): All([Location], Length(min=1)), "description": str, "links": [Link], "publication": TimeRange, "validities": [TimeRange], "lastModified": DateTime, "planned": bool, "reason": str, } ) """AnnouncementResponse announcements: Announcement A list of announcements that fits to the requested parameters. (0 - unbounded) lastUpdate: DateTime Time of last announcement update. (None - None) """ AnnouncementResponse = Schema.extend( BaseResponseType, {"announcements": [Announcement], "lastUpdate": DateTime} ) """CourseElement A course element with from- and to-station, departure time, duration, platform and optional the path. fromStation: SDName contains the departure station of the course element. In order to reduce traffic on mobile devices, only the unique combinedName will be returned. The completely filled SDName object can be requested by CNRequest. (None - None) fromPlatform: str The scheduled platform (Gleis) of this from-station. If no platform info is available this element will be null. (0 - None) fromRealtimePlatform: str The realtime platform (Gleis) of this from-station. If no realtime platform info is available this element will be null. * since version 21 (0 - None) toStation: SDName contains the arrival station of the course element. In order to reduce traffic on mobile devices, only the unique combinedName will be returned. The completely filled SDName object can be requested by CNRequest. (None - None) toPlatform: str The scheduled platform (Gleis) of this to-station. If no platform info is available this element will be null. (0 - None) toRealtimePlatform: str The realtime platform (Gleis) of this to-station. If no realtime platform info is available this element will be null. * since version 21 (0 - None) model: str The specific model type of the vehicle if applicable and available. * since API version 24 (0 - None) depTime: DateTime The departure time of the course element. (None - None) arrTime: DateTime The arrival time of the course element. (None - None) depDelay: int Realtime departure delay in seconds (if available). * since version 19 (0 - None) arrDelay: int Realtime arrival delay in seconds (if available). * since version 19 (0 - None) fromExtra: bool realtime flag to mark an additional from stop to those of the intended schedule. * since version 19 Default: false (0 - None) fromCancelled: bool realtime flag to mark a cancelled from stop. * since version 19 Default: false (0 - None) toExtra: bool realtime flag to mark an additional to stop to those of the intended schedule. * since version 19 Default: false (0 - None) toCancelled: bool realtime flag to mark a cancelled to stop. * since version 19 Default: false (0 - None) attributes: Attribute A list with additional textual informations about this leg. * since version 23 (0 - unbounded) path: Path The (optional) path between fromStation and toStation of this course element. Will only be filled if the flag showPath in the request is set to true and a path is defined for the course. (0 - 1) """ CourseElement = Schema( { "fromStation": SDName, "fromPlatform": str, "fromRealtimePlatform": str, "toStation": SDName, "toPlatform": str, "toRealtimePlatform": str, "model": str, "depTime": DateTime, "arrTime": DateTime, "depDelay": int, "arrDelay": int, "fromExtra": bool, "fromCancelled": bool, "toExtra": bool, "toCancelled": bool, "attributes": [Attribute], "path": Path, } ) """DCResponse The response for a DCRequest with a list of CourseElements. courseElements: CourseElement The list with the course elements. Will be empty in case of an error or if it is the last station (followingStations=true) or the first station (followingStations=false) (0 - unbounded) extra: bool realtime flag to mark additional journeys to those of the intended schedule. * since version 19 Default: false (0 - None) cancelled: bool realtime flag to mark cancelled journeys. * since version 19 Default: false (0 - None) attributes: Attribute A list with additional textual informations about the returned journey. * since version 23 (0 - unbounded) """ DCResponse = Schema.extend( BaseResponseType, { "courseElements": [CourseElement], "extra": bool, "cancelled": bool, "attributes": [Attribute], }, ) """BaseSchedule A schedule from start to dest with a list of legs as ScheduleElements. routeId: int The id of the route. (None - None) start: SDName The start of the schedule. (None - None) dest: SDName The destination of the schedule. (None - None) time: int The whole time (in minutes) the journey takes. (None - None) footpathTime: int The whole time for all footpaths in the journey. (None - None) tickets: Ticket DEPRECATED since API Version 13 replaced by "tariffInfos" (None - unbounded) tariffInfos: TariffInfo Tariff informations for this schedule. * select which tariff infos should be returned with the request field "tariffInfoSelection" * since version 13 (0 - unbounded) """ BaseSchedule = Schema( { "routeId": int, "start": SDName, "dest": SDName, "time": int, "footpathTime": int, "tickets": [Ticket], "tariffInfos": [TariffInfo], } ) """IndividualRoute start: SDName Start of the individual route (one of the starts from request) (None - None) dest: SDName Destination of the individual route (one of the dests from request) (None - None) path: Path Coordinate sequence that describes the path of the route * optional since version 25, replaced by paths (0 - None) paths: Path List of paths with attributes * since version 21 (0 - unbounded) length: int length of the route in meters (None - None) time: int estimated time to use individual route in seconds (None - None) serviceType: SimpleServiceType type of individual route (eg. footpath) Default: FOOTPATH (None - None) """ IndividualRoute = Schema( { "start": SDName, "dest": SDName, "path": Path, "paths": [Path], "length": int, "time": int, "serviceType": SimpleServiceType, } ) """IndividualRouteResponse response for IndividualRouteRequest routes: IndividualRoute List of individual route results (1 - unbounded) """ IndividualRouteResponse = Schema.extend( BaseResponseType, {Required("routes"): All([IndividualRoute], Length(min=1))} ) """Departure A departure with line, timeOffset and direction. line: Service The line which departs. (None - None) timeOffset: int The scheduled time in minutes when the line will depart/arrive. This value could be negative on delayed trains! (None - None) delay: int realtime delay in seconds. * since version 19 (0 - None) extra: bool realtime flag to mark additional journeys to those of the intended schedule. * since version 19 Default: false (0 - None) cancelled: bool realtime flag to mark cancelled journeys. * since version 19 Default: false (0 - None) serviceId: int A unique ID for each journey (Fahrt-ID) * since version 7 (0 - None) station: SDName contains the station of the desired changing node for this departure. Is only filled if allStationsInChangingNode in request is true. In order to reduce traffic on mobile devices, only the unique combinedName will be returned. The completely filled SDName object can be requested by CNRequest. * since version 7 (0 - None) platform: str The scheduled platform (Gleis) of this hold. If no platform info is available this element will be null. * since version 11 (0 - None) realtimePlatform: str The realtime platform (Gleis) of this hold. If no realtime platform info is available this element will be null. * since version 21 (0 - None) attributes: Attribute A list with additional textual informations about this journey. * since version 23 (0 - unbounded) """ Departure = Schema( { "line": Service, "timeOffset": int, "delay": int, "extra": bool, "cancelled": bool, "serviceId": int, "station": SDName, "platform": str, "realtimePlatform": str, "attributes": [Attribute], } ) """DLResponse The response for a DLRequest with a list of Departures. time: GTITime The time when the departure list is requested. (None - None) departures: Departure The resulting list of departures or arrivals. (0 - unbounded) filter: DLFilterEntry A list of possible values for DLFilterEntries for the given request. Will be filled if 'returnFilters' in request is set to true! * since Version 20 (0 - unbounded) serviceTypes: FilterServiceType A list of servicetypes that serves this station. * since version 22 (0 - unbounded) """ DLResponse = Schema.extend( BaseResponseType, { "time": GTITime, "departures": [Departure], "filter": [DLFilterEntry], "serviceTypes": [FilterServiceType], }, ) """RegionalSDName distance: int The distance from the coordinate sent in the request to this SDName. The client has to know the coordinate. (0 - None) time: int The travel time from the coordinate to this SDName. (0 - None) """ RegionalSDName = Schema.extend(SDName, {"distance": int, "time": int}) """CNResponse The response for a CNRequest with a list of SDNames. results: RegionalSDName The list with the SDName objects. (0 - unbounded) """ CNResponse = Schema.extend(BaseResponseType, {"results": [RegionalSDName]}) """JourneySDName arrTime: GTITime The arrival time for this location. In most cases only one of dep- and arrTime will be used. (0 - None) depTime: GTITime The departure time for this location (0 - None) arrDelay: int Realtime arrival delay in seconds (if available). * since version 19 (0 - None) depDelay: int Realtime departure delay in seconds (if available). * since version 19 (0 - None) extra: bool realtime flag to mark additional stops to those of the intended schedule. * since version 19 Default: false (0 - None) cancelled: bool realtime flag to mark cancelled stops. * since version 19 Default: false (0 - None) attributes: Attribute A list with attributes. (0 - unbounded) platform: str The scheduled platform (Gleis) of this hold. If no platform info is available this element will be null. * since version 11 (0 - None) realtimePlatform: str The realtime platform (Gleis) of this hold. If no realtime platform info is available this element will be null. * since version 21 (0 - None) """ JourneySDName = Schema.extend( SDName, { "arrTime": GTITime, "depTime": GTITime, "arrDelay": int, "depDelay": int, "extra": bool, "cancelled": bool, "attributes": [Attribute], "platform": str, "realtimePlatform": str, }, ) """ScheduleElement One element of a schedule with from/to SDNames, departure/arrival times and line from: JourneySDName The leg starts here. (None - None) to: JourneySDName The leg ends here. (None - None) line: Service The line/service which is used for this leg. (None - None) paths: Path A list of possible paths from start to destination of this element. * since version 2 (0 - unbounded) attributes: Attribute A list with attributes. (0 - unbounded) extra: bool realtime flag to mark additional journeys to those of the intended schedule. * since version 19 Default: false (0 - None) cancelled: bool realtime flag to mark cancelled journeys. * since version 19 Default: false (0 - None) intermediateStops: JourneySDName A list of all intermediate stops between start and end station. * since version 24 (0 - unbounded) serviceId: int the service-id of the journey * since version 29 (0 - None) shopInfo: ShopInfo Information about the shop, where a ticket for this journey could be bought. (0 - unbounded) """ ScheduleElement = Schema( { "from": JourneySDName, "to": JourneySDName, "line": Service, "paths": [Path], "attributes": [Attribute], "extra": bool, "cancelled": bool, "intermediateStops": [JourneySDName], "serviceId": int, "shopInfo": [ShopInfo], } ) """Schedule scheduleElements: ScheduleElement The legs between start and dest. (0 - unbounded) contSearchBefore: ContSearchByServiceId cont-search data for a possible earlier schedule * since version 29 (0 - None) contSearchAfter: ContSearchByServiceId cont-search data for a possible later schedule * since version 29 (0 - None) """ Schedule = Schema.extend( BaseSchedule, { "scheduleElements": [ScheduleElement], "contSearchBefore": ContSearchByServiceId, "contSearchAfter": ContSearchByServiceId, }, ) """GRResponse The response for a GRRequest with a list of schedules. schedules: Schedule A list of schedules with all legs. Realtime-Informations where not considered to calculate this schedules. (0 - unbounded) realtimeSchedules: Schedule A list of schedules with all legs. This schedules where calculated under consideration of realtime data. Type of realtime consideration could be configured by realtime field in request. * since version 19 (0 - unbounded) realtimeAffected: bool Returns true if the realtime result differes from plandata result. * since version 19 Default: false (0 - None) individualTrack: IndividualTrack Informations about an individual track (footpath, bike) for comparison to the public transport route. * since version 19 (0 - None) """ GRResponse = Schema.extend( BaseResponseType, { "schedules": [Schedule], "realtimeSchedules": [Schedule], "realtimeAffected": bool, "individualTrack": IndividualTrack, }, ) """FilterType Enumeration with all possible filter types. -NO_FILTER: No filter for the result activated. -HVV_LISTED: Return only stations, lines etc. belonging to HVV. """ FilterType = In(["NO_FILTER", "HVV_LISTED"]) """BaseRequestType language: str Language in which the server will respond. (de/en) Default: de (0 - None) version: int Used version of GeofoxThinInterface on Client. Default: 1 (0 - None) filterType: FilterType Sets the filter for the result. Default: NO_FILTER (None - None) """ BaseRequestType = Schema({"language": str, "version": int, "filterType": FilterType}) """SingleTicketOptimizerRequest Request for the TariffOptimizer withReturnJourney: bool Specifies whether the tickets should also be valid for the return journey (None - None) numberOfAdults: int Number of traveling adults (None - None) numberOfChildren: int Number of traveling children (None - None) tickets: TariffOptimizerTicket Tickets owned by user (0 - unbounded) route: SingleTicketOptimizerRequestRoute The route for which a fare is searched (None - None) """ SingleTicketOptimizerRequest = Schema.extend( BaseRequestType, { "withReturnJourney": bool, "numberOfAdults": int, "numberOfChildren": int, "tickets": [TariffOptimizerTicket], "route": SingleTicketOptimizerRequestRoute, }, ) """TicketListRequest request a list of all HVV tickets. stationKey: str The key of the station as used in Geofox (e.g. Master:12345) (0 - 1) """ TicketListRequest = Schema.extend(BaseRequestType, {"stationKey": str}) """TrackCoordinatesRequest request the coordinates for tracks coordinateType: CoordinateType The Projection in that the result should be projected Default: EPSG_4326 (0 - None) stopPointKeys: str The keys of the stopPoints; in blocks of 2; each block identifies a track (2 - unbounded) """ TrackCoordinatesRequest = Schema.extend( BaseRequestType, { "coordinateType": CoordinateType, Required("stopPointKeys"): All([str], Length(min=2)), }, ) """VehicleMapRequest request All Vehicles(and its Journey) in a specified Area at a specified period boundingBox: BoundingBox requested area (None - None) periodBegin: int timestamp begin of period (None - None) periodEnd: int timestamp end of period (None - None) withoutCoords: bool whether the response should not contain coordinates (None - None) coordinateType: CoordinateType The Projection in that the result should be projected Default: EPSG_4326 (0 - None) vehicleTypes: VehicleType requested types of vehicles (bus, s-bahn,...) (0 - unbounded) realtime: bool consider realtime informations (0 - None) """ VehicleMapRequest = Schema.extend( BaseRequestType, { "boundingBox": BoundingBox, "periodBegin": int, "periodEnd": int, "withoutCoords": bool, "coordinateType": CoordinateType, "vehicleTypes": [VehicleType], "realtime": bool, }, ) """StationInformationRequest station: SDName The station to get additional information about (None - None) """ StationInformationRequest = Schema.extend(BaseRequestType, {"station": SDName}) """PCRequest postalCode: int The postal code to check for intersection with the HVV area (None - None) """ PCRequest = Schema.extend(BaseRequestType, {"postalCode": int}) """AnnouncementRequest names: str Names of lines or carriers for which announcements are requested. (0 - unbounded) timeRange: TimeRange the time range for which announcements are requested (0 - None) full: bool If true, the result will contain detailed location and validity informations Default: false (0 - None) filterPlanned: AnnouncementFilterPlannedType Should and how the announcements are to be filtered concerning their planned flag. * since Version 30 (0 - None) """ AnnouncementRequest = Schema.extend( BaseRequestType, { "names": [str], "timeRange": TimeRange, "full": bool, "filterPlanned": AnnouncementFilterPlannedType, }, ) """LLRequest List Lines Request. Returns a filtered list of lines. withSublines: bool Indicates whether the sublines should be returned too. Enabling this flag can increase the amount of data. (None - None) dataReleaseID: str return all modified lines since this release. this request will return all lines if this field is null. (0 - None) modificationTypes: LineModificationType result only contains lines that are modified on one of the given types. Only fields that belongs to the requested types are filled in result. if this field is null/empty, all modifications will be considered. (0 - unbounded) """ LLRequest = Schema.extend( BaseRequestType, { "withSublines": bool, "dataReleaseID": str, "modificationTypes": [LineModificationType], }, ) """LSRequest List Stations Request. Returns a filtered list of stations. dataReleaseID: str return all modified stations since this release. this request will return all stations if this field is null. (0 - None) modificationTypes: ModificationType result only contains stations that are modified on one of the given types. Only fields that belongs to the requested types are filled in result. if this field is null/empty, all modifications will be considered. (0 - unbounded) coordinateType: CoordinateType The type of the coordinate which the server should use in the response. Default: EPSG_4326 (0 - None) filterEquivalent: bool In Geofox bus stops and train stations does not belong together to one station. For example the subway station "Niendorf Nord" and the bus station "U Niendorf Nord" are two different stations. With parameter "filterEquivalent" on true those stations will be merged to one station with vehicle types of both and with the name of the train station. * since API version 17 Default: false (0 - None) """ LSRequest = Schema.extend( BaseRequestType, { "dataReleaseID": str, "modificationTypes": [ModificationType], "coordinateType": CoordinateType, "filterEquivalent": bool, }, ) """DCRequest Departure course request. Get a list of positions related to a given Departure. lineKey: str The key (string) of the line. For Example: HHA-U:U1_HHA-U, DB-EFZ:A3_DB-EFZ_Z, VHH:569_VHH etc. (None - None) station: SDName contains the station for this departure (relates to line/direction/time) In order to reduce traffic on mobile devices, only the name/ID is needed/used. (None - None) time: DateTime The departure date/time for this journey of the given line/direction/station. If the serviceId is set, only the date is relevant. (None - None) direction: str The direction where the line is headed. (0 - None) origin: str The origin where the line comes from. (0 - None) serviceId: int A unique ID for the journey (Fahrt-ID). either serviceId or direction has to be set. Default: -1 (0 - None) segments: SegmentSelector Defines whether the course starting from the given station to the end is shown (AFTER) or the portion from the beginning until the given station (BEFORE) or all stations (ALL). Default: ALL (0 - None) showPath: bool Defines whether the coordinate path is returned together with the textual information of the course. Default is false. Default: false (0 - None) coordinateType: CoordinateType The type of the coordinate which the server should use in the response. Default: EPSG_4326 (0 - None) """ DCRequest = Schema.extend( BaseRequestType, { "lineKey": str, "station": SDName, "time": DateTime, "direction": str, "origin": str, "serviceId": int, "segments": SegmentSelector, "showPath": bool, "coordinateType": CoordinateType, }, ) """InitRequest properties: Property An optional list of properties (only key has to be set). The server will response the properties (including the value) which are defined here. (0 - unbounded) """ InitRequest = Schema.extend(BaseRequestType, {"properties": [Property]}) """IndividualRouteRequest request for calculating an individual route (eg. footpath) starts: SDName List of possible start positions. There will be calculated the shorted path from every start to its nearest destinations. If maxLength or maxResults is used, there could be starts without routes in result. (0 - unbounded) dests: SDName List of possible destinations. (0 - unbounded) maxLength: int Maximum length of the resulting routes in meters. If this parameter is set, the result will not contain any route longer than this value. (0 - None) maxResults: int The maximum number of results is limited to this value. Only the shortest n Routes will be returned. (0 - None) type: CoordinateType Designated coordinate system of the resulting routes. Default is wgs84 (EPSG:4326). Default: EPSG_4326 (0 - None) serviceType: SimpleServiceType Type of individual route (footpath or bicycle). * optional since version 25 Default: FOOTPATH (0 - None) profile: IndividualProfileType Specify a certain profile to use for routing. * since version 25 Default: FOOT_NORMAL (0 - None) speed: str Specify a certain driving speed for bicycle routing. Default: NORMAL (0 - None) """ IndividualRouteRequest = Schema.extend( BaseRequestType, { "starts": [SDName], "dests": [SDName], "maxLength": int, "maxResults": int, "type": CoordinateType, "serviceType": SimpleServiceType, "profile": IndividualProfileType, "speed": str, }, ) """DLRequest Departure list request. Get a list of departures at a given time for a given station. station: SDName The station the departures are requested for. (0 - 1) stations: SDName (0 - unbounded) time: GTITime The time for the request. Including date and time. (None - None) maxList: int The maximum number of elements the result may have. (None - None) maxTimeOffset: int The maximum offset of a result in minutes. Default: 120 (None - 1) allStationsInChangingNode: bool If this is set to true and the given station is a changing node with equivalent stations (e.g. Wedel and S Wedel), the result would contain departures of all equivalent stations. Default is true. Default: true (0 - None) useRealtime: bool true = server is calculating a result based on realtime data. false = server only uses plan data for calculating result. Default: false (0 - None) returnFilters: bool if true, a list of possible DLFilterEntries for this request will be returned. Default: false (0 - None) filter: DLFilterEntry List of filter entries that contains lines and directions/stations. Only Departures that fits to any of these filter entries will be returned. An empty list will deactivate the filter. * since Version 20 (0 - unbounded) serviceTypes: FilterServiceType A list of servicetypes to filter the result list. * since version 22 (0 - unbounded) departure: bool if false, an arrival list will be returned instead of a departure list. Default: true (0 - None) """ DLRequest = Schema.extend( BaseRequestType, { "station": SDName, "stations": [SDName], "time": GTITime, "maxList": int, "maxTimeOffset": int, "allStationsInChangingNode": bool, "useRealtime": bool, "returnFilters": bool, "filter": [DLFilterEntry], "serviceTypes": [FilterServiceType], "departure": bool, }, ) """CNRequest The check name request. The different types of requests are defined by the SDName object possible types are: - Type STATION * name / city is set: the results are SDNames that match the name / city of the station * coordinate is set: the results are stations in the vicinity (use maxDistance) of the coordinate - Type POI * name / city is set: the results are SDNames that match the name / city of the POI - Type ADDRESS * name / city is set: the results are SDNames that match the name / city of the address - Type COORDINATE * coordinate is set: the result is the nearest address to the coordinate (if available) Type is always required. theName: SDName SDName object with the data to check. (None - None) maxList: int The maximum number of elements the result may have. (None - None) maxDistance: int The maximum distance (in meters) of stations that will be returned in a search for stations near to a coordinate. (0 - None) coordinateType: CoordinateType The type of the coordinate which the server should use in the response. Default: EPSG_4326 (0 - None) tariffDetails: bool Flag if detailed tariff information should be transferred. Default is false. Default: false (0 - None) allowTypeSwitch: bool Flag if the server is allowed to offer results with different SDTypes than in the request. Default is true. Default: true (0 - None) """ CNRequest = Schema.extend( BaseRequestType, { "theName": SDName, "maxList": int, "maxDistance": int, "coordinateType": CoordinateType, "tariffDetails": bool, "allowTypeSwitch": bool, }, ) """TariffRequestType scheduleElements: ScheduleElementLight Requests the tariff for this schedule. Only public transport schedule elements are allowed (no footpathes). To reduce size of request, only id fields of stations and lines are necessary. (1 - unbounded) departure: GTITime Date and time of first departure in scheduleElements. (None - None) arrival: GTITime Date and time of last arrival in scheduleElements. (None - None) returnReduced: bool Additionally returns reduced prices for online tickets. * since version 16 Default: false (0 - None) returnPartialTickets: bool if value is false, the tariff informations will not contain any tickets for parts of the route. In this case all returned tickets are valid for the complete route. Default: true (0 - None) """ TariffRequestType = Schema.extend( BaseRequestType, { Required("scheduleElements"): All([ScheduleElementLight], Length(min=1)), "departure": GTITime, "arrival": GTITime, "returnReduced": bool, "returnPartialTickets": bool, }, ) """GRRequest The request for a route. SDName objects will be transferred. start: SDName The SDName of the start station. (None - None) dest: SDName The SDName of the destination station. (None - None) via: SDName The optional SDName of the via station. Type is always STATION. (0 - None) time: GTITime The time for the request. May be departure or arrival, depending on flag isDeparture. (None - None) timeIsDeparture: bool Flag which defines if a time is departure or arrival. (None - None) numberOfSchedules: int The desired number of schedules in the response. May be less. (None - None) penalties: Penalty If no penalty is set, defaults will be used. (0 - unbounded) tariffDetails: bool Flag if detailed tariff information should be transferred. Default is false. Default: false (0 - None) continousSearch: bool Flag if a search is continous. Is used for later/earlier search. Default: false (0 - None) contSearchByServiceId: ContSearchByServiceId This field contains the information to identify the service to start AFTER/BEFORE * since Version 29 (0 - None) coordinateType: CoordinateType The type of the coordinate which the server should use in the response. Default: EPSG_4326 (0 - None) schedulesBefore: int The desired number of schedules before the actual resulting route. Default: 0 (0 - None) schedulesAfter: int The desired number of schedules after the actual resulting route. Default: 0 (0 - None) tariffInfoSelector: TariffInfoSelector Returns Ticketinfos (in schedule) for each of this tariffs and kinds, if the given tariff and kind is valid on the returned schedule. * since version 13 (0 - unbounded) returnReduced: bool Additionally returns reduced prices for online tickets. * since version 16 Default: false (0 - None) returnPartialTickets: bool if value is false, the tariff informations will not contain any tickets for parts of the route. In this case all returned tickets are valid for the complete route. Default: true (0 - None) realtime: RealtimeType Configures the consideration of realtime informations during route calculation. * since version 19 Default: AUTO (0 - None) intermediateStops: bool Additionally returns all intermediate stops between start and end station. * since version 24 Default: false (0 - None) useStationPosition: bool Allows the journey to start/end at stations in the neighborhood of "start"/"dest". * since version 27 Default: true (0 - None) forcedStart: SDName Setting this field forces the result to start at "forcedStart", regardless of the "useStationPosition" flag. * since version 27 (0 - None) forcedDest: SDName Setting this field forces the result to end at "forcedDest", regardless of the "useStationPosition" flag. * since version 27 (0 - None) toStartBy: SimpleServiceType Sets the method to get to the start station. Could be either "FOOTPATH" or "BICYCLE", otherwise an error is returned. * since version 27 (0 - None) toDestBy: SimpleServiceType Sets the method to get to the destination station. Could be either "FOOTPATH" or "BICYCLE", otherwise an error is returned. * since version 27 (0 - None) returnContSearchData: bool returns additional cont search data * since version 29 (0 - None) """ GRRequest = Schema.extend( BaseRequestType, { "start": SDName, "dest": SDName, "via": SDName, "time": GTITime, "timeIsDeparture": bool, "numberOfSchedules": int, "penalties": [Penalty], "tariffDetails": bool, "continousSearch": bool, "contSearchByServiceId": ContSearchByServiceId, "coordinateType": CoordinateType, "schedulesBefore": int, "schedulesAfter": int, "tariffInfoSelector": [TariffInfoSelector], "returnReduced": bool, "returnPartialTickets": bool, "realtime": RealtimeType, "intermediateStops": bool, "useStationPosition": bool, "forcedStart": SDName, "forcedDest": SDName, "toStartBy": SimpleServiceType, "toDestBy": SimpleServiceType, "returnContSearchData": bool, }, ) """ReturnCode Enumeration with all possible return codes. -OK: successful -ERROR_ROUTE: server was unable to calculate route -ERROR_COMM: communication failed -ERROR_CN_TOO_MANY: The request information is not enough precise. More infos needed to check station. -ERROR_TEXT: unknown error with text -START_DEST_TOO_CLOSE: Start and destination are too close. The direct footway will be returned instead. * Deprecated since Version 21 * """ ReturnCode = In( [ "OK", "ERROR_ROUTE", "ERROR_COMM", "ERROR_CN_TOO_MANY", "ERROR_TEXT", "START_DEST_TOO_CLOSE", ] ) """ErrorType returnCode: ReturnCode The return code of the operation. (None - None) errorText: str User friendly textmessage that describes an error (on returnCodes != OK). (0 - None) errorDevInfo: str additional error information for developer. This info ist not intended to be read by the user. * since version 15 (0 - None) """ ErrorType = Schema({"returnCode": ReturnCode, "errorText": str, "errorDevInfo": str}) pygti-0.10.0/pytest.ini000066400000000000000000000001361442343737200147660ustar00rootroot00000000000000[pytest] markers = schema: checks if schemas are correct (deselect with '-m "not schema"')pygti-0.10.0/requirements_dev.txt000066400000000000000000000000221442343737200170510ustar00rootroot00000000000000xsd-to-vol==0.0.6 pygti-0.10.0/requirements_test.txt000066400000000000000000000000331442343737200172540ustar00rootroot00000000000000black==20.8b1 isort==5.6.3 pygti-0.10.0/script/000077500000000000000000000000001442343737200142415ustar00rootroot00000000000000pygti-0.10.0/script/generate.py000066400000000000000000000010401442343737200164000ustar00rootroot00000000000000"""Generate library files based on the GTI WADL/XSD.""" import asyncio import aiohttp from xsd_to_vol import xsd_to_vol async def generate(): async with aiohttp.ClientSession() as session: url = "https://api-prod.geofox.de/gti/public/geofoxThinInterfacePublic.xsd" async with session.get(url) as resp: if resp.status == 200: xsd = await resp.read() with open("pygti/schemas.py", "w") as vol_file: vol_file.write(xsd_to_vol(xsd)) asyncio.run(generate()) pygti-0.10.0/setup.cfg000066400000000000000000000001411442343737200145520ustar00rootroot00000000000000[isort] known_first_party = pygti multi_line_output=3 include_trailing_comma=true line_length=88 pygti-0.10.0/setup.py000066400000000000000000000071221442343737200144510ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Note: To use the 'upload' functionality of this file, you must: # $ pipenv install twine --dev import io import os import sys from shutil import rmtree from setuptools import Command, find_packages, setup # Package meta-data. NAME = "pygti" DESCRIPTION = "access public transport information in hamburg, germany." URL = "https://github.com/vigonotion/pygti" EMAIL = "mail@vigonotion.com" AUTHOR = "Tom Schneider" REQUIRES_PYTHON = ">=3.6.0" VERSION = "0.8.0" # What packages are required for this module to be executed? REQUIRED = ["aiohttp", "voluptuous", "pytz"] # What packages are optional? EXTRAS = { # 'fancy feature': ['django'], } # The rest you shouldn't have to touch too much :) # ------------------------------------------------ # Except, perhaps the License and Trove Classifiers! # If you do change the License, remember to change the Trove Classifier for that! here = os.path.abspath(os.path.dirname(__file__)) # Import the README and use it as the long-description. # Note: this will only work if 'README.md' is present in your MANIFEST.in file! try: with io.open(os.path.join(here, "README.md"), encoding="utf-8") as f: long_description = "\n" + f.read() except FileNotFoundError: long_description = DESCRIPTION # Load the package's __version__.py module as a dictionary. about = {} if not VERSION: project_slug = NAME.lower().replace("-", "_").replace(" ", "_") with open(os.path.join(here, project_slug, "__version__.py")) as f: exec(f.read(), about) else: about["__version__"] = VERSION class UploadCommand(Command): """Support setup.py upload.""" description = "Build and publish the package." user_options = [] @staticmethod def status(s): """Prints things in bold.""" print("\033[1m{0}\033[0m".format(s)) def initialize_options(self): pass def finalize_options(self): pass def run(self): try: self.status("Removing previous builds…") rmtree(os.path.join(here, "dist")) except OSError: pass self.status("Building Source and Wheel (universal) distribution…") os.system("{0} setup.py sdist bdist_wheel --universal".format(sys.executable)) self.status("Uploading the package to PyPI via Twine…") os.system("twine upload dist/*") self.status("Pushing git tags…") os.system("git tag v{0}".format(about["__version__"])) os.system("git push --tags") sys.exit() # Where the magic happens: setup( name=NAME, use_scm_version=True, setup_requires=["setuptools_scm"], description=DESCRIPTION, long_description=long_description, long_description_content_type="text/markdown", author=AUTHOR, author_email=EMAIL, python_requires=REQUIRES_PYTHON, url=URL, packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]), entry_points={}, install_requires=REQUIRED, extras_require=EXTRAS, include_package_data=True, license="Apache-2.0", classifiers=[ # Trove classifiers # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ], # $ setup.py publish support. cmdclass={"upload": UploadCommand}, ) pygti-0.10.0/tox.ini000066400000000000000000000003011442343737200142420ustar00rootroot00000000000000# content of: tox.ini , put in same dir as setup.py [tox] envlist = py36,py38 [testenv] deps = -rrequirements_test.txt commands = black --check --diff pygti isort -c --recursive pygti