pax_global_header00006660000000000000000000000064145333410040014507gustar00rootroot0000000000000052 comment=1f10a27f3fff20b5bf4d34c99a394f1db7229da2 python-overpy-0.7/000077500000000000000000000000001453334100400142205ustar00rootroot00000000000000python-overpy-0.7/.coveragerc000066400000000000000000000000261453334100400163370ustar00rootroot00000000000000[run] source = overpy python-overpy-0.7/.flake8000066400000000000000000000002251453334100400153720ustar00rootroot00000000000000# SPDX-FileCopyrightText: none # SPDX-License-Identifier: CC0-1.0 [flake8] max-line-length = 120 extend-exclude = venv/ docs/source/conf.py python-overpy-0.7/.github/000077500000000000000000000000001453334100400155605ustar00rootroot00000000000000python-overpy-0.7/.github/ISSUE_TEMPLATE.md000066400000000000000000000017421453334100400202710ustar00rootroot00000000000000 ##### Issue type - Bug Report - Feature Idea - Documentation Report ##### OverPy version ``` ``` ##### OS - Ubuntu 14.04 - Ubuntu 16.04 - Debian 8.0 #### Python version - Python 2.7 - Python 3.2 - Python 3.3 - Python 3.4 - Python 3.5 ##### Summary ##### Steps to reproduce ##### Expected results ##### Actual results python-overpy-0.7/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000004771453334100400213710ustar00rootroot00000000000000##### Issue type - Feature - Bugfix - Documentation - ... ##### Summary python-overpy-0.7/.github/workflows/000077500000000000000000000000001453334100400176155ustar00rootroot00000000000000python-overpy-0.7/.github/workflows/ci.yml000066400000000000000000000031111453334100400207270ustar00rootroot00000000000000# SPDX-FileCopyrightText: none # SPDX-License-Identifier: CC0-1.0 name: Python CI Tests on: push: branches: - master paths-ignore: - 'docs/**' - '*.md' - '*.rst' pull_request: branches: - master paths-ignore: - 'docs/**' - '*.md' - '*.rst' jobs: tests: name: "Python ${{ matrix.name }} on ${{ matrix.os }}" runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: include: - {name: Linux, python: '3.9', os: ubuntu-latest, tox: py39} - {name: Windows, python: '3.9', os: windows-latest, tox: py39} # ToDo: There are errors on Mac, but I don't know why: Connection timeout or reset # - {name: Mac, python: '3.9', os: macos-latest, tox: py39} - {name: '3.11', python: '3.11', os: ubuntu-latest, tox: py311} - {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310} - {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39} - {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38} - {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37} - {name: 'PyPy 3.9', python: pypy3.9, os: ubuntu-latest, tox: pypy39} steps: - uses: "actions/checkout@v3" - uses: "actions/setup-python@v4" with: python-version: ${{ matrix.python }} cache: 'pip' # caching pip dependencies - name: Install tox and any other packages run: pip install tox - name: "Run tox targets for ${{ matrix.python }}" run: tox -e ${{ matrix.tox }} python-overpy-0.7/.github/workflows/codeql-analysis.yml000066400000000000000000000044711453334100400234360ustar00rootroot00000000000000# For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: branches: [ master ] pull_request: # The branches below must be a subset of the branches above branches: [ master ] schedule: - cron: '36 17 * * 1' jobs: analyze: name: Analyze runs-on: ubuntu-latest strategy: fail-fast: false matrix: language: [ 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - name: Checkout repository uses: actions/checkout@v2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 python-overpy-0.7/.github/workflows/pypi.yml000066400000000000000000000032151453334100400213220ustar00rootroot00000000000000# SPDX-FileCopyrightText: none # SPDX-License-Identifier: CC0-1.0 name: Publish Python distributions to PyPI and TestPyPI on: pull_request: push: branches: - main - master tags: - 0.* - 1.* jobs: build-n-publish: name: Build and publish Python distributions to PyPI and TestPyPI runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Get history and tags for SCM versioning to work run: | git fetch --prune --unshallow git fetch --depth=1 origin +refs/tags/*:refs/tags/* - name: Set up Python 3.10 uses: actions/setup-python@v3 with: python-version: "3.10" - name: Install pypa/build run: python -m pip install build twine --user - name: Build binary wheel and a source tarball run: python -m build --sdist --wheel --outdir dist/ . - name: Check wheels and source tarballs run: python -m twine check dist/* # The project name os blocked by an other test project # - name: Publish distribution to Test PyPI # if: >- # github.event_name == 'push' && # github.ref == 'refs/heads/main' # uses: pypa/gh-action-pypi-publish@release/v1 # with: # password: ${{ secrets.TEST_PYPI_API_TOKEN }} # repository_url: https://test.pypi.org/legacy/ # skip-existing: true # - name: Publish distribution to PyPI if: >- github.event_name == 'push' && startsWith(github.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_API_TOKEN }} python-overpy-0.7/.gitignore000066400000000000000000000074431453334100400162200ustar00rootroot00000000000000### Python template # 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/ 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 *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .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 # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff .idea/**/workspace.xml .idea/**/tasks.xml .idea/**/usage.statistics.xml .idea/**/dictionaries .idea/**/shelf # Generated files .idea/**/contentModel.xml # Sensitive or high-churn files .idea/**/dataSources/ .idea/**/dataSources.ids .idea/**/dataSources.local.xml .idea/**/sqlDataSources.xml .idea/**/dynamic.xml .idea/**/uiDesigner.xml .idea/**/dbnavigator.xml # Gradle .idea/**/gradle.xml .idea/**/libraries # Gradle and Maven with auto-import # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. # .idea/artifacts # .idea/compiler.xml # .idea/jarRepositories.xml # .idea/modules.xml # .idea/*.iml # .idea/modules # *.iml # *.ipr # CMake cmake-build-*/ # Mongo Explorer plugin .idea/**/mongoSettings.xml # File-based project format *.iws # IntelliJ out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties # Editor-based Rest Client .idea/httpRequests # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser ### Vim template # Swap [._]*.s[a-v][a-z] !*.svg # comment out if you don't need vector files [._]*.sw[a-p] [._]s[a-rt-v][a-z] [._]ss[a-gi-z] [._]sw[a-p] # Session Session.vim Sessionx.vim # Temporary .netrwhist *~ # Auto-generated tag files tags # Persistent undo [._]*.un~ python-overpy-0.7/.pre-commit-config.yaml000066400000000000000000000073541453334100400205120ustar00rootroot00000000000000# SPDX-FileCopyrightText: none # SPDX-License-Identifier: CC0-1.0 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: # Prevent giant files from being committed - id: check-added-large-files # Simply check whether files parse as valid python - id: check-ast # Require literal syntax when initializing empty or zero Python builtin types - id: check-builtin-literals # Check for files that would conflict in case-insensitive filesystems - id: check-case-conflict # Checks for a common error of placing code before the docstring - id: check-docstring-first # Ensures that (non-binary) executables have a shebang - id: check-executables-have-shebangs # Check for files that contain merge conflict strings - id: check-merge-conflict # Checks that scripts with shebangs are executable - id: check-shebang-scripts-are-executable # Checks for symlinks which do not point to anything - id: check-symlinks # This hook checks yaml files for parseable syntax - id: check-yaml # Check for debugger imports and py37+ breakpoint() calls in python source - id: debug-statements # Detects the presence of private keys - id: detect-private-key # Ensures that a file is either empty, or ends with one newline - id: end-of-file-fixer exclude: ^tests/(json|response|xml)/ # Replaces or checks mixed line ending - id: mixed-line-ending exclude: ^tests/(json|response|xml)/ # This hook trims trailing whitespace - id: trailing-whitespace exclude: ^tests/(json|response|xml)/ - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: # Enforce that `noqa` annotations always occur with specific codes - id: python-check-blanket-noqa # Enforce that # type: ignore annotations always occur with specific codes - id: python-check-blanket-type-ignore # Prevent common mistakes of `assert mck.not_called()`, `assert mck.called_once_with(...)` and `mck.assert_called` - id: python-check-mock-methods # A quick check for the `eval()` built-in function - id: python-no-eval # A quick check for the deprecated `.warn()` method of python loggers - id: python-no-log-warn # Enforce that python3.6+ type annotations are used instead of type comments - id: python-use-type-annotations # Detect common mistake of using single backticks when writing rst - id: rst-backticks # Detect mistake of rst directive not ending with double colon - id: rst-directive-colons # Detect mistake of inline code touching normal text in rst - id: rst-inline-touching-normal # Forbid files which have a UTF-8 Unicode replacement character - id: text-unicode-replacement-char - repo: https://github.com/PyCQA/flake8 rev: 6.1.0 hooks: - id: flake8 additional_dependencies: - flake8-bugbear - flake8-implicit-str-concat - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.6.0 hooks: - id: mypy args: [--no-strict-optional, --ignore-missing-imports, --allow-untyped-global] exclude: ^(docs/) # # Check for missing licensing and copyright information. # # The REUSE helper tool assists with achieving and confirming REUSE compliance. # # See: https://reuse.software/ # - repo: https://github.com/fsfe/reuse-tool # rev: v1.1.2 # hooks: # - id: reuse # exclude: ^tests/(json|response|xml)/ ci: autofix_commit_msg: | * - auto fixes from pre-commit hooks for more information, see https://pre-commit.ci autofix_prs: false autoupdate_commit_msg: 'ci - pre-commit autoupdate' python-overpy-0.7/.readthedocs.yaml000066400000000000000000000007611453334100400174530ustar00rootroot00000000000000# .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/source/conf.py # Optionally build your docs in additional formats such as PDF formats: all # Optionally set the version of Python and requirements required to build your docs python: version: 3.7 install: - requirements: docs/requirements.txt python-overpy-0.7/CHANGELOG.rst000066400000000000000000000034031453334100400162410ustar00rootroot00000000000000Changelog ========= 0.x (`master`_) ~~~~~~~~~~~~~~~ .. note:: This version is not yet released and is under development. 0.7 (2023-12-04) ~~~~~~~~~~~~~~~~ * Add type hints * Update requirements to 3.6.2+ * Update docs to use type hints * Update CI pipelines * Add automated upload to PyPI * Build wheels 0.6 (2021-04-20) ~~~~~~~~~~~~~~~~ * Drop Python 2.7 support * Replace Travis CI with GitHub Actions * Change ThreadedHTTPServer to HTTPServer for tests * Add CodeQL CI tests * Add pre-commit * Improve build steps 0.5 (2021-04-14) ~~~~~~~~~~~~~~~~ * Add support to retry a failed request * Improve test handlers to fix issues with Py2.7 and PyPy * Improve tests * Add Support for Python 3.6 * Add function to handle remark tags and elements * Add support to parse data from ET.Element * Move attribute modifiers from class to package * Change to use Exception instead of BaseException 0.4 (2016-12-08) ~~~~~~~~~~~~~~~~ * Add SAX parser * Add option to choose DOM or SAX parser * Fix issues with CI builds with Python 3.2 * Add Python 3.5 to CI builds * Fix issues (Thanks to all contributors) * Add property for default API URL * Add examples * Build Fixes * GitHub templates * Parse center information * Parse geometry information * Support Areas 0.3.1 (2015-04-30) ~~~~~~~~~~~~~~~~~~ * Improve example 0.3.0 (2015-04-30) ~~~~~~~~~~~~~~~~~~ * Improve internal data handling (Dominik) * Add helper functions (Morris Jobke) 0.2.0 (2014-12-27) ~~~~~~~~~~~~~~~~~~ * Added support for xml response data * Added support for exceptions * Added tests with 100% code coverage * Removed Python 2.6 support * Added more examples to the documentation 0.1.0 (2014-12-14) ~~~~~~~~~~~~~~~~~~ Proof of concept * Initial release. .. _`master`: https://github.com/DinoTools/python-overpy python-overpy-0.7/CONTRIBUTING.rst000066400000000000000000000024351453334100400166650ustar00rootroot00000000000000Contributing ============ First of all, thank you for your interest in contributing to OverPy! Filing bug reports ------------------ Bug reports are very welcome. Please fill them on the `GitHub issue tracker`_. Good bug reports come with extensive descriptions of the error and how to reproduce it. Patches ------- All patches to OverPy should be submitted in the form of pull requests to the main OverPy repository, `DinoTools/python-overpy`_. These pull requests should satisfy the following properties: Code ^^^^ - The pull request should focus on one particular improvement to OverPy. - Create different pull requests for unrelated features or bugfixes. - Python code should follow `PEP 8`_, especially in the "do what code around you does" sense. Documentation ^^^^^^^^^^^^^ When introducing new functionality, please remember to write documentation. Tests ^^^^^ It is recommended to add tests for new code you add. Review ------ Finally, pull requests must be reviewed before merging. Everyone can perform reviews; this is a very valuable way to contribute, and is highly encouraged. .. _GitHub issue tracker: https://github.com/DinoTools/python-overpy/issues .. _DinoTools/python-overpy: https://github.com/DinoTools/python-overpy .. _PEP 8: https://www.python.org/dev/peps/pep-0008/ python-overpy-0.7/LICENSE000066400000000000000000000020741453334100400152300ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 PhiBo (DinoTools) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. python-overpy-0.7/MANIFEST.in000066400000000000000000000004711453334100400157600ustar00rootroot00000000000000include CHANGELOG.rst CONTRIBUTING.rst README.rst include LICENSE include MANIFEST.in include docs/make.bat docs/Makefile include docs/source/conf.py include docs/source/*.rst include examples/*.py include tests/*.py include tests/json/*.json include tests/response/*.html include tests/xml/*.xml include tox.ini python-overpy-0.7/README.rst000066400000000000000000000044521453334100400157140ustar00rootroot00000000000000Python Overpass Wrapper ======================= A Python Wrapper to access the Overpass API. Have a look at the `documentation`_ to find additional information. .. image:: https://img.shields.io/pypi/v/overpy.svg :target: https://pypi.python.org/pypi/overpy/ :alt: Latest Version .. image:: https://img.shields.io/pypi/l/overpy.svg :target: https://pypi.python.org/pypi/overpy/ :alt: License .. image:: https://github.com/DinoTools/python-overpy/actions/workflows/ci.yml/badge.svg?branch=master :target: https://github.com/DinoTools/python-overpy/actions/workflows/ci.yml?query=branch%3Amaster+ .. image:: https://coveralls.io/repos/DinoTools/python-overpy/badge.png?branch=master :target: https://coveralls.io/r/DinoTools/python-overpy?branch=master Features -------- * Query Overpass API * Parse JSON and XML response data * Additional helper functions Install ------- **Requirements:** Supported Python versions: * Python >= 3.6.2 * PyPy3 **Install:** .. code-block:: console $ pip install overpy Examples -------- Additional examples can be found in the `documentation`_ and in the *examples* directory. .. code-block:: python import overpy api = overpy.Overpass() # fetch all ways and nodes result = api.query(""" way(50.746,7.154,50.748,7.157) ["highway"]; (._;>;); out body; """) for way in result.ways: print("Name: %s" % way.tags.get("name", "n/a")) print(" Highway: %s" % way.tags.get("highway", "n/a")) print(" Nodes:") for node in way.nodes: print(" Lat: %f, Lon: %f" % (node.lat, node.lon)) Helper ~~~~~~ Helper methods are available to provide easy access to often used requests. .. code-block:: python import overpy.helper # 3600062594 is the OSM id of Chemnitz and is the bounding box for the request street = overpy.helper.get_street( "Straße der Nationen", "3600062594" ) # this finds an intersection between Straße der Nationen and Carolastraße in Chemnitz intersection = overpy.helper.get_intersection( "Straße der Nationen", "Carolastraße", "3600062594" ) License ------- Published under the MIT (see LICENSE for more information) .. _`documentation`: http://python-overpy.readthedocs.org/ python-overpy-0.7/docs/000077500000000000000000000000001453334100400151505ustar00rootroot00000000000000python-overpy-0.7/docs/Makefile000066400000000000000000000152371453334100400166200ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PythonOverpassAPI.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PythonOverpassAPI.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/PythonOverpassAPI" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PythonOverpassAPI" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." python-overpy-0.7/docs/make.bat000066400000000000000000000151141453334100400165570ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source set I18NSPHINXOPTS=%SPHINXOPTS% source if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PythonOverpassAPI.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PythonOverpassAPI.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end python-overpy-0.7/docs/requirements.txt000066400000000000000000000000401453334100400204260ustar00rootroot00000000000000sphinx sphinx-autodoc-typehints python-overpy-0.7/docs/source/000077500000000000000000000000001453334100400164505ustar00rootroot00000000000000python-overpy-0.7/docs/source/_static/000077500000000000000000000000001453334100400200765ustar00rootroot00000000000000python-overpy-0.7/docs/source/_static/.keep000066400000000000000000000000001453334100400210110ustar00rootroot00000000000000python-overpy-0.7/docs/source/api.rst000066400000000000000000000013151453334100400177530ustar00rootroot00000000000000API Reference ============= .. currentmodule:: overpy Overpass API ------------ .. autoclass:: Overpass :members: Result ------ .. autoclass:: Result :members: Elements -------- .. autoclass:: Element :members: .. autoclass:: Area :members: .. autoclass:: Node :members: .. autoclass:: Relation :members: .. autoclass:: Way :members: Relation Members ---------------- .. autoclass:: RelationMember :members: .. autoclass:: RelationArea :members: .. autoclass:: RelationNode :members: .. autoclass:: RelationWay :members: Exceptions ---------- .. automodule:: overpy.exception :members: Helper ------ .. automodule:: overpy.helper :members: python-overpy-0.7/docs/source/changelog.rst000066400000000000000000000000411453334100400211240ustar00rootroot00000000000000.. include:: ../../CHANGELOG.rst python-overpy-0.7/docs/source/conf.py000077500000000000000000000244451453334100400177630ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # All configuration values have a default; values that are commented out # serve to show the default. import sys from pathlib import Path # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent)) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx_autodoc_typehints', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'Python Overpass API' copyright = '2014, PhiBo' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # try: from overpy import __about__ as overpy_about # The short X.Y version. version = overpy_about.__version__ # The full version, including alpha/beta/rc tags. release = overpy_about.__version__ except ImportError: version = "unknown" release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # sphinx-autodoc-typehints options # If True, add stub documentation for undocumented parameters to be able to add type info. always_document_param_types = True # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'PythonOverpassAPIdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'PythonOverpassAPI.tex', 'Python Overpass API Documentation', 'PhiBo', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'pythonoverpassapi', 'Python Overpass API Documentation', ['PhiBo'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'PythonOverpassAPI', 'Python Overpass API Documentation', 'PhiBo', 'PythonOverpassAPI', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False # -- Options for Epub output ---------------------------------------------- # Bibliographic Dublin Core info. epub_title = 'Python Overpass API' epub_author = 'PhiBo' epub_publisher = 'PhiBo' epub_copyright = '2014, PhiBo' # The basename for the epub file. It defaults to the project name. #epub_basename = 'Python Overpass API' # The HTML theme for the epub output. Since the default themes are not optimized # for small screen space, using the same theme for HTML and epub output is # usually not wise. This defaults to 'epub', a theme designed to save visual # space. #epub_theme = 'epub' # The language of the text. It defaults to the language option # or en if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. #epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. #epub_identifier = '' # A unique identification for the text. #epub_uid = '' # A tuple containing the cover image and cover page html template filenames. #epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. #epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] # The depth of the table of contents in toc.ncx. #epub_tocdepth = 3 # Allow duplicate toc entries. #epub_tocdup = True # Choose between 'default' and 'includehidden'. #epub_tocscope = 'default' # Fix unsupported image types using the PIL. #epub_fix_images = False # Scale large images. #epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. #epub_show_urls = 'inline' # If false, no index is generated. #epub_use_index = True python-overpy-0.7/docs/source/contributing.rst000066400000000000000000000000441453334100400217070ustar00rootroot00000000000000.. include:: ../../CONTRIBUTING.rst python-overpy-0.7/docs/source/example.rst000066400000000000000000000125061453334100400206410ustar00rootroot00000000000000Examples ======== Basic example ------------- Lets start with an example from the Overpass API documentation. **Query String:** .. code-block:: text :linenos: node(50.745,7.17,50.75,7.18); out; **Use OverPy:** .. code-block:: pycon :linenos: >>> import overpy >>> api = overpy.Overpass() >>> result = api.query("node(50.745,7.17,50.75,7.18);out;") >>> len(result.nodes) 1984 >>> len(result.ways) 0 >>> len(result.relations) 0 >>> node = result.nodes[2] >>> node.id 100792806 >>> node.tags {} Line 1: Import the required Python module Line 2: Create a new instance of the Overpass() class. This instance is used to query the Overpass API. Line 3: Use the Query-String from above to query the Overpass API service. Line 4,5: Get the number of nodes in the result set. Line 6-9: Get the number of ways and relations available in the result set. Line 10-14: Get the third node from the list. Display the ID and the tags of this node. Use Overpass QL or Overpass XML ------------------------------- Queries are passed directly to the Overpass API service without any modification. So it is possible to use Overpass QL and Overpass XML. Overpass QL ~~~~~~~~~~~ **Query:** .. code-block:: text :linenos: node["name"="Gielgen"]; out body; **Use OverPy:** .. code-block:: pycon :linenos: >>> import overpy >>> api = overpy.Overpass() >>> result = api.query("""node["name"="Gielgen"];out body;""") >>> len(result.nodes) 6 >>> len(result.ways) 0 >>> len(result.relations) 0 Overpass XML ~~~~~~~~~~~~ **Query:** .. code-block:: xml :linenos: **Use OverPy:** .. code-block:: pycon :linenos: >>> import overpy >>> api = overpy.Overpass() >>> result = api.query(""" ... ... ... ... ... """) >>> len(result.nodes) 6 >>> len(result.ways) 0 >>> len(result.relations) 0 Parse JSON or XML responses --------------------------- On a request OverPy detects the content type from the response. JSON response ~~~~~~~~~~~~~ **Query String:** .. code-block:: text :linenos: [out:json]; node(50.745,7.17,50.75,7.18); out; **Use OverPy:** .. code-block:: pycon :linenos: >>> import overpy >>> api = overpy.Overpass() >>> result = api.query("[out:json];node(50.745,7.17,50.75,7.18);out;") >>> len(result.nodes) 1984 >>> len(result.ways) 0 >>> len(result.relations) 0 XML response ~~~~~~~~~~~~ **Query String:** .. code-block:: text :linenos: [out:xml]; node(50.745,7.17,50.75,7.18); out; **Use OverPy:** .. code-block:: pycon :linenos: >>> import overpy >>> api = overpy.Overpass() >>> result = api.query("[out:xml];node(50.745,7.17,50.75,7.18);out;") >>> len(result.nodes) 1984 >>> len(result.ways) 0 >>> len(result.relations) 0 Ways ---- Get all nodes of a way ~~~~~~~~~~~~~~~~~~~~~~ In this example the Overpass API will only return the Way elements with the name "Gielgenstraße". But there will be no Node elements in the result set. OverPy provides a way to resolve missing nodes. **Query String:** .. code-block:: text :linenos: way ["name"="Gielgenstraße"] (50.7,7.1,50.8,7.25); out; **Use OverPy:** .. code-block:: pycon :linenos: >>> import overpy >>> api = overpy.Overpass() >>> result = api.query("""way["name"="Gielgenstraße"](50.7,7.1,50.8,7.25);out;""") >>> len(result.nodes) 0 >>> len(result.ways) 4 >>> way = result.ways[0] >>> way.nodes Traceback (most recent call last): File "", line 1, in [...] raise exception.DataIncomplete("Resolve missing nodes is disabled") overpy.exception.DataIncomplete: ('Data incomplete try to improve the query to resolve the missing data', 'Resolve missing nodes is disabled') >>> way.get_nodes() Traceback (most recent call last): File "", line 1, in [...] raise exception.DataIncomplete("Resolve missing nodes is disabled") overpy.exception.DataIncomplete: ('Data incomplete try to improve the query to resolve the missing data', 'Resolve missing nodes is disabled') >>> nodes = way.get_nodes(resolve_missing=True) >>> len(nodes) 13 >>> len(result.nodes) 13 >>> len(way.nodes) 13 Line 1-3: Send a query to the Overpass API service. Line 4-6: There are 4 Way elements and 0 Node elements in the result set. Line 7: Get the first way. Line 8-19: Use :attr:`overpy.Way.nodes` class attribute and the :func:`overpy.Way.get_nodes()` function to get the nodes for the way. Both raise an exception because the nodes are not in the result set and auto resolving missing nodes is disabled. Line 20-21: Use the :func:`overpy.Way.get_nodes()` function and let OverPy try to resolve the missing nodes. The function will return all Node elements connected with the Way element. Line 22-25: The resolved nodes have been added to the result set and are available to be used again later. python-overpy-0.7/docs/source/faq.rst000066400000000000000000000010441453334100400177500ustar00rootroot00000000000000Frequently Asked Questions ========================== 429 Too Many Requests --------------------- If too many requests are send from the same IP address the server blocks some requests to avoid that a user uses up all resources. For more information have a look at the `Overpass API documentation `_. OverPy tries to fetch missing information automatically. To limit the number of requests you should try to fetch all required information/data(relations, ways, nodes, tags, ...) with the initial query. python-overpy-0.7/docs/source/index.rst000066400000000000000000000004541453334100400203140ustar00rootroot00000000000000Welcome to Python Overpass API's documentation! =============================================== Contents: .. toctree:: :maxdepth: 2 introduction example faq api contributing changelog Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` python-overpy-0.7/docs/source/introduction.rst000066400000000000000000000030001453334100400217140ustar00rootroot00000000000000Introduction ============ Requirements ------------ Supported Python versions: * Python 3.6+ * PyPy3 Installation ------------ As a Python egg ~~~~~~~~~~~~~~~ You can install the most recent version using ``pip`` .. code-block:: console $ pip install overpy From a tarball release ~~~~~~~~~~~~~~~~~~~~~~ Download the most recent tarball from github, unpack it and run the following command on the command-line. .. code-block:: console $ python setup.py install Install the development version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Install git and run the following commands on the command-line. .. code-block:: console $ git clone https://github.com/DinoTools/python-overpy.git $ cd python-overpy $ python setup.py install Usage ----- It is recommended to have a look at the documentation of the `Overpass API`_ before using OverPy. For more examples have a look at the :doc:`examples page ` or in the examples directory. .. code-block:: python import overpy api = overpy.Overpass() # fetch all ways and nodes result = api.query(""" way(50.746,7.154,50.748,7.157) ["highway"]; (._;>;); out body; """) for way in result.ways: print("Name: %s" % way.tags.get("name", "n/a")) print(" Highway: %s" % way.tags.get("highway", "n/a")) print(" Nodes:") for node in way.nodes: print(" Lat: %f, Lon: %f" % (node.lat, node.lon)) .. _Overpass API: https://wiki.openstreetmap.org/wiki/Overpass_API python-overpy-0.7/examples/000077500000000000000000000000001453334100400160365ustar00rootroot00000000000000python-overpy-0.7/examples/get_areas.py000077500000000000000000000006661453334100400203550ustar00rootroot00000000000000#!/usr/bin/env python import overpy api = overpy.Overpass() # fetch all areas # More info on http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_API_by_Example result = api.query(""" area[name="Troisdorf"]; out; """) for area in result.areas: print( "Name: %s (%i)" % ( area.tags.get("name", "n/a"), area.id ) ) for n, v in area.tags.items(): print(f" Tag: {n} = {v}") python-overpy-0.7/examples/get_nodes.py000077500000000000000000000010331453334100400203570ustar00rootroot00000000000000#!/usr/bin/env python import overpy api = overpy.Overpass() # We can also see a node's metadata: jet_deau = 60018172 result = api.query(f"node({jet_deau}); out meta;") node = result.get_node(jet_deau) print( "The node for the famous Geneva {} ({},{}) was:".format( node.tags['name'], node.lat, node.lon ) ) attrs = node.attributes print("* last modified {}".format(attrs['timestamp'])) print("* by {} (uid: {})".format(attrs['user'], attrs['uid'])) print("* in changeset {}".format(attrs['changeset'])) python-overpy-0.7/examples/get_ways.py000077500000000000000000000006711453334100400202410ustar00rootroot00000000000000#!/usr/bin/env python import overpy api = overpy.Overpass() # fetch all ways and nodes result = api.query(""" way(50.746,7.154,50.748,7.157) ["highway"]; (._;>;); out body; """) for way in result.ways: print("Name: %s" % way.tags.get("name", "n/a")) print(" Highway: %s" % way.tags.get("highway", "n/a")) print(" Nodes:") for node in way.nodes: print(f" Lat: {node.lat:f}, Lon: {node.lon:f}") python-overpy-0.7/overpy/000077500000000000000000000000001453334100400155445ustar00rootroot00000000000000python-overpy-0.7/overpy/__about__.py000066400000000000000000000007051453334100400200260ustar00rootroot00000000000000__all__ = [ "__author__", "__copyright__", "__email__", "__license__", "__summary__", "__title__", "__uri__", "__version__", ] __title__ = "overpy" __summary__ = "Python Wrapper to access the OpenStreepMap Overpass API" __uri__ = "https://github.com/DinoTools/python-overpy" __version__ = "0.7" __author__ = "PhiBo (DinoTools)" __email__ = "" __license__ = "MIT" __copyright__ = "Copyright 2014-2023 %s" % __author__ python-overpy-0.7/overpy/__init__.py000066400000000000000000001536521453334100400176710ustar00rootroot00000000000000from collections import OrderedDict from datetime import datetime from decimal import Decimal from urllib.request import urlopen from urllib.error import HTTPError from xml.sax import handler, make_parser import xml.etree.ElementTree import json import re import time from typing import Any, Callable, ClassVar, Dict, List, NoReturn, Optional, Tuple, Type, TypeVar, Union from overpy import exception # Ignore flake8 F401 warning for unused vars from overpy.__about__ import ( # noqa: F401 __author__, __copyright__, __email__, __license__, __summary__, __title__, __uri__, __version__ ) ElementTypeVar = TypeVar("ElementTypeVar", bound="Element") XML_PARSER_DOM = 1 XML_PARSER_SAX = 2 # Try to convert some common attributes # http://wiki.openstreetmap.org/wiki/Elements#Common_attributes GLOBAL_ATTRIBUTE_MODIFIERS: Dict[str, Callable] = { "changeset": int, "timestamp": lambda ts: datetime.strptime(ts, "%Y-%m-%dT%H:%M:%SZ"), "uid": int, "version": int, "visible": lambda v: v.lower() == "true" } def is_valid_type( element: Union["Area", "Node", "Relation", "Way"], cls: Type[Union["Area", "Element", "Node", "Relation", "Way"]]) -> bool: """ Test if an element is of a given type. :param element: The element instance to test :param cls: The element class to test :return: False or True """ return isinstance(element, cls) and element.id is not None class Overpass: """ Class to access the Overpass API :cvar default_max_retry_count: Global max number of retries (Default: 0) :cvar default_read_chunk_size: Max size of each chunk read from the server response :cvar default_retry_timeout: Global time to wait between tries (Default: 1.0s) :cvar default_url: Default URL of the Overpass server """ default_max_retry_count: ClassVar[int] = 0 default_read_chunk_size: ClassVar[int] = 4096 default_retry_timeout: ClassVar[float] = 1.0 default_url: ClassVar[str] = "http://overpass-api.de/api/interpreter" def __init__( self, read_chunk_size: Optional[int] = None, url: Optional[str] = None, xml_parser: int = XML_PARSER_SAX, max_retry_count: int = None, retry_timeout: float = None): """ :param read_chunk_size: Max size of each chunk read from the server response :param url: Optional URL of the Overpass server. Defaults to http://overpass-api.de/api/interpreter :param xml_parser: The xml parser to use :param max_retry_count: Max number of retries (Default: default_max_retry_count) :param retry_timeout: Time to wait between tries (Default: default_retry_timeout) """ self.url = self.default_url if url is not None: self.url = url self._regex_extract_error_msg = re.compile(br"\(?P\") self._regex_remove_tag = re.compile(b"<[^>]*?>") if read_chunk_size is None: read_chunk_size = self.default_read_chunk_size self.read_chunk_size = read_chunk_size if max_retry_count is None: max_retry_count = self.default_max_retry_count self.max_retry_count = max_retry_count if retry_timeout is None: retry_timeout = self.default_retry_timeout self.retry_timeout = retry_timeout self.xml_parser = xml_parser @staticmethod def _handle_remark_msg(msg: str) -> NoReturn: """ Try to parse the message provided with the remark tag or element. :param msg: The message :raises overpy.exception.OverpassRuntimeError: If message starts with 'runtime error:' :raises overpy.exception.OverpassRuntimeRemark: If message starts with 'runtime remark:' :raises overpy.exception.OverpassUnknownError: If we are unable to identify the error """ msg = msg.strip() if msg.startswith("runtime error:"): raise exception.OverpassRuntimeError(msg=msg) elif msg.startswith("runtime remark:"): raise exception.OverpassRuntimeRemark(msg=msg) raise exception.OverpassUnknownError(msg=msg) def query(self, query: Union[bytes, str]) -> "Result": """ Query the Overpass API :param query: The query string in Overpass QL :return: The parsed result """ if not isinstance(query, bytes): query = query.encode("utf-8") retry_num: int = 0 retry_exceptions: List[exception.OverPyException] = [] do_retry: bool = True if self.max_retry_count > 0 else False while retry_num <= self.max_retry_count: if retry_num > 0: time.sleep(self.retry_timeout) retry_num += 1 try: f = urlopen(self.url, query) except HTTPError as e: f = e response = f.read(self.read_chunk_size) while True: data = f.read(self.read_chunk_size) if len(data) == 0: break response = response + data f.close() current_exception: exception.OverPyException if f.code == 200: content_type = f.getheader("Content-Type") if content_type == "application/json": return self.parse_json(response) if content_type == "application/osm3s+xml": return self.parse_xml(response) current_exception = exception.OverpassUnknownContentType(content_type) if not do_retry: raise current_exception retry_exceptions.append(current_exception) continue if f.code == 400: msgs: List[str] = [] for msg_raw in self._regex_extract_error_msg.finditer(response): msg_clean_bytes = self._regex_remove_tag.sub(b"", msg_raw.group("msg")) try: msg = msg_clean_bytes.decode("utf-8") except UnicodeDecodeError: msg = repr(msg_clean_bytes) msgs.append(msg) current_exception = exception.OverpassBadRequest( query, msgs=msgs ) if not do_retry: raise current_exception retry_exceptions.append(current_exception) continue if f.code == 429: current_exception = exception.OverpassTooManyRequests() if not do_retry: raise current_exception retry_exceptions.append(current_exception) continue if f.code == 504: current_exception = exception.OverpassGatewayTimeout() if not do_retry: raise current_exception retry_exceptions.append(current_exception) continue current_exception = exception.OverpassUnknownHTTPStatusCode(f.code) if not do_retry: raise current_exception retry_exceptions.append(current_exception) continue raise exception.MaxRetriesReached(retry_count=retry_num, exceptions=retry_exceptions) def parse_json(self, data: Union[bytes, str], encoding: str = "utf-8") -> "Result": """ Parse raw response from Overpass service. :param data: Raw JSON Data :param encoding: Encoding to decode byte string :return: Result object """ if isinstance(data, bytes): data = data.decode(encoding) data_parsed: dict = json.loads(data, parse_float=Decimal) if "remark" in data_parsed: self._handle_remark_msg(msg=data_parsed.get("remark")) return Result.from_json(data_parsed, api=self) def parse_xml(self, data: Union[bytes, str], encoding: str = "utf-8", parser: Optional[int] = None): """ :param data: Raw XML Data :param encoding: Encoding to decode byte string :param parser: The XML parser to use :return: Result object """ if parser is None: parser = self.xml_parser if isinstance(data, bytes): data = data.decode(encoding) m = re.compile("(?P[^<>]*)").search(data) if m: self._handle_remark_msg(m.group("msg")) return Result.from_xml(data, api=self, parser=parser) class Result: """ Class to handle the result. """ def __init__( self, elements: Optional[List[Union["Area", "Node", "Relation", "Way"]]] = None, api: Optional[Overpass] = None): """ :param elements: List of elements to initialize the result with :param api: The API object to load additional resources and elements """ if elements is None: elements = [] self._areas: Dict[int, Union["Area", "Node", "Relation", "Way"]] = OrderedDict( (element.id, element) for element in elements if is_valid_type(element, Area) ) self._nodes = OrderedDict( (element.id, element) for element in elements if is_valid_type(element, Node) ) self._ways = OrderedDict( (element.id, element) for element in elements if is_valid_type(element, Way) ) self._relations = OrderedDict( (element.id, element) for element in elements if is_valid_type(element, Relation) ) self._class_collection_map: Dict[Any, Any] = { Node: self._nodes, Way: self._ways, Relation: self._relations, Area: self._areas } self.api = api def expand(self, other: "Result"): """ Add all elements from an other result to the list of elements of this result object. It is used by the auto resolve feature. :param other: Expand the result with the elements from this result. :raises ValueError: If provided parameter is not instance of :class:`overpy.Result` """ if not isinstance(other, Result): raise ValueError("Provided argument has to be instance of overpy:Result()") other_collection_map: Dict[Type["Element"], List[Union["Area", "Node", "Relation", "Way"]]] = { Area: other.areas, Node: other.nodes, Relation: other.relations, Way: other.ways } for element_type, own_collection in self._class_collection_map.items(): for element in other_collection_map[element_type]: if is_valid_type(element, element_type) and element.id not in own_collection: own_collection[element.id] = element def append(self, element: Union["Area", "Node", "Relation", "Way"]): """ Append a new element to the result. :param element: The element to append """ if is_valid_type(element, Element): self._class_collection_map[element.__class__].setdefault(element.id, element) def get_elements( self, filter_cls: Type[ElementTypeVar], elem_id: Optional[int] = None) -> List[ElementTypeVar]: """ Get a list of elements from the result and filter the element type by a class. :param filter_cls: :param elem_id: ID of the object :return: List of available elements """ result: List[ElementTypeVar] = [] if elem_id is not None: try: result = [self._class_collection_map[filter_cls][elem_id]] except KeyError: result = [] else: for e in self._class_collection_map[filter_cls].values(): result.append(e) return result def get_ids( self, filter_cls: Type[Union["Area", "Node", "Relation", "Way"]]) -> List[int]: """ Get all Element IDs :param filter_cls: Only IDs of elements with this type :return: List of IDs """ return list(self._class_collection_map[filter_cls].keys()) def get_node_ids(self) -> List[int]: return self.get_ids(filter_cls=Node) def get_way_ids(self) -> List[int]: return self.get_ids(filter_cls=Way) def get_relation_ids(self) -> List[int]: return self.get_ids(filter_cls=Relation) def get_area_ids(self) -> List[int]: return self.get_ids(filter_cls=Area) @classmethod def from_json(cls, data: dict, api: Optional[Overpass] = None) -> "Result": """ Create a new instance and load data from json object. :param data: JSON data returned by the Overpass API :param api: :return: New instance of Result object """ result = cls(api=api) elem_cls: Type[Union["Area", "Node", "Relation", "Way"]] for elem_cls in [Node, Way, Relation, Area]: for element in data.get("elements", []): e_type = element.get("type") if hasattr(e_type, "lower") and e_type.lower() == elem_cls._type_value: result.append(elem_cls.from_json(element, result=result)) return result @classmethod def from_xml( cls, data: Union[str, xml.etree.ElementTree.Element], api: Optional[Overpass] = None, parser: Optional[int] = None) -> "Result": """ Create a new instance and load data from xml data or object. .. note:: If parser is set to None, the functions tries to find the best parse. By default the SAX parser is chosen if a string is provided as data. The parser is set to DOM if an xml.etree.ElementTree.Element is provided as data value. :param data: Root element :param api: The instance to query additional information if required. :param parser: Specify the parser to use(DOM or SAX)(Default: None = autodetect, defaults to SAX) :return: New instance of Result object """ if parser is None: if isinstance(data, str): parser = XML_PARSER_SAX else: parser = XML_PARSER_DOM result = cls(api=api) if parser == XML_PARSER_DOM: import xml.etree.ElementTree as ET if isinstance(data, str): root = ET.fromstring(data) elif isinstance(data, ET.Element): root = data else: raise exception.OverPyException("Unable to detect data type.") elem_cls: Type[Union["Area", "Node", "Relation", "Way"]] for elem_cls in [Node, Way, Relation, Area]: for child in root: if child.tag.lower() == elem_cls._type_value: result.append(elem_cls.from_xml(child, result=result)) elif parser == XML_PARSER_SAX: from io import StringIO if not isinstance(data, str): raise ValueError("data must be of type str if using the SAX parser") source = StringIO(data) sax_handler = OSMSAXHandler(result) sax_parser = make_parser() sax_parser.setContentHandler(sax_handler) sax_parser.parse(source) else: # ToDo: better exception raise Exception("Unknown XML parser") return result def get_area(self, area_id: int, resolve_missing: bool = False) -> "Area": """ Get an area by its ID. :param area_id: The area ID :param resolve_missing: Query the Overpass API if the area is missing in the result set. :return: The area :raises overpy.exception.DataIncomplete: The requested way is not available in the result cache. :raises overpy.exception.DataIncomplete: If resolve_missing is True and the area can't be resolved. """ areas = self.get_areas(area_id=area_id) if len(areas) == 0: if resolve_missing is False: raise exception.DataIncomplete("Resolve missing area is disabled") query = ("\n" "[out:json];\n" "area({area_id});\n" "out body;\n" ) query = query.format( area_id=area_id ) tmp_result = self.api.query(query) self.expand(tmp_result) areas = self.get_areas(area_id=area_id) if len(areas) == 0: raise exception.DataIncomplete("Unable to resolve requested areas") return areas[0] def get_areas(self, area_id: Optional[int] = None) -> List["Area"]: """ Alias for get_elements() but filter the result by Area :param area_id: The Id of the area :return: List of elements """ return self.get_elements(Area, elem_id=area_id) def get_node(self, node_id: int, resolve_missing: bool = False) -> "Node": """ Get a node by its ID. :param node_id: The node ID :param resolve_missing: Query the Overpass API if the node is missing in the result set. :return: The node :raises overpy.exception.DataIncomplete: At least one referenced node is not available in the result cache. :raises overpy.exception.DataIncomplete: If resolve_missing is True and at least one node can't be resolved. """ nodes = self.get_nodes(node_id=node_id) if len(nodes) == 0: if not resolve_missing: raise exception.DataIncomplete("Resolve missing nodes is disabled") query = ("\n" "[out:json];\n" "node({node_id});\n" "out body;\n" ) query = query.format( node_id=node_id ) tmp_result = self.api.query(query) self.expand(tmp_result) nodes = self.get_nodes(node_id=node_id) if len(nodes) == 0: raise exception.DataIncomplete("Unable to resolve all nodes") return nodes[0] def get_nodes(self, node_id: Optional[int] = None) -> List["Node"]: """ Alias for get_elements() but filter the result by Node() :param node_id: The Id of the node :type node_id: Integer :return: List of elements """ return self.get_elements(Node, elem_id=node_id) def get_relation(self, rel_id: int, resolve_missing: bool = False) -> "Relation": """ Get a relation by its ID. :param rel_id: The relation ID :param resolve_missing: Query the Overpass API if the relation is missing in the result set. :return: The relation :raises overpy.exception.DataIncomplete: The requested relation is not available in the result cache. :raises overpy.exception.DataIncomplete: If resolve_missing is True and the relation can't be resolved. """ relations = self.get_relations(rel_id=rel_id) if len(relations) == 0: if resolve_missing is False: raise exception.DataIncomplete("Resolve missing relations is disabled") query = ("\n" "[out:json];\n" "relation({relation_id});\n" "out body;\n" ) query = query.format( relation_id=rel_id ) tmp_result = self.api.query(query) self.expand(tmp_result) relations = self.get_relations(rel_id=rel_id) if len(relations) == 0: raise exception.DataIncomplete("Unable to resolve requested reference") return relations[0] def get_relations(self, rel_id: int = None) -> List["Relation"]: """ Alias for get_elements() but filter the result by Relation :param rel_id: Id of the relation :return: List of elements """ return self.get_elements(Relation, elem_id=rel_id) def get_way(self, way_id: int, resolve_missing: bool = False) -> "Way": """ Get a way by its ID. :param way_id: The way ID :param resolve_missing: Query the Overpass API if the way is missing in the result set. :return: The way :raises overpy.exception.DataIncomplete: The requested way is not available in the result cache. :raises overpy.exception.DataIncomplete: If resolve_missing is True and the way can't be resolved. """ ways = self.get_ways(way_id=way_id) if len(ways) == 0: if resolve_missing is False: raise exception.DataIncomplete("Resolve missing way is disabled") query = ("\n" "[out:json];\n" "way({way_id});\n" "out body;\n" ) query = query.format( way_id=way_id ) tmp_result = self.api.query(query) self.expand(tmp_result) ways = self.get_ways(way_id=way_id) if len(ways) == 0: raise exception.DataIncomplete("Unable to resolve requested way") return ways[0] def get_ways(self, way_id: Optional[int] = None) -> List["Way"]: """ Alias for get_elements() but filter the result by Way :param way_id: The Id of the way :return: List of elements """ return self.get_elements(Way, elem_id=way_id) area_ids = property(get_area_ids) areas = property(get_areas) node_ids = property(get_node_ids) nodes = property(get_nodes) relation_ids = property(get_relation_ids) relations = property(get_relations) way_ids = property(get_way_ids) ways = property(get_ways) class Element: """ Base element """ _type_value: str def __init__(self, attributes: Optional[dict] = None, result: Optional[Result] = None, tags: Optional[Dict] = None): """ :param attributes: Additional attributes :param result: The result object this element belongs to :param tags: List of tags """ self._result = result self.attributes = attributes # ToDo: Add option to modify attribute modifiers attribute_modifiers: Dict[str, Callable] = dict(GLOBAL_ATTRIBUTE_MODIFIERS.items()) for n, m in attribute_modifiers.items(): if n in self.attributes: self.attributes[n] = m(self.attributes[n]) self.id: int self.tags = tags @classmethod def get_center_from_json(cls, data: dict) -> Tuple[Decimal, Decimal]: """ Get center information from json data :param data: json data :return: tuple with two elements: lat and lon """ center_lat = None center_lon = None center = data.get("center") if isinstance(center, dict): center_lat = center.get("lat") center_lon = center.get("lon") if center_lat is None or center_lon is None: raise ValueError("Unable to get lat or lon of way center.") center_lat = Decimal(center_lat) center_lon = Decimal(center_lon) return center_lat, center_lon @classmethod def get_center_from_xml_dom(cls, sub_child: xml.etree.ElementTree.Element) -> Tuple[Decimal, Decimal]: center_lat_str: str = sub_child.attrib.get("lat") center_lon_str: str = sub_child.attrib.get("lon") if center_lat_str is None or center_lon_str is None: raise ValueError("Unable to get lat or lon of way center.") center_lat = Decimal(center_lat_str) center_lon = Decimal(center_lon_str) return center_lat, center_lon @classmethod def from_json(cls: Type[ElementTypeVar], data: dict, result: Optional[Result] = None) -> ElementTypeVar: """ Create new Element() from json data :param data: :param result: :return: """ raise NotImplementedError @classmethod def from_xml( cls: Type[ElementTypeVar], child: xml.etree.ElementTree.Element, result: Optional[Result] = None) -> ElementTypeVar: """ Create new Element() element from XML data """ raise NotImplementedError class Area(Element): """ Class to represent an element of type area """ _type_value = "area" def __init__(self, area_id: Optional[int] = None, **kwargs): """ :param area_id: Id of the area element :param kwargs: Additional arguments are passed directly to the parent class """ Element.__init__(self, **kwargs) #: The id of the way self.id = area_id def __repr__(self) -> str: return f"" @classmethod def from_json(cls, data: dict, result: Optional[Result] = None) -> "Area": """ Create new Area element from JSON data :param data: Element data from JSON :param result: The result this element belongs to :return: New instance of Way :raises overpy.exception.ElementDataWrongType: If type value of the passed JSON data does not match. """ if data.get("type") != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=data.get("type") ) tags = data.get("tags", {}) area_id = data.get("id") attributes = {} ignore = ["id", "tags", "type"] for n, v in data.items(): if n in ignore: continue attributes[n] = v return cls(area_id=area_id, attributes=attributes, tags=tags, result=result) @classmethod def from_xml(cls, child: xml.etree.ElementTree.Element, result: Optional[Result] = None) -> "Area": """ Create new way element from XML data :param child: XML node to be parsed :param result: The result this node belongs to :return: New Way oject :raises overpy.exception.ElementDataWrongType: If name of the xml child node doesn't match :raises ValueError: If the ref attribute of the xml node is not provided :raises ValueError: If a tag doesn't have a name """ if child.tag.lower() != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=child.tag.lower() ) tags = {} for sub_child in child: if sub_child.tag.lower() == "tag": name = sub_child.attrib.get("k") if name is None: raise ValueError("Tag without name/key.") value = sub_child.attrib.get("v") tags[name] = value area_id_str: Optional[str] = child.attrib.get("id") area_id: Optional[int] = None if area_id_str is not None: area_id = int(area_id_str) attributes = {} ignore = ["id"] for n, v in child.attrib.items(): if n in ignore: continue attributes[n] = v return cls(area_id=area_id, attributes=attributes, tags=tags, result=result) class Node(Element): """ Class to represent an element of type node """ _type_value = "node" def __init__( self, node_id: Optional[int] = None, lat: Optional[Union[Decimal, float]] = None, lon: Optional[Union[Decimal, float]] = None, **kwargs): """ :param lat: Latitude :param lon: Longitude :param node_id: Id of the node element :param kwargs: Additional arguments are passed directly to the parent class """ Element.__init__(self, **kwargs) self.id = node_id self.lat = lat self.lon = lon def __repr__(self) -> str: return f"" @classmethod def from_json(cls, data: dict, result: Optional[Result] = None) -> "Node": """ Create new Node element from JSON data :param data: Element data from JSON :param result: The result this element belongs to :return: New instance of Node :raises overpy.exception.ElementDataWrongType: If type value of the passed JSON data does not match. """ if data.get("type") != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=data.get("type") ) tags = data.get("tags", {}) node_id = data.get("id") lat = data.get("lat") lon = data.get("lon") attributes = {} ignore = ["type", "id", "lat", "lon", "tags"] for n, v in data.items(): if n in ignore: continue attributes[n] = v return cls(node_id=node_id, lat=lat, lon=lon, tags=tags, attributes=attributes, result=result) @classmethod def from_xml(cls, child: xml.etree.ElementTree.Element, result: Optional[Result] = None) -> "Node": """ Create new way element from XML data :param child: XML node to be parsed :param result: The result this node belongs to :return: New Way oject :raises overpy.exception.ElementDataWrongType: If name of the xml child node doesn't match :raises ValueError: If a tag doesn't have a name """ if child.tag.lower() != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=child.tag.lower() ) tags = {} for sub_child in child: if sub_child.tag.lower() == "tag": name = sub_child.attrib.get("k") if name is None: raise ValueError("Tag without name/key.") value = sub_child.attrib.get("v") tags[name] = value node_id: Optional[int] = None node_id_str: Optional[str] = child.attrib.get("id") if node_id_str is not None: node_id = int(node_id_str) lat: Optional[Decimal] = None lat_str: Optional[str] = child.attrib.get("lat") if lat_str is not None: lat = Decimal(lat_str) lon: Optional[Decimal] = None lon_str: Optional[str] = child.attrib.get("lon") if lon_str is not None: lon = Decimal(lon_str) attributes = {} ignore = ["id", "lat", "lon"] for n, v in child.attrib.items(): if n in ignore: continue attributes[n] = v return cls(node_id=node_id, lat=lat, lon=lon, tags=tags, attributes=attributes, result=result) class Way(Element): """ Class to represent an element of type way """ _type_value = "way" def __init__( self, way_id: Optional[int] = None, center_lat: Optional[Union[Decimal, float]] = None, center_lon: Optional[Union[Decimal, float]] = None, node_ids: Optional[Union[List[int], Tuple[int]]] = None, **kwargs): """ :param node_ids: List of node IDs :param way_id: Id of the way element :param kwargs: Additional arguments are passed directly to the parent class """ Element.__init__(self, **kwargs) #: The id of the way self.id = way_id #: List of Ids of the associated nodes self._node_ids = node_ids #: The lat/lon of the center of the way (optional depending on query) self.center_lat = center_lat self.center_lon = center_lon def __repr__(self): return f"" @property def nodes(self) -> List[Node]: """ List of nodes associated with the way. """ return self.get_nodes() def get_nodes(self, resolve_missing: bool = False) -> List[Node]: """ Get the nodes defining the geometry of the way :param resolve_missing: Try to resolve missing nodes. :return: List of nodes :raises overpy.exception.DataIncomplete: At least one referenced node is not available in the result cache. :raises overpy.exception.DataIncomplete: If resolve_missing is True and at least one node can't be resolved. """ result = [] resolved = False for node_id in self._node_ids: try: node = self._result.get_node(node_id) except exception.DataIncomplete: node = None if node is not None: result.append(node) continue if not resolve_missing: raise exception.DataIncomplete("Resolve missing nodes is disabled") # We tried to resolve the data but some nodes are still missing if resolved: raise exception.DataIncomplete("Unable to resolve all nodes") query = ("\n" "[out:json];\n" "way({way_id});\n" "node(w);\n" "out body;\n" ) query = query.format( way_id=self.id ) tmp_result = self._result.api.query(query) self._result.expand(tmp_result) resolved = True try: node = self._result.get_node(node_id) except exception.DataIncomplete: node = None if node is None: raise exception.DataIncomplete("Unable to resolve all nodes") result.append(node) return result @classmethod def from_json(cls, data: dict, result: Optional[Result] = None) -> "Way": """ Create new Way element from JSON data :param data: Element data from JSON :param result: The result this element belongs to :return: New instance of Way :raises overpy.exception.ElementDataWrongType: If type value of the passed JSON data does not match. """ if data.get("type") != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=data.get("type") ) tags = data.get("tags", {}) way_id = data.get("id") node_ids = data.get("nodes") (center_lat, center_lon) = cls.get_center_from_json(data=data) attributes = {} ignore = ["center", "id", "nodes", "tags", "type"] for n, v in data.items(): if n in ignore: continue attributes[n] = v return cls( attributes=attributes, center_lat=center_lat, center_lon=center_lon, node_ids=node_ids, tags=tags, result=result, way_id=way_id ) @classmethod def from_xml(cls, child: xml.etree.ElementTree.Element, result: Optional[Result] = None) -> "Way": """ Create new way element from XML data :param child: XML node to be parsed :param result: The result this node belongs to :return: New Way oject :raises overpy.exception.ElementDataWrongType: If name of the xml child node doesn't match :raises ValueError: If the ref attribute of the xml node is not provided :raises ValueError: If a tag doesn't have a name """ if child.tag.lower() != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=child.tag.lower() ) tags = {} node_ids = [] center_lat = None center_lon = None for sub_child in child: if sub_child.tag.lower() == "tag": name = sub_child.attrib.get("k") if name is None: raise ValueError("Tag without name/key.") value = sub_child.attrib.get("v") tags[name] = value if sub_child.tag.lower() == "nd": ref_id_str = sub_child.attrib.get("ref") if ref_id_str is None: raise ValueError("Unable to find required ref value.") ref_id: int = int(ref_id_str) node_ids.append(ref_id) if sub_child.tag.lower() == "center": (center_lat, center_lon) = cls.get_center_from_xml_dom(sub_child=sub_child) way_id: Optional[int] = None way_id_str: Optional[str] = child.attrib.get("id") if way_id_str is not None: way_id = int(way_id_str) attributes = {} ignore = ["id"] for n, v in child.attrib.items(): if n in ignore: continue attributes[n] = v return cls(way_id=way_id, center_lat=center_lat, center_lon=center_lon, attributes=attributes, node_ids=node_ids, tags=tags, result=result) class Relation(Element): """ Class to represent an element of type relation """ _type_value = "relation" def __init__( self, rel_id: Optional[int] = None, center_lat: Optional[Union[Decimal, float]] = None, center_lon: Optional[Union[Decimal, float]] = None, members: Optional[List["RelationMember"]] = None, **kwargs): """ :param members: :param rel_id: Id of the relation element :param kwargs: :return: """ Element.__init__(self, **kwargs) self.id = rel_id self.members = members #: The lat/lon of the center of the way (optional depending on query) self.center_lat = center_lat self.center_lon = center_lon def __repr__(self): return f"" @classmethod def from_json(cls, data: dict, result: Optional[Result] = None) -> "Relation": """ Create new Relation element from JSON data :param data: Element data from JSON :param result: The result this element belongs to :return: New instance of Relation :raises overpy.exception.ElementDataWrongType: If type value of the passed JSON data does not match. """ if data.get("type") != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=data.get("type") ) tags = data.get("tags", {}) rel_id = data.get("id") (center_lat, center_lon) = cls.get_center_from_json(data=data) members = [] supported_members = [RelationNode, RelationWay, RelationRelation] for member in data.get("members", []): type_value = member.get("type") for member_cls in supported_members: if member_cls._type_value == type_value: members.append( member_cls.from_json( member, result=result ) ) attributes = {} ignore = ["id", "members", "tags", "type"] for n, v in data.items(): if n in ignore: continue attributes[n] = v return cls( rel_id=rel_id, attributes=attributes, center_lat=center_lat, center_lon=center_lon, members=members, tags=tags, result=result ) @classmethod def from_xml(cls, child: xml.etree.ElementTree.Element, result: Optional[Result] = None) -> "Relation": """ Create new way element from XML data :param child: XML node to be parsed :param result: The result this node belongs to :return: New Way oject :raises overpy.exception.ElementDataWrongType: If name of the xml child node doesn't match :raises ValueError: If a tag doesn't have a name """ if child.tag.lower() != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=child.tag.lower() ) tags = {} members = [] center_lat = None center_lon = None supported_members = [RelationNode, RelationWay, RelationRelation, RelationArea] for sub_child in child: if sub_child.tag.lower() == "tag": name = sub_child.attrib.get("k") if name is None: raise ValueError("Tag without name/key.") value = sub_child.attrib.get("v") tags[name] = value if sub_child.tag.lower() == "member": type_value = sub_child.attrib.get("type") for member_cls in supported_members: if member_cls._type_value == type_value: members.append( member_cls.from_xml( sub_child, result=result ) ) if sub_child.tag.lower() == "center": (center_lat, center_lon) = cls.get_center_from_xml_dom(sub_child=sub_child) rel_id: Optional[int] = None rel_id_str: Optional[str] = child.attrib.get("id") if rel_id_str is not None: rel_id = int(rel_id_str) attributes = {} ignore = ["id"] for n, v in child.attrib.items(): if n in ignore: continue attributes[n] = v return cls( rel_id=rel_id, attributes=attributes, center_lat=center_lat, center_lon=center_lon, members=members, tags=tags, result=result ) class RelationMember: """ Base class to represent a member of a relation. """ _type_value: Optional[str] = None def __init__( self, attributes: Optional[dict] = None, geometry: Optional[List["RelationWayGeometryValue"]] = None, ref: Optional[int] = None, role: Optional[str] = None, result: Optional[Result] = None): """ :param ref: Reference Id :type ref: Integer :param role: The role of the relation member :type role: String :param result: """ self.ref = ref self._result = result self.role = role self.attributes = attributes self.geometry = geometry @classmethod def from_json(cls, data: dict, result: Optional[Result] = None) -> "RelationMember": """ Create new RelationMember element from JSON data :param data: Element data from JSON :param result: The result this element belongs to :return: New instance of RelationMember :raises overpy.exception.ElementDataWrongType: If type value of the passed JSON data does not match. """ if data.get("type") != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=data.get("type") ) ref = data.get("ref") role = data.get("role") attributes = {} ignore = ["geometry", "type", "ref", "role"] for n, v in data.items(): if n in ignore: continue attributes[n] = v geometry = data.get("geometry") if isinstance(geometry, list): geometry_orig = geometry geometry = [] for v in geometry_orig: geometry.append( RelationWayGeometryValue( lat=v.get("lat"), lon=v.get("lon") ) ) else: geometry = None return cls( attributes=attributes, geometry=geometry, ref=ref, role=role, result=result ) @classmethod def from_xml( cls, child: xml.etree.ElementTree.Element, result: Optional[Result] = None) -> "RelationMember": """ Create new RelationMember from XML data :param child: XML node to be parsed :param result: The result this element belongs to :return: New relation member oject :raises overpy.exception.ElementDataWrongType: If name of the xml child node doesn't match """ if child.attrib.get("type") != cls._type_value: raise exception.ElementDataWrongType( type_expected=cls._type_value, type_provided=child.tag.lower() ) ref: Optional[int] = None ref_str: Optional[str] = child.attrib.get("ref") if ref_str is not None: ref = int(ref_str) role: Optional[str] = child.attrib.get("role") attributes = {} ignore = ["geometry", "ref", "role", "type"] for n, v in child.attrib.items(): if n in ignore: continue attributes[n] = v geometry = None for sub_child in child: if sub_child.tag.lower() == "nd": if geometry is None: geometry = [] geometry.append( RelationWayGeometryValue( lat=Decimal(sub_child.attrib["lat"]), lon=Decimal(sub_child.attrib["lon"]) ) ) return cls( attributes=attributes, geometry=geometry, ref=ref, role=role, result=result ) class RelationNode(RelationMember): _type_value = "node" def resolve(self, resolve_missing: bool = False) -> Node: return self._result.get_node(self.ref, resolve_missing=resolve_missing) def __repr__(self): return f"" class RelationWay(RelationMember): _type_value = "way" def resolve(self, resolve_missing: bool = False) -> Way: return self._result.get_way(self.ref, resolve_missing=resolve_missing) def __repr__(self): return f"" class RelationWayGeometryValue: def __init__(self, lat: Union[Decimal, float], lon: Union[Decimal, float]): self.lat = lat self.lon = lon def __repr__(self): return f"" class RelationRelation(RelationMember): _type_value = "relation" def resolve(self, resolve_missing: bool = False) -> Relation: return self._result.get_relation(self.ref, resolve_missing=resolve_missing) def __repr__(self): return f"" class RelationArea(RelationMember): _type_value = "area" def resolve(self, resolve_missing: bool = False) -> Area: return self._result.get_area(self.ref, resolve_missing=resolve_missing) def __repr__(self): return f"" class OSMSAXHandler(handler.ContentHandler): """ SAX parser for Overpass XML response. """ #: Tuple of opening elements to ignore ignore_start: ClassVar = ('osm', 'meta', 'note', 'bounds', 'remark') #: Tuple of closing elements to ignore ignore_end: ClassVar = ('osm', 'meta', 'note', 'bounds', 'remark', 'tag', 'nd', 'center') def __init__(self, result: Result): """ :param result: Append results to this result set. """ handler.ContentHandler.__init__(self) self._result = result self._curr: Dict[str, Any] = {} #: Current relation member object self.cur_relation_member: Optional[RelationMember] = None def startElement(self, name: str, attrs: dict): """ Handle opening elements. :param name: Name of the element :param attrs: Attributes of the element """ if name in self.ignore_start: return try: handler = getattr(self, '_handle_start_%s' % name) except AttributeError: raise KeyError("Unknown element start '%s'" % name) handler(attrs) def endElement(self, name: str): """ Handle closing elements :param name: Name of the element """ if name in self.ignore_end: return try: handler = getattr(self, '_handle_end_%s' % name) except AttributeError: raise KeyError("Unknown element end '%s'" % name) handler() def _handle_start_center(self, attrs: dict): """ Handle opening center element :param attrs: Attributes of the element :type attrs: Dict """ center_lat = attrs.get("lat") center_lon = attrs.get("lon") if center_lat is None or center_lon is None: raise ValueError("Unable to get lat or lon of way center.") self._curr["center_lat"] = Decimal(center_lat) self._curr["center_lon"] = Decimal(center_lon) def _handle_start_tag(self, attrs: dict): """ Handle opening tag element :param attrs: Attributes of the element """ try: tag_key = attrs['k'] except KeyError: raise ValueError("Tag without name/key.") self._curr['tags'][tag_key] = attrs.get('v') def _handle_start_node(self, attrs: dict): """ Handle opening node element :param attrs: Attributes of the element """ self._curr = { 'attributes': dict(attrs), 'lat': None, 'lon': None, 'node_id': None, 'tags': {} } if attrs.get('id', None) is not None: self._curr['node_id'] = int(attrs['id']) del self._curr['attributes']['id'] if attrs.get('lat', None) is not None: self._curr['lat'] = Decimal(attrs['lat']) del self._curr['attributes']['lat'] if attrs.get('lon', None) is not None: self._curr['lon'] = Decimal(attrs['lon']) del self._curr['attributes']['lon'] def _handle_end_node(self): """ Handle closing node element """ self._result.append(Node(result=self._result, **self._curr)) self._curr = {} def _handle_start_way(self, attrs: dict): """ Handle opening way element :param attrs: Attributes of the element """ self._curr = { 'center_lat': None, 'center_lon': None, 'attributes': dict(attrs), 'node_ids': [], 'tags': {}, 'way_id': None } if attrs.get('id', None) is not None: self._curr['way_id'] = int(attrs['id']) del self._curr['attributes']['id'] def _handle_end_way(self): """ Handle closing way element """ self._result.append(Way(result=self._result, **self._curr)) self._curr = {} def _handle_start_area(self, attrs: dict): """ Handle opening area element :param attrs: Attributes of the element """ self._curr = { 'attributes': dict(attrs), 'tags': {}, 'area_id': None } if attrs.get('id', None) is not None: self._curr['area_id'] = int(attrs['id']) del self._curr['attributes']['id'] def _handle_end_area(self): """ Handle closing area element """ self._result.append(Area(result=self._result, **self._curr)) self._curr = {} def _handle_start_nd(self, attrs: dict): """ Handle opening nd element :param attrs: Attributes of the element """ if isinstance(self.cur_relation_member, RelationWay): if self.cur_relation_member.geometry is None: self.cur_relation_member.geometry = [] self.cur_relation_member.geometry.append( RelationWayGeometryValue( lat=Decimal(attrs["lat"]), lon=Decimal(attrs["lon"]) ) ) else: try: node_ref = attrs['ref'] except KeyError: raise ValueError("Unable to find required ref value.") self._curr['node_ids'].append(int(node_ref)) def _handle_start_relation(self, attrs: dict): """ Handle opening relation element :param attrs: Attributes of the element """ self._curr = { 'attributes': dict(attrs), 'members': [], 'rel_id': None, 'tags': {} } if attrs.get('id', None) is not None: self._curr['rel_id'] = int(attrs['id']) del self._curr['attributes']['id'] def _handle_end_relation(self): """ Handle closing relation element """ self._result.append(Relation(result=self._result, **self._curr)) self._curr = {} def _handle_start_member(self, attrs: dict): """ Handle opening member element :param attrs: Attributes of the element """ params: Dict[str, Any] = { # ToDo: Parse attributes 'attributes': {}, 'ref': None, 'result': self._result, 'role': None } if attrs.get('ref', None): params['ref'] = int(attrs['ref']) if attrs.get('role', None): params['role'] = attrs['role'] cls_map = { "area": RelationArea, "node": RelationNode, "relation": RelationRelation, "way": RelationWay } cls: Type[RelationMember] = cls_map.get(attrs["type"]) if cls is None: raise ValueError("Undefined type for member: '%s'" % attrs['type']) self.cur_relation_member = cls(**params) self._curr['members'].append(self.cur_relation_member) def _handle_end_member(self): self.cur_relation_member = None python-overpy-0.7/overpy/exception.py000066400000000000000000000112731453334100400201200ustar00rootroot00000000000000class OverPyException(Exception): """OverPy base exception""" pass class DataIncomplete(OverPyException): """ Raised if the requested data isn't available in the result. Try to improve the query or to resolve the missing data. """ def __init__(self, *args, **kwargs): OverPyException.__init__( self, "Data incomplete try to improve the query to resolve the missing data", *args, **kwargs ) class ElementDataWrongType(OverPyException): """ Raised if the provided element does not match the expected type. :param type_expected: The expected element type :type type_expected: String :param type_provided: The provided element type :type type_provided: String|None """ def __init__(self, type_expected, type_provided=None): self.type_expected = type_expected self.type_provided = type_provided def __str__(self) -> str: return "Type expected '{}' but '{}' provided".format( self.type_expected, str(self.type_provided) ) class MaxRetriesReached(OverPyException): """ Raised if max retries reached and the Overpass server didn't respond with a result. """ def __init__(self, retry_count, exceptions): self.exceptions = exceptions self.retry_count = retry_count def __str__(self) -> str: return "Unable get any result from the Overpass API server after %d retries." % self.retry_count class OverpassBadRequest(OverPyException): """ Raised if the Overpass API service returns a syntax error. :param query: The encoded query how it was send to the server :type query: Bytes :param msgs: List of error messages :type msgs: List """ def __init__(self, query, msgs=None): self.query = query if msgs is None: msgs = [] self.msgs = msgs def __str__(self) -> str: tmp_msgs = [] for tmp_msg in self.msgs: if not isinstance(tmp_msg, str): tmp_msg = str(tmp_msg) tmp_msgs.append(tmp_msg) return "\n".join(tmp_msgs) class OverpassError(OverPyException): """ Base exception to report errors if the response returns a remark tag or element. .. note:: If you are not sure which of the subexceptions you should use, use this one and try to parse the message. For more information have a look at https://github.com/DinoTools/python-overpy/issues/62 :param str msg: The message from the remark tag or element """ def __init__(self, msg=None): #: The message from the remark tag or element self.msg = msg def __str__(self) -> str: if self.msg is None: return "No error message provided" if not isinstance(self.msg, str): return str(self.msg) return self.msg class OverpassGatewayTimeout(OverPyException): """ Raised if load of the Overpass API service is too high and it can't handle the request. """ def __init__(self): OverPyException.__init__(self, "Server load too high") class OverpassRuntimeError(OverpassError): """ Raised if the server returns a remark-tag(xml) or remark element(json) with a message starting with 'runtime error:'. """ pass class OverpassRuntimeRemark(OverpassError): """ Raised if the server returns a remark-tag(xml) or remark element(json) with a message starting with 'runtime remark:'. """ pass class OverpassTooManyRequests(OverPyException): """ Raised if the Overpass API service returns a 429 status code. """ def __init__(self): OverPyException.__init__(self, "Too many requests") class OverpassUnknownContentType(OverPyException): """ Raised if the reported content type isn't handled by OverPy. :param content_type: The reported content type :type content_type: None or String """ def __init__(self, content_type): self.content_type = content_type def __str__(self) -> str: if self.content_type is None: return "No content type returned" return "Unknown content type: %s" % self.content_type class OverpassUnknownError(OverpassError): """ Raised if the server returns a remark-tag(xml) or remark element(json) and we are unable to find any reason. """ pass class OverpassUnknownHTTPStatusCode(OverPyException): """ Raised if the returned HTTP status code isn't handled by OverPy. :param code: The HTTP status code :type code: Integer """ def __init__(self, code): self.code = code def __str__(self) -> str: return "Unknown/Unhandled status code: %d" % self.code python-overpy-0.7/overpy/helper.py000066400000000000000000000035361453334100400174040ustar00rootroot00000000000000from typing import List, Optional __author__ = 'mjob' import overpy def get_street( street: str, areacode: str, api: Optional[overpy.Overpass] = None) -> overpy.Result: """ Retrieve streets in a given bounding area :param street: Name of street :param areacode: The OSM id of the bounding area :param api: API object to fetch missing elements :return: Parsed result :raises overpy.exception.OverPyException: If something bad happens. """ if api is None: api = overpy.Overpass() query = """ area(%s)->.location; ( way[highway][name="%s"](area.location); - ( way[highway=service](area.location); way[highway=track](area.location); ); ); out body; >; out skel qt; """ data = api.query(query % (areacode, street)) return data def get_intersection( street1: str, street2: str, areacode: str, api: Optional[overpy.Overpass] = None) -> List[overpy.Node]: """ Retrieve intersection of two streets in a given bounding area :param street1: Name of first street of intersection :param street2: Name of second street of intersection :param areacode: The OSM id of the bounding area :param api: API object to fetch missing elements :return: List of intersections :raises overpy.exception.OverPyException: If something bad happens. """ if api is None: api = overpy.Overpass() query = """ area(%s)->.location; ( way[highway][name="%s"](area.location); node(w)->.n1; way[highway][name="%s"](area.location); node(w)->.n2; ); node.n1.n2; out meta; """ data = api.query(query % (areacode, street1, street2)) return data.get_nodes() python-overpy-0.7/setup.cfg000066400000000000000000000016731453334100400160500ustar00rootroot00000000000000[metadata] license-file = LICENSE long_description = file: README.rst long_description_content_type = text/x-rst classifiers = Development Status :: 4 - Beta License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy project_urls = Documentation = https://python-overpy.readthedocs.io/ Source = https://github.com/DinoTools/python-overpy Issue Tracker = https://github.com/DinoTools/python-overpy/issues [options] python_requires = >=3.6 include_package_data = true zip_safe = false [aliases] test=pytest [tool:pytest] python_files = tests/*.py python-overpy-0.7/setup.py000077500000000000000000000011731453334100400157370ustar00rootroot00000000000000#!/usr/bin/env python from pathlib import Path from setuptools import setup, find_packages HERE = Path(__file__).resolve().parent about = {} exec((HERE / "overpy" / "__about__.py").read_text(), about) setup( name=about["__title__"], version=about["__version__"], description=about["__summary__"], license=about["__license__"], url=about["__uri__"], author=about["__author__"], keywords="OverPy Overpass OSM OpenStreetMap", install_requires=[], packages=find_packages(exclude=["*.tests", "*.tests.*", "tests"]), package_data={ # "": ["README"], }, tests_require=["pytest"], ) python-overpy-0.7/tests/000077500000000000000000000000001453334100400153625ustar00rootroot00000000000000python-overpy-0.7/tests/README.md000066400000000000000000000011601453334100400166370ustar00rootroot00000000000000Data ==== Queries to get test data. Have a look at https://overpass-turbo.eu/ to test the queries. area-01 (2016-11-22) -------------------- ``` area[name="Troisdorf"]; out; ``` relation-03 (2016-11-23) ------------------------ ``` (rel["ref"="A 555"];); out center; ``` relation-04 (2016-11-24) ------------------------ ``` (rel["ref"="A 555"];); out geom; ``` way-03.xml (2016-11-22) ----------------------- ``` (way(225576797);>;); out meta center; ``` way-04 (2016-11-22) ------------------- ``` (way(225576797);); out center; ``` * With empty center information to test exception, this should never happen python-overpy-0.7/tests/__init__.py000066400000000000000000000023141453334100400174730ustar00rootroot00000000000000import sys import threading from pathlib import Path from threading import Lock from socketserver import BaseRequestHandler, TCPServer from http.server import HTTPServer TCPServer.allow_reuse_address = True HOST = "127.0.0.1" PORT_START = sys.version_info[0] * 10000 + sys.version_info[1] * 100 current_port = PORT_START test_lock = Lock() class OverpyBaseRequestHandler(BaseRequestHandler): def handle(self): for data in self.get_response(self): self.request.send(data) @staticmethod def get_response(): yield b"" def read_file(filename, mode="r"): return (Path(__file__).resolve().parent / filename).open(mode).read() def new_server_thread(handle_cls, port=None): global current_port if port is None: test_lock.acquire() port = current_port current_port += 1 test_lock.release() server = HTTPServer( (HOST, port), handle_cls ) server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() return ( "http://%s:%d" % (HOST, port), server ) def stop_server_thread(server): server.shutdown() server.server_close() python-overpy-0.7/tests/base_class.py000066400000000000000000000367061453334100400200470ustar00rootroot00000000000000from decimal import Decimal from datetime import datetime import pytest import overpy class BaseTestAreas: @staticmethod def _test_area01(result): assert len(result.areas) == 4 assert len(result.nodes) == 0 assert len(result.relations) == 0 assert len(result.ways) == 0 area = result.areas[0] assert isinstance(area, overpy.Area) assert isinstance(area.id, int) assert area.id == 2448756446 assert isinstance(area.tags, dict) assert len(area.tags) == 12 area = result.areas[1] assert isinstance(area, overpy.Area) assert isinstance(area.id, int) assert area.id == 3600055060 assert isinstance(area.tags, dict) assert len(area.tags) == 13 area = result.areas[2] assert isinstance(area, overpy.Area) assert isinstance(area.id, int) assert area.id == 3605945175 assert isinstance(area.tags, dict) assert len(area.tags) == 12 area = result.areas[3] assert isinstance(area, overpy.Area) assert isinstance(area.id, int) assert area.id == 3605945176 assert isinstance(area.tags, dict) assert len(area.tags) == 14 # try to get a single area by id area = result.get_area(3605945175) assert area.id == 3605945175 # try to get a single area by id not available in the result with pytest.raises(overpy.exception.DataIncomplete): result.get_area(123456) # area_ids is an alias for get_node_ids() and should return the same data for area_ids in (result.area_ids, result.get_area_ids()): assert len(area_ids) == 4 assert area_ids[0] == 2448756446 assert area_ids[1] == 3600055060 assert area_ids[2] == 3605945175 assert area_ids[3] == 3605945176 assert len(result.node_ids) == 0 assert len(result.get_node_ids()) == 0 assert len(result.relation_ids) == 0 assert len(result.get_relation_ids()) == 0 assert len(result.way_ids) == 0 assert len(result.get_way_ids()) == 0 class BaseTestNodes: @staticmethod def _test_node01(result): assert len(result.nodes) == 3 assert len(result.relations) == 0 assert len(result.ways) == 0 node = result.nodes[0] assert isinstance(node, overpy.Node) assert isinstance(node.id, int) assert isinstance(node.lat, Decimal) assert isinstance(node.lon, Decimal) assert node.id == 50878400 assert node.lat == Decimal("50.7461788") assert node.lon == Decimal("7.1742257") assert isinstance(node.tags, dict) assert len(node.tags) == 0 node = result.nodes[1] assert isinstance(node, overpy.Node) assert isinstance(node.id, int) assert isinstance(node.lat, Decimal) assert isinstance(node.lon, Decimal) assert node.id == 100793192 assert node.lat == Decimal("50.7468472") assert node.lon == Decimal("7.1709376") assert isinstance(node.tags, dict) assert len(node.tags) == 1 assert node.tags["highway"] == "turning_circle" node = result.nodes[2] assert isinstance(node, overpy.Node) assert isinstance(node.id, int) assert isinstance(node.lat, Decimal) assert isinstance(node.lon, Decimal) assert node.id == 3233854234 assert node.lat == Decimal("50.7494236") assert node.lon == Decimal("7.1757664") assert isinstance(node.attributes, dict) assert len(node.attributes) == 5 assert node.attributes["changeset"] == 23456789 assert node.attributes["timestamp"] == datetime(2014, 12, 14, 7, 27, 19, 0, None) assert node.attributes["uid"] == 345678 assert node.attributes["user"] == "TestUser" assert node.attributes["version"] == 1 # try to get a single node by id node = result.get_node(50878400) assert node.id == 50878400 # try to get a single node by id not available in the result with pytest.raises(overpy.exception.DataIncomplete): result.get_node(123456) # node_ids is an alias for get_node_ids() and should return the same data for node_ids in (result.node_ids, result.get_node_ids()): assert len(node_ids) == 3 assert node_ids[0] == 50878400 assert node_ids[1] == 100793192 assert node_ids[2] == 3233854234 assert len(result.relation_ids) == 0 assert len(result.get_relation_ids()) == 0 assert len(result.way_ids) == 0 assert len(result.get_way_ids()) == 0 class BaseTestRelation: @staticmethod def _test_relation01(result): assert len(result.nodes) == 0 assert len(result.relations) == 1 assert len(result.ways) == 0 relation = result.relations[0] assert isinstance(relation, overpy.Relation) assert isinstance(relation.id, int) assert relation.id == 2046898 assert isinstance(relation.tags, dict) assert len(relation.tags) == 6 assert relation.tags["from"] == "Here" assert relation.tags["name"] == "Test relation" assert relation.tags["ref"] == "609" assert relation.tags["route"] == "bus" assert relation.tags["to"] == "There" assert relation.tags["type"] == "route" assert isinstance(relation.attributes, dict) assert len(relation.attributes) == 5 assert relation.attributes["changeset"] == 17433822 assert relation.attributes["timestamp"] == datetime(2014, 12, 15, 13, 13, 11, 0, None) assert relation.attributes["uid"] == 12345 assert relation.attributes["user"] == "Username" assert relation.attributes["version"] == 12 assert len(relation.members) == 5 assert isinstance(relation.members[0], overpy.RelationNode) assert isinstance(relation.members[1], overpy.RelationNode) assert isinstance(relation.members[2], overpy.RelationNode) assert isinstance(relation.members[3], overpy.RelationNode) assert isinstance(relation.members[4], overpy.RelationWay) @staticmethod def _test_relation02(result): assert len(result.nodes) == 3 assert len(result.relations) == 1 assert len(result.ways) == 1 relation = result.relations[0] assert isinstance(relation, overpy.Relation) assert isinstance(relation.id, int) assert relation.id == 2046898 assert isinstance(relation.tags, dict) assert len(relation.tags) == 6 assert relation.tags["from"] == "Here" assert relation.tags["name"] == "Test relation" assert relation.tags["ref"] == "609" assert relation.tags["route"] == "bus" assert relation.tags["to"] == "There" assert relation.tags["type"] == "route" assert isinstance(relation.attributes, dict) assert len(relation.attributes) == 5 assert len(relation.members) == 4 member = relation.members[0] assert isinstance(member, overpy.RelationNode) node = member.resolve() assert isinstance(node, overpy.Node) assert node.id == 3233854233 assert member.ref == node.id member = relation.members[1] assert isinstance(member, overpy.RelationNode) node = member.resolve() assert isinstance(node, overpy.Node) assert node.id == 3233854234 assert member.ref == node.id member = relation.members[2] assert isinstance(member, overpy.RelationNode) node = member.resolve() assert isinstance(node, overpy.Node) assert node.id == 3233854235 assert member.ref == node.id member = relation.members[3] assert isinstance(member, overpy.RelationWay) way = member.resolve() assert isinstance(way, overpy.Way) assert way.id == 317146078 assert member.ref == way.id @staticmethod def _test_relation03(result): assert len(result.nodes) == 0 assert len(result.relations) == 1 assert len(result.ways) == 0 relation = result.relations[0] assert isinstance(relation, overpy.Relation) assert isinstance(relation.id, int) assert relation.id == 23092 assert isinstance(relation.tags, dict) assert len(relation.tags) == 10 assert isinstance(relation.center_lat, Decimal) assert isinstance(relation.center_lon, Decimal) assert relation.center_lat == Decimal("50.8176646") assert relation.center_lon == Decimal("7.0208539") @staticmethod def _test_relation04(result): assert len(result.nodes) == 0 assert len(result.relations) == 1 assert len(result.ways) == 0 relation = result.relations[0] assert isinstance(relation, overpy.Relation) assert isinstance(relation.id, int) assert relation.id == 23092 assert isinstance(relation.tags, dict) assert len(relation.tags) == 10 way = relation.members[2] assert isinstance(way, overpy.RelationWay) assert len(way.attributes) == 0 assert isinstance(way.attributes, dict) assert isinstance(way.geometry, list) assert len(way.geometry) == 2 assert isinstance(way.geometry[0], overpy.RelationWayGeometryValue) assert isinstance(way.geometry[0].lat, Decimal) assert isinstance(way.geometry[0].lon, Decimal) assert way.geometry[0].lat == Decimal("50.8137408") assert way.geometry[0].lon == Decimal("6.9813352") class BaseTestWay: @staticmethod def _test_way01(result): assert len(result.nodes) == 0 assert len(result.relations) == 0 assert len(result.ways) == 2 way = result.ways[0] assert isinstance(way, overpy.Way) assert isinstance(way.id, int) assert way.id == 317146077 assert isinstance(way.tags, dict) assert len(way.tags) == 1 assert way.tags["building"] == "yes" assert isinstance(way.attributes, dict) assert len(way.attributes) == 0 way = result.ways[1] assert isinstance(way, overpy.Way) assert isinstance(way.id, int) assert way.id == 317146078 assert isinstance(way.tags, dict) assert len(way.tags) == 0 assert isinstance(way.attributes, dict) assert len(way.attributes) == 5 assert way.attributes["changeset"] == 23456789 assert way.attributes["timestamp"] == datetime(2014, 12, 14, 7, 27, 21, 0, None) assert way.attributes["uid"] == 345678 assert way.attributes["user"] == "TestUser" assert way.attributes["version"] == 1 # try to get a single way by id way = result.get_way(317146077) assert way.id == 317146077 # try to get a single way by id not available in the result with pytest.raises(overpy.exception.DataIncomplete): result.get_way(123456) assert len(result.node_ids) == 0 assert len(result.get_node_ids()) == 0 assert len(result.relation_ids) == 0 assert len(result.get_relation_ids()) == 0 # way_ids is an alias for get_way_ids() and should return the same data for way_ids in (result.way_ids, result.get_way_ids()): assert len(way_ids) == 2 assert way_ids[0] == 317146077 assert way_ids[1] == 317146078 @staticmethod def _test_way02(result): assert len(result.nodes) == 6 assert len(result.relations) == 0 assert len(result.ways) == 1 node = result.nodes[0] assert isinstance(node, overpy.Node) assert isinstance(node.id, int) assert isinstance(node.lat, Decimal) assert isinstance(node.lon, Decimal) assert node.id == 3233854233 assert node.lat == Decimal("50.7494187") assert node.lon == Decimal("7.1758731") way = result.ways[0] assert isinstance(way, overpy.Way) assert isinstance(way.id, int) assert way.id == 317146077 assert isinstance(way.tags, dict) assert len(way.tags) == 1 assert way.tags["building"] == "yes" nodes = way.nodes assert len(nodes) == 7 node = nodes[0] assert isinstance(node, overpy.Node) assert node.id == 3233854241 # try to get a single way by id way = result.get_way(317146077) assert way.id == 317146077 # try to get a single way by id not available in the result with pytest.raises(overpy.exception.DataIncomplete): result.get_way(123456) # node_ids is an alias for get_node_ids() and should return the same data for node_ids in (result.node_ids, result.get_node_ids()): assert len(node_ids) == 6 assert node_ids[0] == 3233854233 assert node_ids[1] == 3233854234 assert node_ids[2] == 3233854236 assert node_ids[3] == 3233854237 assert node_ids[4] == 3233854238 assert node_ids[5] == 3233854241 assert len(result.relation_ids) == 0 assert len(result.get_relation_ids()) == 0 # way_ids is an alias for get_way_ids() and should return the same data for way_ids in (result.way_ids, result.get_way_ids()): assert len(way_ids) == 1 assert way_ids[0] == 317146077 @staticmethod def _test_way03(result): assert len(result.nodes) == 4 assert len(result.relations) == 0 assert len(result.ways) == 1 way = result.ways[0] assert isinstance(way, overpy.Way) assert isinstance(way.id, int) assert way.id == 225576797 assert isinstance(way.tags, dict) assert len(way.tags) == 2 assert way.tags["building"] == "kiosk" assert way.tags["shop"] == "florist" assert isinstance(way.center_lat, Decimal) assert isinstance(way.center_lon, Decimal) assert way.center_lat == Decimal("41.8954998") assert way.center_lon == Decimal("12.5032265") for nodes in (way.nodes, way.get_nodes()): assert len(nodes) == 5 for node in nodes: assert isinstance(node, overpy.Node) assert isinstance(node.id, int) assert nodes[0].id == 2343425525 assert nodes[1].id == 2343425528 assert nodes[2].id == 2343425526 assert nodes[3].id == 2343425523 assert nodes[4].id == 2343425525 # try to get a single way by id way = result.get_way(225576797) assert way.id == 225576797 # try to get a single way by id not available in the result with pytest.raises(overpy.exception.DataIncomplete): result.get_way(123456) # node_ids is an alias for get_node_ids() and should return the same data for node_ids in (result.node_ids, result.get_node_ids()): assert len(node_ids) == 4 assert node_ids[0] == 2343425523 assert node_ids[1] == 2343425525 assert node_ids[2] == 2343425526 assert node_ids[3] == 2343425528 assert len(result.relation_ids) == 0 assert len(result.get_relation_ids()) == 0 # way_ids is an alias for get_way_ids() and should return the same data for way_ids in (result.way_ids, result.get_way_ids()): assert len(way_ids) == 1 assert way_ids[0] == 225576797 python-overpy-0.7/tests/json/000077500000000000000000000000001453334100400163335ustar00rootroot00000000000000python-overpy-0.7/tests/json/area-01.json000066400000000000000000000044541453334100400203630ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2016-11-22T21:04:02Z", "timestamp_areas_base": "2016-11-22T20:25:03Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "area", "id": 2448756446, "tags": { "addr:city": "Troisdorf", "addr:postcode": "53840", "area": "yes", "description": "Troisdorf Bahnsteig Gleis 9", "name": "Troisdorf", "public_transport": "platform", "railway": "platform", "ref": "9", "train": "yes", "wheelchair": "no", "wheelchair:description": "Plattformlift ist vorhanden, Betriebsbereitschaft nach 8 Jahren stillstand fraglich.", "width": "5" } } , { "type": "area", "id": 3600055060, "tags": { "TMC:cid_58:tabcd_1:Class": "Area", "TMC:cid_58:tabcd_1:LCLversion": "8.00", "TMC:cid_58:tabcd_1:LocationCode": "2550", "admin_level": "8", "boundary": "administrative", "de:amtlicher_gemeindeschluessel": "05382068", "de:place": "town", "de:regionalschluessel": "053820068068", "name": "Troisdorf", "name:prefix": "Stadt", "type": "boundary", "wikidata": "Q3900", "wikipedia": "de:Troisdorf" } } , { "type": "area", "id": 3605945175, "tags": { "addr:city": "Troisdorf", "addr:postcode": "53840", "description": "Troisdorf Bahnsteig Gleis 1+2", "local_ref": "1;2", "name": "Troisdorf", "public_transport": "platform", "railway": "platform", "ref": "1/2", "tactile_paving": "yes", "train": "yes", "type": "multipolygon", "wheelchair": "yes" } } , { "type": "area", "id": 3605945176, "tags": { "addr:city": "Troisdorf", "addr:postcode": "53840", "description": "Troisdorf Bahnsteig Gleis 5+6", "name": "Troisdorf", "phone": "+49 221 1411055", "public_transport": "platform", "railway": "platform", "ref": "5/6", "tactile_paving": "yes", "train": "yes", "type": "multipolygon", "wheelchair": "yes", "wheelchair:description": "Der Aufzug zu diesem Bahnsteig ist oft defekt, bitte informieren. Betriebszustand kann bei 3S-Zentrale erfragt werden (siehe Telefonnummer, aber Vorsicht, die sind nicht immer informiert!)", "width": "6" } } ] } python-overpy-0.7/tests/json/node-01.json000066400000000000000000000012461453334100400203740ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T12:58:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 50878400, "lat": 50.7461788, "lon": 7.1742257 }, { "type": "node", "id": 100793192, "lat": 50.7468472, "lon": 7.1709376, "tags": { "highway": "turning_circle" } }, { "type": "node", "id": 3233854234, "lat": 50.7494236, "lon": 7.1757664, "timestamp": "2014-12-14T07:27:19Z", "version": 1, "changeset": 23456789, "user": "TestUser", "uid": 345678 } ] }python-overpy-0.7/tests/json/relation-01.json000066400000000000000000000022171453334100400212630ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-21T20:00:03Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "relation", "id": 2046898, "timestamp": "2014-12-15T13:13:11Z", "version": 12, "changeset": 17433822, "user": "Username", "uid": 12345, "members": [ { "type": "node", "ref": 507464632, "role": "platform" }, { "type": "node", "ref": 2252681768, "role": "stop" }, { "type": "node", "ref": 507464636, "role": "platform" }, { "type": "node", "ref": 1620886108, "role": "stop" }, { "type": "way", "ref": 4893348, "role": "" } ], "tags": { "from": "Here", "name": "Test relation", "ref": "609", "route": "bus", "to": "There", "type": "route" } } ] } python-overpy-0.7/tests/json/relation-02.json000066400000000000000000000027731453334100400212730ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 3233854233, "lat": 50.7494187, "lon": 7.1758731 }, { "type": "node", "id": 3233854234, "lat": 50.7494287, "lon": 7.1758731 }, { "type": "node", "id": 3233854235, "lat": 50.7494287, "lon": 7.1758731 }, { "type": "way", "id": 317146078, "nodes": [ 3233854233, 3233854234, 3233854235 ] }, { "type": "relation", "id": 2046898, "timestamp": "2014-12-15T13:13:11Z", "version": 12, "changeset": 17433822, "user": "Username", "uid": 12345, "members": [ { "type": "node", "ref": 3233854233, "role": "platform" }, { "type": "node", "ref": 3233854234, "role": "stop" }, { "type": "node", "ref": 3233854235, "role": "platform" }, { "type": "way", "ref": 317146078, "role": "" } ], "tags": { "from": "Here", "name": "Test relation", "ref": "609", "route": "bus", "to": "There", "type": "route" } } ] }python-overpy-0.7/tests/json/relation-03.json000066400000000000000000000246061453334100400212730ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2016-11-23T20:28:03Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "relation", "id": 23092, "center": { "lat": 50.8176646, "lon": 7.0208539 }, "members": [ { "type": "way", "ref": 4334856, "role": "" }, { "type": "way", "ref": 234434903, "role": "" }, { "type": "way", "ref": 37881522, "role": "" }, { "type": "way", "ref": 37881521, "role": "" }, { "type": "way", "ref": 4356491, "role": "" }, { "type": "way", "ref": 235363211, "role": "" }, { "type": "way", "ref": 48290877, "role": "" }, { "type": "way", "ref": 210683519, "role": "" }, { "type": "way", "ref": 42743961, "role": "" }, { "type": "way", "ref": 210683522, "role": "" }, { "type": "way", "ref": 48290881, "role": "" }, { "type": "way", "ref": 235363214, "role": "" }, { "type": "way", "ref": 4400137, "role": "" }, { "type": "way", "ref": 230940375, "role": "" }, { "type": "way", "ref": 4400140, "role": "" }, { "type": "way", "ref": 4400142, "role": "" }, { "type": "way", "ref": 235824476, "role": "" }, { "type": "way", "ref": 4400143, "role": "" }, { "type": "way", "ref": 235824475, "role": "" }, { "type": "way", "ref": 178797123, "role": "" }, { "type": "way", "ref": 233553030, "role": "" }, { "type": "way", "ref": 4829989, "role": "" }, { "type": "way", "ref": 99834112, "role": "" }, { "type": "way", "ref": 133081219, "role": "" }, { "type": "way", "ref": 234434905, "role": "" }, { "type": "way", "ref": 20661567, "role": "" }, { "type": "way", "ref": 230941900, "role": "" }, { "type": "way", "ref": 20661568, "role": "" }, { "type": "way", "ref": 20661572, "role": "" }, { "type": "way", "ref": 230940374, "role": "" }, { "type": "way", "ref": 20661573, "role": "" }, { "type": "way", "ref": 20662817, "role": "" }, { "type": "way", "ref": 230941903, "role": "" }, { "type": "way", "ref": 20662819, "role": "" }, { "type": "way", "ref": 20662824, "role": "" }, { "type": "way", "ref": 20662827, "role": "" }, { "type": "way", "ref": 27492515, "role": "" }, { "type": "way", "ref": 129125122, "role": "" }, { "type": "way", "ref": 234434901, "role": "" }, { "type": "way", "ref": 234434904, "role": "" }, { "type": "way", "ref": 27492542, "role": "" }, { "type": "way", "ref": 27492543, "role": "" }, { "type": "way", "ref": 29233646, "role": "" }, { "type": "way", "ref": 235820561, "role": "" }, { "type": "way", "ref": 29233647, "role": "" }, { "type": "way", "ref": 235820559, "role": "" }, { "type": "way", "ref": 235820562, "role": "" }, { "type": "way", "ref": 29233648, "role": "" }, { "type": "way", "ref": 29382960, "role": "" }, { "type": "way", "ref": 271008229, "role": "" }, { "type": "way", "ref": 271008238, "role": "" }, { "type": "way", "ref": 271008230, "role": "" }, { "type": "way", "ref": 271008226, "role": "" }, { "type": "way", "ref": 40033062, "role": "" }, { "type": "way", "ref": 40033063, "role": "" }, { "type": "way", "ref": 29384561, "role": "" }, { "type": "way", "ref": 29384563, "role": "" }, { "type": "way", "ref": 271008224, "role": "" }, { "type": "way", "ref": 271008227, "role": "" }, { "type": "way", "ref": 271008237, "role": "" }, { "type": "way", "ref": 271008232, "role": "" }, { "type": "way", "ref": 271008239, "role": "" }, { "type": "way", "ref": 29384564, "role": "" }, { "type": "way", "ref": 31282638, "role": "" }, { "type": "way", "ref": 31282787, "role": "" }, { "type": "way", "ref": 383262762, "role": "" }, { "type": "way", "ref": 31304443, "role": "" }, { "type": "way", "ref": 128541594, "role": "" }, { "type": "way", "ref": 31304503, "role": "" }, { "type": "way", "ref": 31363881, "role": "" }, { "type": "way", "ref": 31363891, "role": "" }, { "type": "way", "ref": 31363892, "role": "" }, { "type": "way", "ref": 31363898, "role": "" }, { "type": "way", "ref": 31363910, "role": "" }, { "type": "way", "ref": 31364152, "role": "" }, { "type": "way", "ref": 31364158, "role": "" }, { "type": "way", "ref": 31364178, "role": "" }, { "type": "way", "ref": 31364384, "role": "" }, { "type": "way", "ref": 31364387, "role": "" }, { "type": "way", "ref": 31364484, "role": "" }, { "type": "way", "ref": 31364512, "role": "" }, { "type": "way", "ref": 31364656, "role": "" }, { "type": "way", "ref": 31364667, "role": "" }, { "type": "way", "ref": 271008234, "role": "" }, { "type": "way", "ref": 31364888, "role": "" }, { "type": "way", "ref": 122158730, "role": "" }, { "type": "way", "ref": 31364985, "role": "" }, { "type": "way", "ref": 271008235, "role": "" }, { "type": "way", "ref": 271008231, "role": "" }, { "type": "way", "ref": 271008233, "role": "" }, { "type": "way", "ref": 31365377, "role": "" }, { "type": "way", "ref": 31365425, "role": "" }, { "type": "way", "ref": 271008236, "role": "" }, { "type": "way", "ref": 36447898, "role": "" }, { "type": "way", "ref": 271008228, "role": "" }, { "type": "way", "ref": 31366812, "role": "" }, { "type": "way", "ref": 31366880, "role": "" }, { "type": "way", "ref": 31367017, "role": "" }, { "type": "way", "ref": 31367443, "role": "" }, { "type": "way", "ref": 31367449, "role": "" }, { "type": "way", "ref": 31367526, "role": "" }, { "type": "way", "ref": 31367534, "role": "" }, { "type": "way", "ref": 31369852, "role": "" }, { "type": "way", "ref": 449397558, "role": "" }, { "type": "way", "ref": 31797389, "role": "" }, { "type": "way", "ref": 31798039, "role": "" }, { "type": "way", "ref": 235363212, "role": "" }, { "type": "way", "ref": 156492546, "role": "" }, { "type": "way", "ref": 156492545, "role": "" }, { "type": "way", "ref": 130749935, "role": "" }, { "type": "way", "ref": 32472877, "role": "" }, { "type": "way", "ref": 31798988, "role": "" }, { "type": "way", "ref": 31798989, "role": "" }, { "type": "way", "ref": 235820560, "role": "" }, { "type": "way", "ref": 235820563, "role": "" }, { "type": "way", "ref": 235820564, "role": "" }, { "type": "way", "ref": 235820570, "role": "" }, { "type": "way", "ref": 32472855, "role": "" }, { "type": "way", "ref": 32472856, "role": "" }, { "type": "way", "ref": 37881520, "role": "" }, { "type": "way", "ref": 37881519, "role": "" }, { "type": "way", "ref": 234434902, "role": "" }, { "type": "way", "ref": 32472875, "role": "" }, { "type": "way", "ref": 32473071, "role": "" }, { "type": "way", "ref": 128522486, "role": "" }, { "type": "way", "ref": 36447896, "role": "" }, { "type": "way", "ref": 32473075, "role": "" }, { "type": "way", "ref": 32473086, "role": "" }, { "type": "way", "ref": 32473087, "role": "" }, { "type": "way", "ref": 40033064, "role": "" }, { "type": "way", "ref": 189189059, "role": "" }, { "type": "way", "ref": 271008225, "role": "" }, { "type": "way", "ref": 41550921, "role": "" } ], "tags": { "TMC:cid_58:tabcd_1:Class": "Road", "TMC:cid_58:tabcd_1:LCLversion": "8.00", "TMC:cid_58:tabcd_1:LocationCode": "7142", "name": "Bundesautobahn 555", "network": "BAB", "operator": "Bundesrepublik Deutschland", "ref": "A 555", "route": "road", "type": "route", "wikipedia": "de:Bundesautobahn 555" } } ] } python-overpy-0.7/tests/json/relation-04.json000066400000000000000000001042211453334100400212640ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2016-11-24T21:40:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "relation", "id": 23092, "bounds": { "minlat": 50.7432318, "minlon": 6.9639432, "maxlat": 50.8920975, "maxlon": 7.0777645 }, "members": [ { "type": "way", "ref": 4334856, "role": "", "geometry": [ { "lat": 50.8104598, "lon": 6.9871803 }, { "lat": 50.8117239, "lon": 6.9849282 } ] }, { "type": "way", "ref": 234434903, "role": "", "geometry": [ { "lat": 50.8117239, "lon": 6.9849282 }, { "lat": 50.8137408, "lon": 6.9813352 } ] }, { "type": "way", "ref": 37881522, "role": "", "geometry": [ { "lat": 50.8137408, "lon": 6.9813352 }, { "lat": 50.8140146, "lon": 6.9808445 } ] }, { "type": "way", "ref": 37881521, "role": "", "geometry": [ { "lat": 50.8140146, "lon": 6.9808445 }, { "lat": 50.8193541, "lon": 6.9713457 }, { "lat": 50.8203182, "lon": 6.9697248 }, { "lat": 50.8210652, "lon": 6.9685758 }, { "lat": 50.8217885, "lon": 6.9676136 }, { "lat": 50.8225495, "lon": 6.9667439 }, { "lat": 50.8233005, "lon": 6.9660515 }, { "lat": 50.8238128, "lon": 6.9656463 }, { "lat": 50.8243279, "lon": 6.9653077 } ] }, { "type": "way", "ref": 4356491, "role": "", "geometry": [ { "lat": 50.7433997, "lon": 7.0777645 }, { "lat": 50.7434097, "lon": 7.0775890 }, { "lat": 50.7434629, "lon": 7.0774402 }, { "lat": 50.7435198, "lon": 7.0773718 }, { "lat": 50.7437507, "lon": 7.0771524 } ] }, { "type": "way", "ref": 235363211, "role": "", "geometry": [ { "lat": 50.7437507, "lon": 7.0771524 }, { "lat": 50.7446592, "lon": 7.0762926 } ] }, { "type": "way", "ref": 48290877, "role": "", "geometry": [ { "lat": 50.7446592, "lon": 7.0762926 }, { "lat": 50.7450803, "lon": 7.0757571 }, { "lat": 50.7453888, "lon": 7.0753312 }, { "lat": 50.7457125, "lon": 7.0748518 }, { "lat": 50.7460370, "lon": 7.0743265 }, { "lat": 50.7462718, "lon": 7.0739425 }, { "lat": 50.7464798, "lon": 7.0735173 }, { "lat": 50.7468359, "lon": 7.0727449 } ] }, { "type": "way", "ref": 210683519, "role": "", "geometry": [ { "lat": 50.7468359, "lon": 7.0727449 }, { "lat": 50.7471006, "lon": 7.0720546 }, { "lat": 50.7473135, "lon": 7.0714640 }, { "lat": 50.7475199, "lon": 7.0708095 }, { "lat": 50.7479418, "lon": 7.0693723 } ] }, { "type": "way", "ref": 42743961, "role": "", "geometry": [ { "lat": 50.7464112, "lon": 7.0734310 }, { "lat": 50.7459053, "lon": 7.0743560 }, { "lat": 50.7457638, "lon": 7.0745740 } ] }, { "type": "way", "ref": 210683522, "role": "", "geometry": [ { "lat": 50.7457638, "lon": 7.0745740 }, { "lat": 50.7456300, "lon": 7.0747409 }, { "lat": 50.7454858, "lon": 7.0749187 }, { "lat": 50.7452550, "lon": 7.0752554 }, { "lat": 50.7450000, "lon": 7.0756385 }, { "lat": 50.7448878, "lon": 7.0758027 }, { "lat": 50.7447522, "lon": 7.0759730 }, { "lat": 50.7445514, "lon": 7.0762032 }, { "lat": 50.7443577, "lon": 7.0764098 }, { "lat": 50.7441185, "lon": 7.0766490 } ] }, { "type": "way", "ref": 48290881, "role": "", "geometry": [ { "lat": 50.7441185, "lon": 7.0766490 }, { "lat": 50.7439033, "lon": 7.0768575 }, { "lat": 50.7437722, "lon": 7.0769631 }, { "lat": 50.7436609, "lon": 7.0770394 } ] }, { "type": "way", "ref": 235363214, "role": "", "geometry": [ { "lat": 50.7436609, "lon": 7.0770394 }, { "lat": 50.7435688, "lon": 7.0771154 }, { "lat": 50.7434662, "lon": 7.0771906 }, { "lat": 50.7434058, "lon": 7.0772230 }, { "lat": 50.7433331, "lon": 7.0772525 }, { "lat": 50.7432822, "lon": 7.0772636 }, { "lat": 50.7432318, "lon": 7.0772601 } ] }, { "type": "way", "ref": 4400137, "role": "", "geometry": [ { "lat": 50.8887155, "lon": 6.9676900 }, { "lat": 50.8876384, "lon": 6.9678150 } ] }, { "type": "way", "ref": 230940375, "role": "", "geometry": [ { "lat": 50.8876384, "lon": 6.9678150 }, { "lat": 50.8870572, "lon": 6.9679058 }, { "lat": 50.8858563, "lon": 6.9680103 } ] }, { "type": "way", "ref": 4400140, "role": "", "geometry": [ { "lat": 50.8797318, "lon": 6.9690108 }, { "lat": 50.8799208, "lon": 6.9689396 }, { "lat": 50.8807058, "lon": 6.9688470 }, { "lat": 50.8824762, "lon": 6.9687068 } ] }, { "type": "way", "ref": 4400142, "role": "", "geometry": [ { "lat": 50.8919691, "lon": 6.9670292 }, { "lat": 50.8918982, "lon": 6.9671419 }, { "lat": 50.8918068, "lon": 6.9672404 }, { "lat": 50.8917186, "lon": 6.9673001 }, { "lat": 50.8916153, "lon": 6.9673480 }, { "lat": 50.8914588, "lon": 6.9673816 } ] }, { "type": "way", "ref": 235824476, "role": "", "geometry": [ { "lat": 50.8914588, "lon": 6.9673816 }, { "lat": 50.8892470, "lon": 6.9676302 }, { "lat": 50.8887155, "lon": 6.9676900 } ] }, { "type": "way", "ref": 4400143, "role": "", "geometry": [ { "lat": 50.8887787, "lon": 6.9681629 }, { "lat": 50.8896224, "lon": 6.9680604 }, { "lat": 50.8897525, "lon": 6.9680446 } ] }, { "type": "way", "ref": 235824475, "role": "", "geometry": [ { "lat": 50.8897525, "lon": 6.9680446 }, { "lat": 50.8906556, "lon": 6.9679349 }, { "lat": 50.8912013, "lon": 6.9678862 } ] }, { "type": "way", "ref": 178797123, "role": "", "geometry": [ { "lat": 50.8912013, "lon": 6.9678862 }, { "lat": 50.8913492, "lon": 6.9678648 } ] }, { "type": "way", "ref": 233553030, "role": "", "geometry": [ { "lat": 50.8913492, "lon": 6.9678648 }, { "lat": 50.8916648, "lon": 6.9677762 }, { "lat": 50.8917895, "lon": 6.9677694 }, { "lat": 50.8919294, "lon": 6.9677947 }, { "lat": 50.8920975, "lon": 6.9678618 } ] }, { "type": "way", "ref": 4829989, "role": "", "geometry": [ { "lat": 50.8105743, "lon": 6.9865001 }, { "lat": 50.8088268, "lon": 6.9896207 } ] }, { "type": "way", "ref": 99834112, "role": "", "geometry": [ { "lat": 50.8088268, "lon": 6.9896207 }, { "lat": 50.8066272, "lon": 6.9935457 }, { "lat": 50.8057165, "lon": 6.9951151 } ] }, { "type": "way", "ref": 133081219, "role": "", "geometry": [ { "lat": 50.8057165, "lon": 6.9951151 }, { "lat": 50.8050332, "lon": 6.9962100 }, { "lat": 50.8043133, "lon": 6.9972614 } ] }, { "type": "way", "ref": 234434905, "role": "", "geometry": [ { "lat": 50.8043133, "lon": 6.9972614 }, { "lat": 50.8038004, "lon": 6.9979304 }, { "lat": 50.8032120, "lon": 6.9986363 }, { "lat": 50.8029818, "lon": 6.9989181 } ] }, { "type": "way", "ref": 20661567, "role": "", "geometry": [ { "lat": 50.8849681, "lon": 6.9681126 }, { "lat": 50.8839667, "lon": 6.9682524 }, { "lat": 50.8829770, "lon": 6.9684059 } ] }, { "type": "way", "ref": 230941900, "role": "", "geometry": [ { "lat": 50.8829770, "lon": 6.9684059 }, { "lat": 50.8826286, "lon": 6.9684595 } ] }, { "type": "way", "ref": 20661568, "role": "", "geometry": [ { "lat": 50.8850872, "lon": 6.9685052 }, { "lat": 50.8859127, "lon": 6.9684079 } ] }, { "type": "way", "ref": 20661572, "role": "", "geometry": [ { "lat": 50.8859127, "lon": 6.9684079 }, { "lat": 50.8872823, "lon": 6.9682592 }, { "lat": 50.8876807, "lon": 6.9682539 } ] }, { "type": "way", "ref": 230940374, "role": "", "geometry": [ { "lat": 50.8876807, "lon": 6.9682539 }, { "lat": 50.8887787, "lon": 6.9681629 } ] }, { "type": "way", "ref": 20661573, "role": "", "geometry": [ { "lat": 50.8858563, "lon": 6.9680103 }, { "lat": 50.8849681, "lon": 6.9681126 } ] }, { "type": "way", "ref": 20662817, "role": "", "geometry": [ { "lat": 50.8823655, "lon": 6.9684998 }, { "lat": 50.8806620, "lon": 6.9686453 } ] }, { "type": "way", "ref": 230941903, "role": "", "geometry": [ { "lat": 50.8806620, "lon": 6.9686453 }, { "lat": 50.8793943, "lon": 6.9687847 } ] }, { "type": "way", "ref": 20662819, "role": "", "geometry": [ { "lat": 50.8824762, "lon": 6.9687068 }, { "lat": 50.8827522, "lon": 6.9686901 } ] }, { "type": "way", "ref": 20662824, "role": "", "geometry": [ { "lat": 50.8827522, "lon": 6.9686901 }, { "lat": 50.8839133, "lon": 6.9686122 }, { "lat": 50.8850872, "lon": 6.9685052 } ] }, { "type": "way", "ref": 20662827, "role": "", "geometry": [ { "lat": 50.8826286, "lon": 6.9684595 }, { "lat": 50.8823655, "lon": 6.9684998 } ] }, { "type": "way", "ref": 27492515, "role": "", "geometry": [ { "lat": 50.8029818, "lon": 6.9989181 }, { "lat": 50.8026288, "lon": 6.9992932 } ] }, { "type": "way", "ref": 129125122, "role": "", "geometry": [ { "lat": 50.8093979, "lon": 6.9890430 }, { "lat": 50.8104598, "lon": 6.9871803 } ] }, { "type": "way", "ref": 234434901, "role": "", "geometry": [ { "lat": 50.8063753, "lon": 6.9944172 }, { "lat": 50.8093979, "lon": 6.9890430 } ] }, { "type": "way", "ref": 234434904, "role": "", "geometry": [ { "lat": 50.8053262, "lon": 6.9961817 }, { "lat": 50.8058108, "lon": 6.9953914 }, { "lat": 50.8063753, "lon": 6.9944172 } ] }, { "type": "way", "ref": 27492542, "role": "", "geometry": [ { "lat": 50.8029899, "lon": 6.9991939 }, { "lat": 50.8032828, "lon": 6.9988807 }, { "lat": 50.8038702, "lon": 6.9982129 }, { "lat": 50.8044350, "lon": 6.9974695 }, { "lat": 50.8053262, "lon": 6.9961817 } ] }, { "type": "way", "ref": 27492543, "role": "", "geometry": [ { "lat": 50.8026483, "lon": 6.9995590 }, { "lat": 50.8029899, "lon": 6.9991939 } ] }, { "type": "way", "ref": 29233646, "role": "", "geometry": [ { "lat": 50.8793943, "lon": 6.9687847 }, { "lat": 50.8716935, "lon": 6.9696241 }, { "lat": 50.8701666, "lon": 6.9697243 }, { "lat": 50.8688585, "lon": 6.9697057 }, { "lat": 50.8652424, "lon": 6.9693872 } ] }, { "type": "way", "ref": 235820561, "role": "", "geometry": [ { "lat": 50.8652424, "lon": 6.9693872 }, { "lat": 50.8636340, "lon": 6.9692339 } ] }, { "type": "way", "ref": 29233647, "role": "", "geometry": [ { "lat": 50.8636340, "lon": 6.9692339 }, { "lat": 50.8608791, "lon": 6.9689787 } ] }, { "type": "way", "ref": 235820559, "role": "", "geometry": [ { "lat": 50.8608791, "lon": 6.9689787 }, { "lat": 50.8590168, "lon": 6.9688055 } ] }, { "type": "way", "ref": 235820562, "role": "", "geometry": [ { "lat": 50.8590168, "lon": 6.9688055 }, { "lat": 50.8523854, "lon": 6.9681888 } ] }, { "type": "way", "ref": 29233648, "role": "", "geometry": [ { "lat": 50.8522171, "lon": 6.9684787 }, { "lat": 50.8590359, "lon": 6.9691023 } ] }, { "type": "way", "ref": 29382960, "role": "", "geometry": [ { "lat": 50.8391695, "lon": 6.9667285 }, { "lat": 50.8411491, "lon": 6.9672118 }, { "lat": 50.8425706, "lon": 6.9674985 } ] }, { "type": "way", "ref": 271008229, "role": "", "geometry": [ { "lat": 50.8425706, "lon": 6.9674985 }, { "lat": 50.8443277, "lon": 6.9677563 } ] }, { "type": "way", "ref": 271008238, "role": "", "geometry": [ { "lat": 50.8443277, "lon": 6.9677563 }, { "lat": 50.8453254, "lon": 6.9678465 }, { "lat": 50.8468114, "lon": 6.9679862 } ] }, { "type": "way", "ref": 271008230, "role": "", "geometry": [ { "lat": 50.8468114, "lon": 6.9679862 }, { "lat": 50.8491169, "lon": 6.9681907 } ] }, { "type": "way", "ref": 271008226, "role": "", "geometry": [ { "lat": 50.8491169, "lon": 6.9681907 }, { "lat": 50.8518181, "lon": 6.9684403 } ] }, { "type": "way", "ref": 40033062, "role": "", "geometry": [ { "lat": 50.8391857, "lon": 6.9664246 }, { "lat": 50.8386690, "lon": 6.9662911 } ] }, { "type": "way", "ref": 40033063, "role": "", "geometry": [ { "lat": 50.8386690, "lon": 6.9662911 }, { "lat": 50.8314332, "lon": 6.9644546 } ] }, { "type": "way", "ref": 29384561, "role": "", "geometry": [ { "lat": 50.8523854, "lon": 6.9681888 }, { "lat": 50.8519590, "lon": 6.9681595 } ] }, { "type": "way", "ref": 29384563, "role": "", "geometry": [ { "lat": 50.8519590, "lon": 6.9681595 }, { "lat": 50.8506534, "lon": 6.9680320 } ] }, { "type": "way", "ref": 271008224, "role": "", "geometry": [ { "lat": 50.8506534, "lon": 6.9680320 }, { "lat": 50.8490308, "lon": 6.9678717 } ] }, { "type": "way", "ref": 271008227, "role": "", "geometry": [ { "lat": 50.8490308, "lon": 6.9678717 }, { "lat": 50.8478121, "lon": 6.9677589 } ] }, { "type": "way", "ref": 271008237, "role": "", "geometry": [ { "lat": 50.8478121, "lon": 6.9677589 }, { "lat": 50.8459552, "lon": 6.9676249 }, { "lat": 50.8451822, "lon": 6.9675256 } ] }, { "type": "way", "ref": 271008232, "role": "", "geometry": [ { "lat": 50.8451822, "lon": 6.9675256 }, { "lat": 50.8433946, "lon": 6.9673373 } ] }, { "type": "way", "ref": 271008239, "role": "", "geometry": [ { "lat": 50.8433946, "lon": 6.9673373 }, { "lat": 50.8424071, "lon": 6.9671724 }, { "lat": 50.8411984, "lon": 6.9669289 }, { "lat": 50.8391857, "lon": 6.9664246 } ] }, { "type": "way", "ref": 29384564, "role": "", "geometry": [ { "lat": 50.8518181, "lon": 6.9684403 }, { "lat": 50.8522171, "lon": 6.9684787 } ] }, { "type": "way", "ref": 31282638, "role": "", "geometry": [ { "lat": 50.7547305, "lon": 7.0468957 }, { "lat": 50.7550333, "lon": 7.0462257 } ] }, { "type": "way", "ref": 31282787, "role": "", "geometry": [ { "lat": 50.7548175, "lon": 7.0462659 }, { "lat": 50.7545192, "lon": 7.0469416 } ] }, { "type": "way", "ref": 383262762, "role": "", "geometry": [ { "lat": 50.7545192, "lon": 7.0469416 }, { "lat": 50.7522859, "lon": 7.0519784 }, { "lat": 50.7519030, "lon": 7.0528750 } ] }, { "type": "way", "ref": 31304443, "role": "", "geometry": [ { "lat": 50.7519030, "lon": 7.0528750 }, { "lat": 50.7514373, "lon": 7.0540731 }, { "lat": 50.7512408, "lon": 7.0546346 }, { "lat": 50.7511231, "lon": 7.0549962 }, { "lat": 50.7508172, "lon": 7.0560135 } ] }, { "type": "way", "ref": 128541594, "role": "", "geometry": [ { "lat": 50.7508172, "lon": 7.0560135 }, { "lat": 50.7504938, "lon": 7.0572440 } ] }, { "type": "way", "ref": 31304503, "role": "", "geometry": [ { "lat": 50.7509429, "lon": 7.0561605 }, { "lat": 50.7512483, "lon": 7.0551357 }, { "lat": 50.7513759, "lon": 7.0547500 }, { "lat": 50.7515670, "lon": 7.0542197 }, { "lat": 50.7520213, "lon": 7.0530348 }, { "lat": 50.7524214, "lon": 7.0520935 }, { "lat": 50.7547305, "lon": 7.0468957 } ] }, { "type": "way", "ref": 31363881, "role": "", "geometry": [ { "lat": 50.8026288, "lon": 6.9992932 }, { "lat": 50.8018617, "lon": 7.0000625 }, { "lat": 50.8010270, "lon": 7.0007950 }, { "lat": 50.8001164, "lon": 7.0015291 }, { "lat": 50.7928343, "lon": 7.0072406 }, { "lat": 50.7832350, "lon": 7.0147268 }, { "lat": 50.7826087, "lon": 7.0151803 } ] }, { "type": "way", "ref": 31363891, "role": "", "geometry": [ { "lat": 50.7826087, "lon": 7.0151803 }, { "lat": 50.7823221, "lon": 7.0153822 } ] }, { "type": "way", "ref": 31363892, "role": "", "geometry": [ { "lat": 50.7823221, "lon": 7.0153822 }, { "lat": 50.7802850, "lon": 7.0170023 }, { "lat": 50.7782200, "lon": 7.0186241 } ] }, { "type": "way", "ref": 31363898, "role": "", "geometry": [ { "lat": 50.7826777, "lon": 7.0153975 }, { "lat": 50.7833048, "lon": 7.0149295 }, { "lat": 50.8001641, "lon": 7.0017836 }, { "lat": 50.8010947, "lon": 7.0010142 }, { "lat": 50.8019538, "lon": 7.0002540 }, { "lat": 50.8026483, "lon": 6.9995590 } ] }, { "type": "way", "ref": 31363910, "role": "", "geometry": [ { "lat": 50.7823930, "lon": 7.0156008 }, { "lat": 50.7826777, "lon": 7.0153975 } ] }, { "type": "way", "ref": 31364152, "role": "", "geometry": [ { "lat": 50.7782200, "lon": 7.0186241 }, { "lat": 50.7779774, "lon": 7.0188037 } ] }, { "type": "way", "ref": 31364158, "role": "", "geometry": [ { "lat": 50.7783056, "lon": 7.0188240 }, { "lat": 50.7788577, "lon": 7.0183860 }, { "lat": 50.7803473, "lon": 7.0172040 }, { "lat": 50.7816582, "lon": 7.0161766 }, { "lat": 50.7823930, "lon": 7.0156008 } ] }, { "type": "way", "ref": 31364178, "role": "", "geometry": [ { "lat": 50.7780676, "lon": 7.0190054 }, { "lat": 50.7783056, "lon": 7.0188240 } ] }, { "type": "way", "ref": 31364384, "role": "", "geometry": [ { "lat": 50.7749036, "lon": 7.0214625 }, { "lat": 50.7780676, "lon": 7.0190054 } ] }, { "type": "way", "ref": 31364387, "role": "", "geometry": [ { "lat": 50.7744886, "lon": 7.0214841 }, { "lat": 50.7712930, "lon": 7.0240315 }, { "lat": 50.7695809, "lon": 7.0254447 }, { "lat": 50.7686243, "lon": 7.0263151 } ] }, { "type": "way", "ref": 31364484, "role": "", "geometry": [ { "lat": 50.7748248, "lon": 7.0212347 }, { "lat": 50.7744886, "lon": 7.0214841 } ] }, { "type": "way", "ref": 31364512, "role": "", "geometry": [ { "lat": 50.7745735, "lon": 7.0217089 }, { "lat": 50.7749036, "lon": 7.0214625 } ] }, { "type": "way", "ref": 31364656, "role": "", "geometry": [ { "lat": 50.7686546, "lon": 7.0266216 }, { "lat": 50.7696586, "lon": 7.0256891 }, { "lat": 50.7713905, "lon": 7.0242565 }, { "lat": 50.7745735, "lon": 7.0217089 } ] }, { "type": "way", "ref": 31364667, "role": "", "geometry": [ { "lat": 50.7686243, "lon": 7.0263151 }, { "lat": 50.7676165, "lon": 7.0273126 }, { "lat": 50.7665957, "lon": 7.0283332 }, { "lat": 50.7653333, "lon": 7.0297134 } ] }, { "type": "way", "ref": 271008234, "role": "", "geometry": [ { "lat": 50.7653333, "lon": 7.0297134 }, { "lat": 50.7643799, "lon": 7.0308081 } ] }, { "type": "way", "ref": 31364888, "role": "", "geometry": [ { "lat": 50.7635269, "lon": 7.0321873 }, { "lat": 50.7641966, "lon": 7.0313729 } ] }, { "type": "way", "ref": 122158730, "role": "", "geometry": [ { "lat": 50.7641966, "lon": 7.0313729 }, { "lat": 50.7644716, "lon": 7.0310241 } ] }, { "type": "way", "ref": 31364985, "role": "", "geometry": [ { "lat": 50.7644716, "lon": 7.0310241 }, { "lat": 50.7648596, "lon": 7.0305814 } ] }, { "type": "way", "ref": 271008235, "role": "", "geometry": [ { "lat": 50.7648596, "lon": 7.0305814 }, { "lat": 50.7657812, "lon": 7.0295145 }, { "lat": 50.7666465, "lon": 7.0285903 } ] }, { "type": "way", "ref": 271008231, "role": "", "geometry": [ { "lat": 50.7666465, "lon": 7.0285903 }, { "lat": 50.7679887, "lon": 7.0272481 } ] }, { "type": "way", "ref": 271008233, "role": "", "geometry": [ { "lat": 50.7679887, "lon": 7.0272481 }, { "lat": 50.7686546, "lon": 7.0266216 } ] }, { "type": "way", "ref": 31365377, "role": "", "geometry": [ { "lat": 50.7643799, "lon": 7.0308081 }, { "lat": 50.7640807, "lon": 7.0311662 } ] }, { "type": "way", "ref": 31365425, "role": "", "geometry": [ { "lat": 50.7640807, "lon": 7.0311662 }, { "lat": 50.7638566, "lon": 7.0314272 } ] }, { "type": "way", "ref": 271008236, "role": "", "geometry": [ { "lat": 50.7638566, "lon": 7.0314272 }, { "lat": 50.7628914, "lon": 7.0326760 }, { "lat": 50.7621053, "lon": 7.0336961 } ] }, { "type": "way", "ref": 36447898, "role": "", "geometry": [ { "lat": 50.7621053, "lon": 7.0336961 }, { "lat": 50.7613433, "lon": 7.0347526 } ] }, { "type": "way", "ref": 271008228, "role": "", "geometry": [ { "lat": 50.7613433, "lon": 7.0347526 }, { "lat": 50.7608295, "lon": 7.0354890 } ] }, { "type": "way", "ref": 31366812, "role": "", "geometry": [ { "lat": 50.7588227, "lon": 7.0386254 }, { "lat": 50.7583011, "lon": 7.0394929 }, { "lat": 50.7576749, "lon": 7.0405773 }, { "lat": 50.7569096, "lon": 7.0419812 }, { "lat": 50.7558745, "lon": 7.0439976 }, { "lat": 50.7548175, "lon": 7.0462659 } ] }, { "type": "way", "ref": 31366880, "role": "", "geometry": [ { "lat": 50.7550333, "lon": 7.0462257 }, { "lat": 50.7559939, "lon": 7.0442408 }, { "lat": 50.7570656, "lon": 7.0421620 }, { "lat": 50.7578037, "lon": 7.0408023 }, { "lat": 50.7584541, "lon": 7.0396561 }, { "lat": 50.7589669, "lon": 7.0387984 } ] }, { "type": "way", "ref": 31367017, "role": "", "geometry": [ { "lat": 50.7609333, "lon": 7.0356976 }, { "lat": 50.7619690, "lon": 7.0342371 }, { "lat": 50.7630051, "lon": 7.0328461 }, { "lat": 50.7635269, "lon": 7.0321873 } ] }, { "type": "way", "ref": 31367443, "role": "", "geometry": [ { "lat": 50.7607331, "lon": 7.0359794 }, { "lat": 50.7609333, "lon": 7.0356976 } ] }, { "type": "way", "ref": 31367449, "role": "", "geometry": [ { "lat": 50.7589669, "lon": 7.0387984 }, { "lat": 50.7602933, "lon": 7.0366481 }, { "lat": 50.7607331, "lon": 7.0359794 } ] }, { "type": "way", "ref": 31367526, "role": "", "geometry": [ { "lat": 50.7606164, "lon": 7.0358121 }, { "lat": 50.7601681, "lon": 7.0365126 }, { "lat": 50.7588227, "lon": 7.0386254 } ] }, { "type": "way", "ref": 31367534, "role": "", "geometry": [ { "lat": 50.7608295, "lon": 7.0354890 }, { "lat": 50.7606164, "lon": 7.0358121 } ] }, { "type": "way", "ref": 31369852, "role": "", "geometry": [ { "lat": 50.7779774, "lon": 7.0188037 }, { "lat": 50.7748248, "lon": 7.0212347 } ] }, { "type": "way", "ref": 449397558, "role": "", "geometry": [ { "lat": 50.7479418, "lon": 7.0693723 }, { "lat": 50.7494783, "lon": 7.0624630 } ] }, { "type": "way", "ref": 31797389, "role": "", "geometry": [ { "lat": 50.7494783, "lon": 7.0624630 }, { "lat": 50.7502727, "lon": 7.0588905 }, { "lat": 50.7506441, "lon": 7.0572942 }, { "lat": 50.7509429, "lon": 7.0561605 } ] }, { "type": "way", "ref": 31798039, "role": "", "geometry": [ { "lat": 50.7504938, "lon": 7.0572440 }, { "lat": 50.7501306, "lon": 7.0588140 } ] }, { "type": "way", "ref": 235363212, "role": "", "geometry": [ { "lat": 50.7501306, "lon": 7.0588140 }, { "lat": 50.7492636, "lon": 7.0626737 }, { "lat": 50.7489407, "lon": 7.0641605 } ] }, { "type": "way", "ref": 156492546, "role": "", "geometry": [ { "lat": 50.7489407, "lon": 7.0641605 }, { "lat": 50.7488307, "lon": 7.0647205 }, { "lat": 50.7483739, "lon": 7.0668216 } ] }, { "type": "way", "ref": 156492545, "role": "", "geometry": [ { "lat": 50.7483739, "lon": 7.0668216 }, { "lat": 50.7483009, "lon": 7.0672440 }, { "lat": 50.7478400, "lon": 7.0692844 } ] }, { "type": "way", "ref": 130749935, "role": "", "geometry": [ { "lat": 50.7478400, "lon": 7.0692844 }, { "lat": 50.7477294, "lon": 7.0697394 }, { "lat": 50.7476187, "lon": 7.0701855 }, { "lat": 50.7474997, "lon": 7.0706232 }, { "lat": 50.7473468, "lon": 7.0711189 }, { "lat": 50.7472087, "lon": 7.0715434 }, { "lat": 50.7470472, "lon": 7.0719838 }, { "lat": 50.7469114, "lon": 7.0723163 }, { "lat": 50.7467733, "lon": 7.0726489 }, { "lat": 50.7465937, "lon": 7.0730580 }, { "lat": 50.7464112, "lon": 7.0734310 } ] }, { "type": "way", "ref": 32472877, "role": "", "geometry": [ { "lat": 50.8246828, "lon": 6.9651077 }, { "lat": 50.8253375, "lon": 6.9647718 }, { "lat": 50.8260000, "lon": 6.9645354 }, { "lat": 50.8266134, "lon": 6.9643649 }, { "lat": 50.8272671, "lon": 6.9642646 }, { "lat": 50.8278017, "lon": 6.9642349 } ] }, { "type": "way", "ref": 31798988, "role": "", "geometry": [ { "lat": 50.8278017, "lon": 6.9642349 }, { "lat": 50.8284805, "lon": 6.9642342 }, { "lat": 50.8294617, "lon": 6.9643395 }, { "lat": 50.8302437, "lon": 6.9644810 }, { "lat": 50.8309474, "lon": 6.9646345 } ] }, { "type": "way", "ref": 31798989, "role": "", "geometry": [ { "lat": 50.8590359, "lon": 6.9691023 }, { "lat": 50.8634113, "lon": 6.9695191 } ] }, { "type": "way", "ref": 235820560, "role": "", "geometry": [ { "lat": 50.8634113, "lon": 6.9695191 }, { "lat": 50.8656224, "lon": 6.9697185 } ] }, { "type": "way", "ref": 235820563, "role": "", "geometry": [ { "lat": 50.8656224, "lon": 6.9697185 }, { "lat": 50.8679633, "lon": 6.9699314 } ] }, { "type": "way", "ref": 235820564, "role": "", "geometry": [ { "lat": 50.8679633, "lon": 6.9699314 }, { "lat": 50.8691580, "lon": 6.9700171 }, { "lat": 50.8699302, "lon": 6.9700221 } ] }, { "type": "way", "ref": 235820570, "role": "", "geometry": [ { "lat": 50.8699302, "lon": 6.9700221 }, { "lat": 50.8717399, "lon": 6.9699121 }, { "lat": 50.8746263, "lon": 6.9695939 } ] }, { "type": "way", "ref": 32472855, "role": "", "geometry": [ { "lat": 50.8246253, "lon": 6.9648384 }, { "lat": 50.8242516, "lon": 6.9650453 } ] }, { "type": "way", "ref": 32472856, "role": "", "geometry": [ { "lat": 50.8242516, "lon": 6.9650453 }, { "lat": 50.8237235, "lon": 6.9653841 }, { "lat": 50.8232034, "lon": 6.9657948 }, { "lat": 50.8224317, "lon": 6.9665263 }, { "lat": 50.8216642, "lon": 6.9673886 }, { "lat": 50.8209037, "lon": 6.9684049 }, { "lat": 50.8201541, "lon": 6.9695500 }, { "lat": 50.8192181, "lon": 6.9711445 }, { "lat": 50.8138575, "lon": 6.9806731 } ] }, { "type": "way", "ref": 37881520, "role": "", "geometry": [ { "lat": 50.8138575, "lon": 6.9806731 }, { "lat": 50.8135770, "lon": 6.9811721 } ] }, { "type": "way", "ref": 37881519, "role": "", "geometry": [ { "lat": 50.8135770, "lon": 6.9811721 }, { "lat": 50.8113547, "lon": 6.9851361 } ] }, { "type": "way", "ref": 234434902, "role": "", "geometry": [ { "lat": 50.8113547, "lon": 6.9851361 }, { "lat": 50.8105743, "lon": 6.9865001 } ] }, { "type": "way", "ref": 32472875, "role": "", "geometry": [ { "lat": 50.8243279, "lon": 6.9653077 }, { "lat": 50.8246828, "lon": 6.9651077 } ] }, { "type": "way", "ref": 32473071, "role": "", "geometry": [ { "lat": 50.8309464, "lon": 6.9643368 }, { "lat": 50.8302815, "lon": 6.9641912 } ] }, { "type": "way", "ref": 128522486, "role": "", "geometry": [ { "lat": 50.8302815, "lon": 6.9641912 }, { "lat": 50.8294728, "lon": 6.9640448 }, { "lat": 50.8284964, "lon": 6.9639463 }, { "lat": 50.8277970, "lon": 6.9639432 } ] }, { "type": "way", "ref": 36447896, "role": "", "geometry": [ { "lat": 50.8277970, "lon": 6.9639432 }, { "lat": 50.8272631, "lon": 6.9639682 }, { "lat": 50.8265661, "lon": 6.9640827 }, { "lat": 50.8259717, "lon": 6.9642405 }, { "lat": 50.8252714, "lon": 6.9645096 }, { "lat": 50.8246253, "lon": 6.9648384 } ] }, { "type": "way", "ref": 32473075, "role": "", "geometry": [ { "lat": 50.8314332, "lon": 6.9644546 }, { "lat": 50.8309464, "lon": 6.9643368 } ] }, { "type": "way", "ref": 32473086, "role": "", "geometry": [ { "lat": 50.8309474, "lon": 6.9646345 }, { "lat": 50.8314534, "lon": 6.9647679 } ] }, { "type": "way", "ref": 32473087, "role": "", "geometry": [ { "lat": 50.8314534, "lon": 6.9647679 }, { "lat": 50.8386440, "lon": 6.9665955 } ] }, { "type": "way", "ref": 40033064, "role": "", "geometry": [ { "lat": 50.8386440, "lon": 6.9665955 }, { "lat": 50.8391695, "lon": 6.9667285 } ] }, { "type": "way", "ref": 189189059, "role": "", "geometry": [ { "lat": 50.8746263, "lon": 6.9695939 }, { "lat": 50.8760907, "lon": 6.9694358 } ] }, { "type": "way", "ref": 271008225, "role": "", "geometry": [ { "lat": 50.8760907, "lon": 6.9694358 }, { "lat": 50.8775484, "lon": 6.9692784 } ] }, { "type": "way", "ref": 41550921, "role": "", "geometry": [ { "lat": 50.8775484, "lon": 6.9692784 }, { "lat": 50.8797318, "lon": 6.9690108 } ] } ], "tags": { "TMC:cid_58:tabcd_1:Class": "Road", "TMC:cid_58:tabcd_1:LCLversion": "8.00", "TMC:cid_58:tabcd_1:LocationCode": "7142", "name": "Bundesautobahn 555", "network": "BAB", "operator": "Bundesrepublik Deutschland", "ref": "A 555", "route": "road", "type": "route", "wikipedia": "de:Bundesautobahn 555" } } ] } python-overpy-0.7/tests/json/remark-runtime-error-01.json000066400000000000000000000006241453334100400235370ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2017-03-17T22:05:02Z", "timestamp_areas_base": "2017-03-17T18:38:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ ], "remark": "runtime error: Query timed out in \"query\" at line 4 after 2 seconds." } python-overpy-0.7/tests/json/remark-runtime-remark-01.json000066400000000000000000000005421453334100400236660ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2017-03-17T22:05:02Z", "timestamp_areas_base": "2017-03-17T18:38:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ ], "remark": "runtime remark: Test" } python-overpy-0.7/tests/json/remark-unknown-01.json000066400000000000000000000005311453334100400224210ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2017-03-17T22:05:02Z", "timestamp_areas_base": "2017-03-17T18:38:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ ], "remark": "Test remark" } python-overpy-0.7/tests/json/result-expand-01.json000066400000000000000000000012111453334100400222320ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 3233854233, "lat": 50.7494187, "lon": 7.1758731 }, { "type": "node", "id": 3233854234, "lat": 50.7494287, "lon": 7.1758731 }, { "type": "way", "id": 317146077, "nodes": [ 3233854233, 3233854234 ], "tags": { "building": "yes" } } ] }python-overpy-0.7/tests/json/result-expand-02.json000066400000000000000000000027511453334100400222450ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "area", "id": 3605945176 }, { "type": "node", "id": 3233854233, "lat": 50.7494187, "lon": 7.1758731 }, { "type": "node", "id": 3233854235, "lat": 50.7494287, "lon": 7.1758731 }, { "type": "way", "id": 317146078, "nodes": [ 3233854233, 3233854235 ], "tags": { "building": "yes" } }, { "type": "relation", "id": 2046898, "timestamp": "2014-12-15T13:13:11Z", "version": 12, "changeset": 17433822, "user": "Username", "uid": 12345, "members": [ { "type": "node", "ref": 3233854233, "role": "platform" }, { "type": "node", "ref": 3233854234, "role": "stop" }, { "type": "node", "ref": 3233854235, "role": "platform" }, { "type": "way", "ref": 317146078, "role": "" } ], "tags": { "from": "Here", "name": "Test relation", "ref": "609", "route": "bus", "to": "There", "type": "route" } } ] }python-overpy-0.7/tests/json/result-way-01.json000066400000000000000000000006631453334100400215650ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "way", "id": 317146077, "nodes": [ 3233854233, 3233854234 ], "tags": { "building": "yes" } } ] }python-overpy-0.7/tests/json/result-way-02.json000066400000000000000000000010361453334100400215610ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 3233854233, "lat": 50.7494187, "lon": 7.1758731 }, { "type": "way", "id": 317146077, "nodes": [ 3233854233, 3233854234 ], "tags": { "building": "yes" } } ] }python-overpy-0.7/tests/json/result-way-03.json000066400000000000000000000012111453334100400215550ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 3233854233, "lat": 50.7494187, "lon": 7.1758731 }, { "type": "node", "id": 3233854234, "lat": 50.7494287, "lon": 7.1758731 }, { "type": "way", "id": 317146077, "nodes": [ 3233854233, 3233854234 ], "tags": { "building": "yes" } } ] }python-overpy-0.7/tests/json/way-01.json000066400000000000000000000013711453334100400202460ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:33:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "way", "id": 317146077, "nodes": [ 3233854241, 3233854238, 3233854233, 3233854234, 3233854236, 3233854237, 3233854241 ], "tags": { "building": "yes" } }, { "type": "way", "id": 317146078, "timestamp": "2014-12-14T07:27:21Z", "version": 1, "changeset": 23456789, "user": "TestUser", "uid": 345678, "nodes": [ 3233854241, 3233854238, 3233854233, 3233854234, 3233854236, 3233854237, 3233854241 ] } ] }python-overpy-0.7/tests/json/way-02.json000066400000000000000000000017131453334100400202470ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2014-12-14T13:34:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 3233854233, "lat": 50.7494187, "lon": 7.1758731 }, { "type": "node", "id": 3233854234, "lat": 50.7494236, "lon": 7.1757664 }, { "type": "node", "id": 3233854236, "lat": 50.7494909, "lon": 7.1757741 }, { "type": "node", "id": 3233854237, "lat": 50.7494985, "lon": 7.1756064 }, { "type": "node", "id": 3233854238, "lat": 50.7495391, "lon": 7.1758868 }, { "type": "node", "id": 3233854241, "lat": 50.7495516, "lon": 7.1756125 }, { "type": "way", "id": 317146077, "nodes": [ 3233854241, 3233854238, 3233854233, 3233854234, 3233854236, 3233854237, 3233854241 ], "tags": { "building": "yes" } } ] }python-overpy-0.7/tests/json/way-03.json000066400000000000000000000026611453334100400202530ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2016-11-22T22:33:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "node", "id": 2343425523, "lat": 41.8954452, "lon": 12.5032169, "timestamp": "2013-06-13T15:34:01Z", "version": 1, "changeset": 16539126, "user": "Giardia", "uid": 113909 }, { "type": "node", "id": 2343425525, "lat": 41.8954752, "lon": 12.5031604, "timestamp": "2013-06-13T15:34:01Z", "version": 1, "changeset": 16539126, "user": "Giardia", "uid": 113909 }, { "type": "node", "id": 2343425526, "lat": 41.8955244, "lon": 12.5032926, "timestamp": "2013-06-13T15:34:01Z", "version": 1, "changeset": 16539126, "user": "Giardia", "uid": 113909 }, { "type": "node", "id": 2343425528, "lat": 41.8955543, "lon": 12.5032362, "timestamp": "2013-06-13T15:34:01Z", "version": 1, "changeset": 16539126, "user": "Giardia", "uid": 113909 }, { "type": "way", "id": 225576797, "timestamp": "2013-06-13T15:34:01Z", "version": 1, "changeset": 16539126, "user": "Giardia", "uid": 113909, "center": { "lat": 41.8954998, "lon": 12.5032265 }, "nodes": [ 2343425525, 2343425528, 2343425526, 2343425523, 2343425525 ], "tags": { "building": "kiosk", "shop": "florist" } } ] } python-overpy-0.7/tests/json/way-04.json000066400000000000000000000007421453334100400202520ustar00rootroot00000000000000{ "version": 0.6, "generator": "Overpass API", "osm3s": { "timestamp_osm_base": "2016-11-22T23:25:02Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ { "type": "way", "id": 225576797, "center": {}, "nodes": [ 2343425525, 2343425528, 2343425526, 2343425523, 2343425525 ], "tags": { "building": "kiosk", "shop": "florist" } } ] }python-overpy-0.7/tests/response/000077500000000000000000000000001453334100400172205ustar00rootroot00000000000000python-overpy-0.7/tests/response/bad-request-encoding.html000066400000000000000000000011631453334100400241070ustar00rootroot00000000000000 OSM3S Response

The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.

Error: line 2: parse error: ';' expected - 'out' found.

python-overpy-0.7/tests/response/bad-request.html000066400000000000000000000011141453334100400223170ustar00rootroot00000000000000 OSM3S Response

The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.

Error: line 2: parse error: ';' expected - 'out' found.

python-overpy-0.7/tests/test_exception.py000066400000000000000000000042271453334100400207760ustar00rootroot00000000000000import overpy class TestExceptions: def test_element_data_wrong_type(self): e = overpy.exception.ElementDataWrongType("from1") assert e.type_expected == "from1" assert e.type_provided is None assert isinstance(str(e), str) e = overpy.exception.ElementDataWrongType("from2", "to2") assert e.type_expected == "from2" assert e.type_provided == "to2" assert isinstance(str(e), str) def test_overpass_bad_request(self): e = overpy.exception.OverpassBadRequest("query") assert e.query == "query" assert isinstance(e.msgs, list) assert len(e.msgs) == 0 assert str(e) == "" e = overpy.exception.OverpassBadRequest("test\nquery\n123", ["abc", 1]) assert e.query == "test\nquery\n123" assert isinstance(e.msgs, list) assert len(e.msgs) == 2 assert str(e) == "abc\n1" def test_overpass_unknown_content_type(self): e = overpy.exception.OverpassUnknownContentType(None) assert e.content_type is None assert str(e).startswith("No content") e = overpy.exception.OverpassUnknownContentType("content") assert e.content_type == "content" assert str(e).startswith("Unknown content") assert str(e).endswith("content") def test_overpass_unknown_http_status_code(self): e = overpy.exception.OverpassUnknownHTTPStatusCode(123) assert e.code == 123 assert str(e).endswith("123") def test_overpass_error(self): exceptions = [ overpy.exception.OverpassError, overpy.exception.OverpassRuntimeError, overpy.exception.OverpassRuntimeRemark, overpy.exception.OverpassUnknownError ] for cls in exceptions: e = cls(msg="Test message") assert e.msg == "Test message" assert str(e) == "Test message" for cls in exceptions: e = cls() assert e.msg is None assert str(e) == "No error message provided" for cls in exceptions: e = cls(msg=123) assert e.msg == 123 assert str(e) == "123" python-overpy-0.7/tests/test_json.py000066400000000000000000000067621453334100400177570ustar00rootroot00000000000000import pytest import overpy from tests import read_file from tests.base_class import BaseTestAreas, BaseTestNodes, BaseTestRelation, BaseTestWay class TestAreas(BaseTestAreas): def test_area01(self): api = overpy.Overpass() result = api.parse_json(read_file("json/area-01.json")) self._test_area01(result) class TestNodes(BaseTestNodes): def test_node01(self): api = overpy.Overpass() result = api.parse_json(read_file("json/node-01.json")) self._test_node01(result) class TestRelation(BaseTestRelation): def test_relation01(self): api = overpy.Overpass() result = api.parse_json(read_file("json/relation-01.json")) self._test_relation01(result) def test_relation02(self): api = overpy.Overpass() result = api.parse_json(read_file("json/relation-02.json")) self._test_relation02(result) def test_relation03(self): api = overpy.Overpass() result = api.parse_json(read_file("json/relation-03.json")) self._test_relation03(result) def test_relation04(self): api = overpy.Overpass() result = api.parse_json(read_file("json/relation-04.json")) self._test_relation04(result) class TestWay(BaseTestWay): def test_way01(self): api = overpy.Overpass() result = api.parse_json(read_file("json/way-01.json")) self._test_way01(result) def test_way02(self): api = overpy.Overpass() result = api.parse_json(read_file("json/way-02.json")) self._test_way02(result) def test_way03(self): api = overpy.Overpass() result = api.parse_json(read_file("json/way-03.json")) self._test_way03(result) def test_way04(self): api = overpy.Overpass() with pytest.raises(ValueError): api.parse_json(read_file("json/way-04.json")) class TestDataError: def test_element_wrong_type(self): with pytest.raises(overpy.exception.ElementDataWrongType): overpy.Node.from_json( { "type": "foo" } ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.Relation.from_json( { "type": "foo" } ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.RelationNode.from_json( { "type": "foo" } ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.RelationWay.from_json( { "type": "foo" } ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.Way.from_json( { "type": "foo" } ) class TestRemark: def test_remark_runtime_error(self): api = overpy.Overpass() with pytest.raises(overpy.exception.OverpassRuntimeError): api.parse_json(read_file("json/remark-runtime-error-01.json")) def test_remark_runtime_remark(self): api = overpy.Overpass() with pytest.raises(overpy.exception.OverpassRuntimeRemark): api.parse_json(read_file("json/remark-runtime-remark-01.json")) def test_remark_unknown(self): api = overpy.Overpass() with pytest.raises(overpy.exception.OverpassUnknownError): api.parse_json(read_file("json/remark-unknown-01.json")) python-overpy-0.7/tests/test_request.py000066400000000000000000000162221453334100400204660ustar00rootroot00000000000000from http.server import BaseHTTPRequestHandler import pytest import overpy from tests import read_file, new_server_thread, stop_server_thread def handle_bad_request(request): request.send_response(400, "Bad Request") request.send_header("Content-Type", "text/html; charset=utf-8") request.end_headers() request.wfile.write(read_file("response/bad-request.html", "rb")) def handle_bad_request_encoding(request): request.send_response(400, "Bad Request") request.send_header("Content-Type", "text/html; charset=utf-8") request.end_headers() request.wfile.write(read_file("response/bad-request-encoding.html", "rb")) def handle_too_many_requests(request): request.send_response(429, "Too Many Requests") request.send_header("Content-Type", "text/html; charset=utf-8") request.end_headers() request.wfile.write(b"Too Many Requests") def handle_gateway_timeout(request): request.send_response(504, "Gateway Timeout") request.send_header("Content-Type", "text/html; charset=utf-8") request.end_headers() request.wfile.write(b"Gateway Timeout") def handle_unknown_content_type(request): request.send_response(200, "OK") request.send_header("Content-Type", "application/foobar") request.end_headers() request.wfile.write(read_file("xml/way-02.xml", "rb")) def handle_unknown_http_status_code(request): request.send_response(123, "Unknown") request.send_header("Content-Type", "text/html; charset=utf-8") request.end_headers() request.wfile.write(b"Unknown status code") class HandleOverpassBadRequest(BaseHTTPRequestHandler): """ Simulate the response if the query string has syntax errors """ def do_POST(self): handle_bad_request(self) class HandleOverpassBadRequestEncoding(BaseHTTPRequestHandler): """ """ def do_POST(self): handle_bad_request_encoding(self) class HandleOverpassTooManyRequests(BaseHTTPRequestHandler): """ """ def do_POST(self): handle_too_many_requests(self) class HandleOverpassGatewayTimeout(BaseHTTPRequestHandler): """ """ def do_POST(self): handle_gateway_timeout(self) class HandleOverpassUnknownHTTPStatusCode(BaseHTTPRequestHandler): """ """ def do_POST(self): handle_unknown_http_status_code(self) class HandleResponseJSON(BaseHTTPRequestHandler): """ """ def do_POST(self): self.send_response(200, "OK") self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(read_file("json/way-02.json", "rb")) class HandleResponseXML(BaseHTTPRequestHandler): """ """ def do_POST(self): self.send_response(200, "OK") self.send_header("Content-Type", "application/osm3s+xml") self.end_headers() self.wfile.write(read_file("xml/way-02.xml", "rb")) class HandleResponseUnknown(BaseHTTPRequestHandler): """ """ def do_POST(self): handle_unknown_content_type(self) class HandleRetry(BaseHTTPRequestHandler): default_handler_func = [ handle_bad_request, handle_bad_request_encoding, handle_too_many_requests, handle_gateway_timeout, handle_unknown_content_type, handle_unknown_http_status_code ] def do_POST(self): f = self.default_handler_func.pop(0) f(self) class TestQuery: def test_chunk_size(self): url, server = new_server_thread(HandleResponseJSON) api = overpy.Overpass(read_chunk_size=128) api.url = url result = api.query("[out:json];node(50.745,7.17,50.75,7.18);out;") stop_server_thread(server) assert len(result.nodes) > 0 def test_overpass_syntax_error(self): url, server = new_server_thread(HandleOverpassBadRequest) api = overpy.Overpass() api.url = url with pytest.raises(overpy.exception.OverpassBadRequest): # Missing ; after way(1) api.query( "way(1)" "out body;" ) stop_server_thread(server) def test_overpass_syntax_error_encoding_error(self): with pytest.raises(UnicodeDecodeError): # File should be encoded with iso8859-15 and will raise an exception tmp = read_file("response/bad-request-encoding.html", "rb") tmp.decode("utf-8") url, server = new_server_thread(HandleOverpassBadRequestEncoding) api = overpy.Overpass() api.url = url with pytest.raises(overpy.exception.OverpassBadRequest): # Missing ; after way(1) api.query( "way(1)" "out body;" ) stop_server_thread(server) def test_overpass_too_many_requests(self): url, server = new_server_thread(HandleOverpassTooManyRequests) api = overpy.Overpass() api.url = url with pytest.raises(overpy.exception.OverpassTooManyRequests): api.query( "way(1);" "out body;" ) stop_server_thread(server) def test_overpass_gateway_timeout(self): url, server = new_server_thread(HandleOverpassGatewayTimeout) api = overpy.Overpass() api.url = url with pytest.raises(overpy.exception.OverpassGatewayTimeout): api.query( "way(1);" "out body;" ) stop_server_thread(server) def test_overpass_unknown_status_code(self): url, server = new_server_thread(HandleOverpassUnknownHTTPStatusCode) api = overpy.Overpass() api.url = url with pytest.raises(overpy.exception.OverpassUnknownHTTPStatusCode): api.query( "way(1);" "out body;" ) stop_server_thread(server) def test_response_json(self): url, server = new_server_thread(HandleResponseJSON) api = overpy.Overpass() api.url = url result = api.query("[out:json];node(50.745,7.17,50.75,7.18);out;") stop_server_thread(server) assert len(result.nodes) > 0 def test_response_unknown(self): url, server = new_server_thread(HandleResponseUnknown) api = overpy.Overpass() api.url = url with pytest.raises(overpy.exception.OverpassUnknownContentType): api.query("[out:xml];node(50.745,7.17,50.75,7.18);out;") stop_server_thread(server) def test_response_xml(self): url, server = new_server_thread(HandleResponseXML) api = overpy.Overpass() api.url = url result = api.query("[out:xml];node(50.745,7.17,50.75,7.18);out;") stop_server_thread(server) assert len(result.nodes) > 0 def test_retry(self): url, server = new_server_thread(HandleRetry) api = overpy.Overpass() # HandleRetry.default_handler_cls should contain at least 2 classes to process api.max_retry_count = len(HandleRetry.default_handler_func) - 1 api.url = url with pytest.raises(overpy.exception.MaxRetriesReached): api.query( "way(1);" "out body;" ) stop_server_thread(server) python-overpy-0.7/tests/test_result.py000066400000000000000000000133211453334100400203110ustar00rootroot00000000000000from http.server import BaseHTTPRequestHandler import pytest import overpy from tests import read_file, new_server_thread, stop_server_thread from tests.base_class import BaseTestWay class HandleResponseJSON02(BaseHTTPRequestHandler): """ """ def do_POST(self): self.send_response(200, "OK") self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(read_file("json/result-expand-02.json", "rb")) class TestResult: def test_expand_error(self): api = overpy.Overpass() result = api.parse_json(read_file("json/result-expand-01.json")) with pytest.raises(ValueError): result.expand(123) with pytest.raises(ValueError): result.expand(1.23) with pytest.raises(ValueError): result.expand("abc") def test_expand_01(self): api = overpy.Overpass() result1 = api.parse_json(read_file("json/result-expand-01.json")) assert len(result1.nodes) == 2 assert len(result1.ways) == 1 result2 = api.parse_json(read_file("json/result-expand-02.json")) assert len(result2.nodes) == 2 assert len(result2.ways) == 1 result1.expand(result2) # Don't overwrite existing elements assert len(result1.nodes) == 3 assert len(result1.ways) == 2 class TestArea: def test_missing_unresolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) with pytest.raises(overpy.exception.DataIncomplete): result1.get_area(123, resolve_missing=True) stop_server_thread(server) def test_missing_resolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) # Node must not be available with pytest.raises(overpy.exception.DataIncomplete): result1.get_area(3605945176) # Node must be available area = result1.get_area(3605945176, resolve_missing=True) assert isinstance(area, overpy.Area) assert area.id == 3605945176 stop_server_thread(server) class TestNode: def test_missing_unresolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) with pytest.raises(overpy.exception.DataIncomplete): result1.get_node(123, resolve_missing=True) stop_server_thread(server) def test_missing_resolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) # Node must not be available with pytest.raises(overpy.exception.DataIncomplete): result1.get_node(3233854235) # Node must be available node = result1.get_node(3233854235, resolve_missing=True) assert isinstance(node, overpy.Node) assert node.id == 3233854235 stop_server_thread(server) class TestPickle(BaseTestWay): def test_way02(self): """ Try to pickle and unpickle the result object """ import pickle api = overpy.Overpass() result = api.parse_json(read_file("json/way-02.json")) self._test_way02(result) # do pickle and unpickle result_string = pickle.dumps(result) new_result = pickle.loads(result_string) # test new result self._test_way02(new_result) class TestRelation: def test_missing_unresolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) with pytest.raises(overpy.exception.DataIncomplete): result1.get_relation(123, resolve_missing=True) stop_server_thread(server) def test_missing_resolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) # Relation must not be available with pytest.raises(overpy.exception.DataIncomplete): result1.get_relation(2046898) # Relation must be available relation = result1.get_relation(2046898, resolve_missing=True) assert isinstance(relation, overpy.Relation) assert relation.id == 2046898 stop_server_thread(server) class TestWay: def test_missing_unresolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) with pytest.raises(overpy.exception.DataIncomplete): result1.get_way(123, resolve_missing=True) stop_server_thread(server) def test_missing_resolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result1 = api.parse_json(read_file("json/result-expand-01.json")) # Way must not be available with pytest.raises(overpy.exception.DataIncomplete): result1.get_way(317146078) # Way must be available way = result1.get_way(317146078, resolve_missing=True) assert isinstance(way, overpy.Way) assert way.id == 317146078 stop_server_thread(server) python-overpy-0.7/tests/test_result_way.py000066400000000000000000000055551453334100400212030ustar00rootroot00000000000000from http.server import BaseHTTPRequestHandler import pytest import overpy from tests import read_file, new_server_thread, stop_server_thread class HandleResponseJSON01(BaseHTTPRequestHandler): """ """ def do_POST(self): self.send_response(200, "OK") self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(read_file("json/result-way-01.json", "rb")) class HandleResponseJSON02(BaseHTTPRequestHandler): """ """ def do_POST(self): self.send_response(200, "OK") self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(read_file("json/result-way-02.json", "rb")) class HandleResponseJSON03(BaseHTTPRequestHandler): """ """ def do_POST(self): self.send_response(200, "OK") self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(read_file("json/result-way-03.json", "rb")) class TestNodes: def test_missing_unresolvable(self): url, server = new_server_thread(HandleResponseJSON01) api = overpy.Overpass() api.url = url result = api.parse_json(read_file("json/result-way-01.json")) assert len(result.nodes) == 0 assert len(result.ways) == 1 way = result.ways[0] assert isinstance(way, overpy.Way) with pytest.raises(overpy.exception.DataIncomplete): way.get_nodes() with pytest.raises(overpy.exception.DataIncomplete): way.get_nodes(resolve_missing=True) assert len(result.nodes) == 0 stop_server_thread(server) def test_missing_partly_unresolvable(self): url, server = new_server_thread(HandleResponseJSON02) api = overpy.Overpass() api.url = url result = api.parse_json(read_file("json/result-way-01.json")) assert len(result.nodes) == 0 assert len(result.ways) == 1 way = result.ways[0] assert isinstance(way, overpy.Way) with pytest.raises(overpy.exception.DataIncomplete): way.get_nodes() with pytest.raises(overpy.exception.DataIncomplete): way.get_nodes(resolve_missing=True) assert len(result.nodes) == 1 stop_server_thread(server) def test_missing_resolvable(self): url, server = new_server_thread(HandleResponseJSON03) api = overpy.Overpass() api.url = url result = api.parse_json(read_file("json/result-way-01.json")) assert len(result.nodes) == 0 assert len(result.ways) == 1 way = result.ways[0] assert isinstance(way, overpy.Way) with pytest.raises(overpy.exception.DataIncomplete): way.get_nodes() nodes = way.get_nodes(resolve_missing=True) assert len(nodes) == 2 stop_server_thread(server) python-overpy-0.7/tests/test_xml.py000066400000000000000000000160071453334100400175770ustar00rootroot00000000000000import pytest import overpy from tests import read_file from tests.base_class import BaseTestAreas, BaseTestNodes, BaseTestRelation, BaseTestWay class TestAreas(BaseTestAreas): def test_node01(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/area-01.xml"), parser=overpy.XML_PARSER_DOM) self._test_area01(result) # SAX result = api.parse_xml(read_file("xml/area-01.xml"), parser=overpy.XML_PARSER_SAX) self._test_area01(result) class TestNodes(BaseTestNodes): def test_node01(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/node-01.xml"), parser=overpy.XML_PARSER_DOM) self._test_node01(result) # SAX result = api.parse_xml(read_file("xml/node-01.xml"), parser=overpy.XML_PARSER_SAX) self._test_node01(result) class TestRelation(BaseTestRelation): def test_relation01(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/relation-01.xml"), parser=overpy.XML_PARSER_DOM) self._test_relation01(result) # SAX result = api.parse_xml(read_file("xml/relation-01.xml"), parser=overpy.XML_PARSER_SAX) self._test_relation01(result) def test_relation02(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/relation-02.xml"), parser=overpy.XML_PARSER_DOM) self._test_relation02(result) # SAX result = api.parse_xml(read_file("xml/relation-02.xml"), parser=overpy.XML_PARSER_SAX) self._test_relation02(result) def test_relation03(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/relation-03.xml"), parser=overpy.XML_PARSER_DOM) self._test_relation03(result) # SAX result = api.parse_xml(read_file("xml/relation-03.xml"), parser=overpy.XML_PARSER_SAX) self._test_relation03(result) def test_relation04(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/relation-04.xml"), parser=overpy.XML_PARSER_DOM) self._test_relation04(result) # SAX result = api.parse_xml(read_file("xml/relation-04.xml"), parser=overpy.XML_PARSER_SAX) self._test_relation04(result) class TestWay(BaseTestWay): def test_way01(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/way-01.xml"), parser=overpy.XML_PARSER_DOM) self._test_way01(result) # SAX result = api.parse_xml(read_file("xml/way-01.xml"), parser=overpy.XML_PARSER_SAX) self._test_way01(result) def test_way02(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/way-02.xml"), parser=overpy.XML_PARSER_DOM) self._test_way02(result) # SAX result = api.parse_xml(read_file("xml/way-02.xml"), parser=overpy.XML_PARSER_SAX) self._test_way02(result) def test_way03(self): api = overpy.Overpass() # DOM result = api.parse_xml(read_file("xml/way-03.xml"), parser=overpy.XML_PARSER_DOM) self._test_way03(result) # SAX result = api.parse_xml(read_file("xml/way-03.xml"), parser=overpy.XML_PARSER_SAX) self._test_way03(result) def test_way04(self): api = overpy.Overpass() # DOM with pytest.raises(ValueError): api.parse_xml(read_file("xml/way-04.xml"), parser=overpy.XML_PARSER_DOM) # SAX with pytest.raises(ValueError): api.parse_xml(read_file("xml/way-04.xml"), parser=overpy.XML_PARSER_SAX) class TestDataError: @staticmethod def _get_element_wrong_type(): data = "" import xml.etree.ElementTree as ET return ET.fromstring(data) def test_element_wrong_type(self): with pytest.raises(overpy.exception.ElementDataWrongType): overpy.Node.from_xml( self._get_element_wrong_type() ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.Relation.from_xml( self._get_element_wrong_type() ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.RelationNode.from_xml( self._get_element_wrong_type() ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.RelationWay.from_xml( self._get_element_wrong_type() ) with pytest.raises(overpy.exception.ElementDataWrongType): overpy.Way.from_xml( self._get_element_wrong_type() ) def test_node_missing_data(self): import xml.etree.ElementTree as ET # Tag without k attribute data = """""" node = ET.fromstring(data) with pytest.raises(ValueError): overpy.Node.from_xml(node) def test_relation_missing_data(self): import xml.etree.ElementTree as ET # Tag without k attribute data = """""" node = ET.fromstring(data) with pytest.raises(ValueError): overpy.Relation.from_xml(node) def test_way_missing_data(self): import xml.etree.ElementTree as ET # Node without ref attribute data = """""" node = ET.fromstring(data) with pytest.raises(ValueError): overpy.Way.from_xml(node) # Tag without k attribute data = """""" node = ET.fromstring(data) with pytest.raises(ValueError): overpy.Way.from_xml(node) class TestParser(BaseTestNodes): def test_exception(self): with pytest.raises(overpy.exception.OverPyException): overpy.Result.from_xml(123) def test_xml_element(self): import xml.etree.ElementTree as ET data = read_file("xml/node-01.xml") root = ET.fromstring(data) result = overpy.Result.from_xml(root) assert isinstance(result, overpy.Result) self._test_node01(result) def test_xml_autodetect_parser(self): data = read_file("xml/node-01.xml") result = overpy.Result.from_xml(data) assert isinstance(result, overpy.Result) self._test_node01(result) class TestRemark: def test_remark_runtime_error(self): api = overpy.Overpass() with pytest.raises(overpy.exception.OverpassRuntimeError): api.parse_xml(read_file("xml/remark-runtime-error-01.xml")) def test_remark_runtime_remark(self): api = overpy.Overpass() with pytest.raises(overpy.exception.OverpassRuntimeRemark): api.parse_xml(read_file("xml/remark-runtime-remark-01.xml")) def test_remark_unknown(self): api = overpy.Overpass() with pytest.raises(overpy.exception.OverpassUnknownError): api.parse_xml(read_file("xml/remark-unknown-01.xml")) python-overpy-0.7/tests/xml/000077500000000000000000000000001453334100400161625ustar00rootroot00000000000000python-overpy-0.7/tests/xml/area-01.xml000066400000000000000000000051611453334100400200350ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/node-01.xml000066400000000000000000000010711453334100400200460ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/relation-01.xml000066400000000000000000000015051453334100400207400ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/relation-02.xml000066400000000000000000000020641453334100400207420ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/relation-03.xml000066400000000000000000000160311453334100400207420ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.
python-overpy-0.7/tests/xml/relation-04.xml000066400000000000000000000655061453334100400207560ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/remark-runtime-error-01.xml000066400000000000000000000005601453334100400232140ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. runtime error: Query timed out in "query" at line 4 after 2 seconds. python-overpy-0.7/tests/xml/remark-runtime-remark-01.xml000066400000000000000000000005001453334100400233360ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. runtime remark: Test python-overpy-0.7/tests/xml/remark-unknown-01.xml000066400000000000000000000004671453334100400221070ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. Test remark python-overpy-0.7/tests/xml/way-01.xml000066400000000000000000000014621453334100400177250ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/way-02.xml000066400000000000000000000015301453334100400177220ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. python-overpy-0.7/tests/xml/way-03.xml000066400000000000000000000023321453334100400177240ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.
python-overpy-0.7/tests/xml/way-04.xml000066400000000000000000000007621453334100400177320ustar00rootroot00000000000000 The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.
python-overpy-0.7/tox.ini000066400000000000000000000005311453334100400155320ustar00rootroot00000000000000# SPDX-FileCopyrightText: none # SPDX-License-Identifier: CC0-1.0 [tox] envlist = py37,py38,py39,py310,py311,pypy39 [testenv] deps = pytest pytest-cov commands = pytest --cov overpy --cov-report=term-missing -v tests/ [gh-actions] python = 3.7: py37 3.8: py38 3.9: py39 3.10: py310 3.11: py311 pypy3.9: pypy39