├── .github └── workflows │ ├── ci-development.yml │ └── ci-production.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── notebooks ├── Public_Green_Spaces_in_OSM.ipynb └── Tutorial.ipynb ├── ohsome ├── __init__.py ├── clients.py ├── constants.py ├── exceptions.py ├── helper.py ├── response.py └── test │ ├── __init__.py │ ├── cassettes │ ├── test_client │ │ ├── test_check_time_parameter_datetime.yaml │ │ ├── test_check_time_parameter_list.yaml │ │ ├── test_end_timestamp_as_time_input.yaml │ │ ├── test_format_bboxes_dataframe.yaml │ │ ├── test_format_bboxes_list.yaml │ │ ├── test_format_bcircles_dataframe.yaml │ │ ├── test_format_bcircles_list.yaml │ │ ├── test_format_bcircles_pandas.yaml │ │ ├── test_post_with_endpoint_string.yaml │ │ └── test_user_agent.yaml │ ├── test_exceptions │ │ ├── test_disable_logging.yaml │ │ ├── test_exception_connection_reset.yaml │ │ ├── test_exception_invalid_parameters.yaml │ │ ├── test_invalid_url.yaml │ │ ├── test_log_bpolys.yaml │ │ ├── test_log_curl.yaml │ │ └── test_timeout_error.yaml │ └── test_response │ │ ├── test_all_columns_with_timestamps_to_be_without_timezone.yaml │ │ ├── test_contributions_centroid.yaml │ │ ├── test_contributions_count_density_groupbyboundary.yaml │ │ ├── test_contributions_latest.yaml │ │ ├── test_elementsFullHistory_geometry.yaml │ │ ├── test_elements_count.yaml │ │ ├── test_elements_count_groupby_boundary.yaml │ │ ├── test_elements_count_groupby_boundary_groupby_tag.yaml │ │ ├── test_elements_count_groupby_key.yaml │ │ ├── test_elements_count_groupby_tag.yaml │ │ ├── test_elements_count_groupby_type.yaml │ │ ├── test_elements_count_ratio.yaml │ │ ├── test_elements_count_ratio_groupby_boundary.yaml │ │ ├── test_elements_density.yaml │ │ ├── test_elements_geometry.yaml │ │ ├── test_empty_geodataframe.yaml │ │ ├── test_extra_tags_argument.yaml │ │ ├── test_multi_index_false.yaml │ │ ├── test_not_implemented_query.yaml │ │ └── test_users_timestamp.yaml │ ├── conftest.py │ ├── data │ ├── invalid_response.txt │ ├── invalid_response_customCode.txt │ ├── invalid_response_no_message.txt │ ├── invalid_response_outOfMemory.txt │ ├── points.geojson │ └── polygons.geojson │ ├── test_client.py │ ├── test_exceptions.py │ ├── test_helper.py │ └── test_response.py ├── poetry.lock ├── pyproject.toml └── pytest.ini /.github/workflows/ci-development.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration for development 2 | 3 | on: pull_request 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-22.04 7 | steps: 8 | - uses: actions/checkout@v4 9 | - name: Install python 10 | uses: actions/setup-python@v4 11 | with: 12 | python-version: "3.11" 13 | - name: Install lint dependencies 14 | run: | 15 | pip install pre-commit black 16 | - name: Install and run pre-commit 17 | uses: pre-commit/action@v3.0.0 18 | test: 19 | runs-on: ubuntu-22.04 20 | needs: 21 | - lint 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | python-version: ["3.10", "3.11", "3.12"] 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Set up testing python ${{ matrix.config.python-version }} 30 | uses: actions/setup-python@v4 31 | with: 32 | python-version: ${{ matrix.config.python-version }} 33 | - name: Install poetry 34 | uses: abatilo/actions-poetry@v2.3.0 35 | - name: Setup a local virtual environment for caching 36 | run: | 37 | poetry config virtualenvs.create true --local 38 | poetry config virtualenvs.in-project true --local 39 | - name: Define a cache for the virtual environment based on the dependencies lock file to speed up later runs 40 | uses: actions/cache@v3 41 | with: 42 | path: ./.venv 43 | key: venv-${{ hashFiles('poetry.lock') }} 44 | - name: Install dependencies 45 | run: poetry install --no-root --without dev 46 | - name: Pytest 47 | run: poetry run pytest -x --random-order 48 | -------------------------------------------------------------------------------- /.github/workflows/ci-production.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | release: 9 | types: 10 | - created 11 | 12 | jobs: 13 | test: 14 | runs-on: ubuntu-22.04 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | python-version: ["3.10", "3.11", "3.12"] 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Set up testing python ${{ matrix.config.python-version }} 23 | uses: actions/setup-python@v4 24 | with: 25 | python-version: ${{ matrix.config.python-version }} 26 | - name: Install poetry 27 | uses: abatilo/actions-poetry@v2.3.0 28 | - name: Setup a local virtual environment for caching 29 | run: | 30 | poetry config virtualenvs.create true --local 31 | poetry config virtualenvs.in-project true --local 32 | - name: Define a cache for the virtual environment based on the dependencies lock file to speed up later runs 33 | uses: actions/cache@v3 34 | with: 35 | path: ./.venv 36 | key: venv-${{ hashFiles('poetry.lock') }} 37 | - name: Install dependencies 38 | run: poetry install --no-root --without dev 39 | - name: Pytest 40 | run: poetry run pytest -x --random-order 41 | 42 | build-and-publish: 43 | name: Build and publish Python distributions 📦 to PyPI and TestPyPI 44 | runs-on: ubuntu-22.04 45 | needs: 46 | - test 47 | steps: 48 | - uses: actions/checkout@v4 49 | - name: Set up base Python 3.11 50 | uses: actions/setup-python@v4 51 | with: 52 | python-version: 3.11 53 | - name: Python Poetry Action 54 | uses: abatilo/actions-poetry@v2.3.0 55 | - name: Publish distribution 📦 with test.pypi.org 56 | if: startsWith(github.ref, 'refs/tags') 57 | run: | 58 | poetry config repositories.testpypi https://test.pypi.org/legacy/ 59 | poetry config pypi-token.testpypi ${{ secrets.TEST_PYPI_API_TOKEN }} 60 | poetry build 61 | poetry publish -r testpypi 62 | - name: Publish distribution 📦 to PyPI 63 | if: startsWith(github.ref, 'refs/tags') 64 | run: | 65 | poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }} 66 | poetry build 67 | poetry publish 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # PyCharm 121 | .idea 122 | __pycache__ 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # Setup.py as it will be generated on the fly through dephell 136 | setup.py 137 | 138 | 139 | # project files 140 | **/ohsome_log/ 141 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/ambv/black 3 | rev: 23.11.0 4 | hooks: 5 | - id: black 6 | - repo: https://github.com/pycqa/flake8 7 | rev: 6.1.0 8 | hooks: 9 | - id: flake8 10 | args: 11 | - "--max-line-length=79" 12 | - "--max-complexity=18" 13 | - "--ignore=E501,W503,E203,F401,D400,D205,D401,D202,T001,D105" 14 | additional_dependencies: 15 | [ 16 | "flake8-bugbear==23.9.16", 17 | "flake8-coding==1.3.2", 18 | "flake8-comprehensions==3.14.0", 19 | "flake8-debugger==4.1.2", 20 | "flake8-deprecated==2.2.1", 21 | "flake8-pep3101==2.1.0", 22 | "flake8-polyfill==1.0.2", 23 | "flake8-print==5.0.0", 24 | "flake8-string-format==0.3.0", 25 | "flake8-docstrings==1.7.0", 26 | ] 27 | - repo: https://github.com/pre-commit/pre-commit-hooks 28 | rev: v4.5.0 29 | hooks: 30 | - id: trailing-whitespace 31 | - id: end-of-file-fixer 32 | - id: check-yaml 33 | - id: check-json 34 | - id: forbid-new-submodules 35 | - id: mixed-line-ending 36 | args: [ '--fix=lf' ] 37 | description: Forces to replace line ending by the UNIX 'lf' character. 38 | - id: pretty-format-json 39 | args: [ '--no-sort-keys' ] 40 | exclude: '.*.ipynb' 41 | - id: no-commit-to-branch 42 | args: [ --branch, master ] 43 | - id: no-commit-to-branch 44 | args: [ --branch, main ] 45 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [Unreleased](https://github.com/GIScience/ohsome-py/compare/v0.3.3..master) 4 | 5 | ## [0.4.0](https://github.com/GIScience/ohsome-py/releases/tag/v0.4.0) 6 | 7 | ### Changed 8 | 9 | - updated `numpy` and `geopandas` dependency to the latest major versions 10 | 11 | ### Fixed 12 | 13 | - the module configuring the root logger on import causing users to be forced to overwrite the configuration. 14 | 15 | ## [0.3.3](https://github.com/GIScience/ohsome-py/releases/tag/v0.3.3) 16 | 17 | ### Fixed 18 | 19 | - Ordering of exception handling to correctly parse a broken response 20 | - Assert that the expected columns are also present if the result is empty 21 | 22 | ### Removed 23 | 24 | - unused attributes `response` and `parameters`/`params` from `OhsomeResponse` 25 | 26 | ### Added 27 | 28 | - init variable `data` to `OhsomeResponse` 29 | 30 | ## [0.3.2](https://github.com/GIScience/ohsome-py/releases/tag/v0.3.2) 31 | 32 | ### Fixed 33 | 34 | - GeoSeries supplied as `bpolys` input raising exception ([#155](https://github.com/GIScience/ohsome-py/issues/155)) 35 | 36 | ### Changed 37 | 38 | - if tags are supplied for explosion in `response.as_dataframe`, the respective column will always be present in the resulting Geodataframe, even if the tags were not part of the result. In that case the column will be all-None ([#149](https://github.com/GIScience/ohsome-py/issues/149)). 39 | 40 | 41 | ## [0.3.1](https://github.com/GIScience/ohsome-py/releases/tag/v0.3.1) 42 | 43 | ### Fixed 44 | 45 | - prevent an exception if the `log_dir` for the `OhsomeClient` was set to `None` 46 | - removed time-dependency of unit tests that would cause them to fail at any time after the cassettes were recorded 47 | 48 | ### Changed 49 | 50 | - relaxed dependency requirement for `urllib3` to >=2.0.2 to prevent ohsome-py from becoming a 'diamond-dependency' 51 | - improved and sped up testing (first steps towards [#139](https://github.com/GIScience/ohsome-py/issues/139)) 52 | - move metadata property from singleton to `cached_property` 53 | 54 | ## [0.3.0](https://github.com/GIScience/ohsome-py/releases/tag/v0.3.0) 55 | 56 | ### Added 57 | 58 | - support for python 3.12 59 | - custom [retry](https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#urllib3.util.Retry) configuration 60 | - start and end timestamp meta information of the client are now datetime objects 61 | - accept shapely Polygon and MultiPolygon for `bpolys` input parameter 62 | - if a request fails a bash script containing the respective `curl` command is logged (if possible). This allows for easier debugging and sharing of failed requests. 63 | - timestamps are converted without timezone information. Deviates from Ohsome API [(Issue #318)](https://github.com/GIScience/ohsome-api/issues/318) 64 | 65 | ### Changed 66 | 67 | - breaking: geodataframes now contain a `@other_tags` colum containing all OSM tags. This behaviour can be adapted using the `explode_tags` parameter that allows to specify tags that should be in a separate column or to disable the feature completely. The latter will result in a potentially wide but sparse data frame. 68 | 69 | ### Removed 70 | 71 | - support for python < 3.10 72 | - support for geopandas < 0.14 73 | - support for pandas < 2.1 74 | - support for urllib3 < 2.1 75 | 76 | ## [0.2.0](https://github.com/GIScience/ohsome-py/releases/tag/v0.2.0) 77 | 78 | ### Added 79 | 80 | - support for python 3.11 81 | - support for geopandas up to v0.12.0 82 | 83 | ### Removed 84 | 85 | - support for python 3.7 86 | 87 | ### Fixed 88 | 89 | - wrong formatting of list parameters for ohsome requests if not given as string 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ohsome-py: A Python client for the ohsome API 2 | 3 | [![status: active](https://github.com/GIScience/badges/raw/master/status/active.svg)](https://github.com/GIScience/badges#active) 4 | 5 | The *ohsome-py* package helps you extract and analyse OpenStreetMap history data using the [ohsome API](https://docs.ohsome.org/ohsome-api/v1/) and Python. It handles queries to the [ohsome API](https://docs.ohsome.org/ohsome-api/v1/) and converts its responses to [Pandas](https://pandas.pydata.org/) and [GeoPandas](https://geopandas.org/) data frames to facilitate easy data handling and analysis. 6 | 7 | The ohsome API provides various endpoints for [data aggregation](https://api.ohsome.org/v1/swagger-ui.html?urls.primaryName=Data%20Aggregation), [data extraction](https://api.ohsome.org/v1/swagger-ui.html?urls.primaryName=dataExtraction) and [contributions](https://api.ohsome.org/v1/swagger-ui.html?urls.primaryName=Contributions) to analyse the history of OSM data. Take a look at the [documentation of the ohsome API](https://docs.ohsome.org/ohsome-api/stable) or go through the [Tutorial](https://github.com/GIScience/ohsome-py/blob/master/notebooks/Tutorial.ipynb) to get started on how to use *ohsome-py*. 8 | 9 | ## Installation 10 | 11 | ### Using pip 12 | 13 | You can install *ohsome-py* using pip, which will also install all dependencies. 14 | 15 | ``` 16 | $ pip install ohsome 17 | ``` 18 | 19 | ### Using Anaconda 20 | 21 | *ohsome-py* is not available through Conda. So if you are using Conda, create a new conda environment and install your required dependencies as well as those from *ohsome-py* (see [pyproject.toml](pyproject.toml)) before installing *ohsome-py* using pip. Please note that there might be issues when [using pip within anaconda](https://www.anaconda.com/blog/using-pip-in-a-conda-environment). To avoid issues we advise to install everything in a new conda environment. 22 | 23 | ### Dependencies for Jupyter Notebooks 24 | 25 | If you want to run the Jupyter Notebook [Tutorial](https://github.com/GIScience/ohsome-py/blob/master/notebooks/Tutorial.ipynb) you also need to install `jupyter` and `matplotlib` e.g. 26 | 27 | ``` 28 | $ pip install jupyter matplotlib 29 | ``` 30 | 31 | ## Usage 32 | 33 | All queries are handled by an `OhsomeClient` object, which also provides information about the current ohsome API instance, e.g. `start_timestamp` and `end_timestamp` indicate the earliest and the latest possible dates for a query. 34 | 35 | ``` python 36 | from ohsome import OhsomeClient 37 | client = OhsomeClient() 38 | client.start_timestamp # --> '2007-10-08T00:00:00Z' 39 | client.end_timestamp # --> '2021-01-23T03:00Z' 40 | ``` 41 | 42 | ### 1. Data Aggregation 43 | 44 | **Example:** The area of OSM elements tagged as _landuse=farmland_ using the [/elements/area](https://api.ohsome.org/v1/swagger-ui.html?urls.primaryName=Data%20Aggregation#/Elements%20Area/area_1) endpoint: 45 | 46 | ``` python 47 | response = client.elements.area.post(bboxes=[8.625,49.3711,8.7334,49.4397], 48 | time="2014-01-01", 49 | filter="landuse=farmland and geometry:polygon") 50 | ``` 51 | 52 | The single components of the endpoint URL are appended as method calls to the `OhsomeClient` object. Use automatic code completion to find valid endpoints. Alternatively, you can define the endpoint as argument in the `.post()` method. 53 | 54 | ``` python 55 | response = client.post(endpoint="elements/area", 56 | bboxes=[8.625,49.3711,8.7334,49.4397], 57 | time="2020-01-01", 58 | filter="landuse=farmland and geometry:polygon") 59 | ``` 60 | 61 | Responses from the data aggregation endpoints can be converted to a `pandas.DataFrame` object using the `OhsomeResponse.as_dataframe()` method. 62 | 63 | ``` 64 | response_df = response.as_dataframe() 65 | ``` 66 | 67 | ### 2. Data Extraction 68 | 69 | **Example:** OSM elements tagged as _landuse=farmland_ including their geometry and tags using the [/elements/geometry](https://api.ohsome.org/v1/swagger-ui.html?urls.primaryName=Data%20Extraction#/Data%20Extraction/elementsGeometry_1) endpoint: 70 | 71 | ``` python 72 | client = OhsomeClient() 73 | response = client.elements.geometry.post(bboxes=[8.625,49.3711,8.7334,49.4397], 74 | time="2020-01-01", 75 | filter="landuse=farmland and geometry:polygon", 76 | properties="tags") 77 | response_gdf = response.as_dataframe() 78 | ``` 79 | 80 | Responses from the data extraction endpoint can be converted to a `geopandas.GeoDataFrame` using the `OhsomeResponse.as_dataframe()` method, since the data contains geometries. 81 | 82 | ### Query Parameters 83 | 84 | All query parameters are described in the [ohsome API documentation](https://docs.ohsome.org/ohsome-api/stable) and can be passed as `string` objects to the `post()` method. Other Python data types are accepted as well. 85 | 86 | #### Boundary 87 | 88 | The [boundary](https://docs.ohsome.org/ohsome-api/stable/boundaries.html) of the query can be defined using the `bpolys`, `bboxes` and `bcircles` parameters. The coordinates have to be given in WGS 84 (EPSG:4326). 89 | 90 | ##### bpolys 91 | 92 | The `bpolys` parameter can be passed as a `geopandas.GeoDataFrame` containing the polygon features. 93 | 94 | ``` python 95 | bpolys = gpd.read_file("./data/polygons.geojson") 96 | client.elements.count.groupByBoundary.post(bpolys=bpolys, filter="amenity=restaurant") 97 | ``` 98 | 99 | ##### bboxes 100 | 101 | The `bboxes` parameter contains the coordinates of one or several bounding boxes. 102 | 103 | ``` python 104 | bboxes = [8.7137,49.4096,8.717,49.4119] # one bounding box 105 | bboxes = [[8.7137,49.4096,8.717,49.4119], [8.7137,49.4096,8.717,49.4119]] 106 | bboxes = {"A": [8.67066, 49.41423, 8.68177, 49.4204], 107 | "B": [8.67066, 49.41423, 8.68177, 49.4204]} 108 | ``` 109 | 110 | ##### bcircles 111 | 112 | The `bcircles` parameter contains one or several circles defined through the coordinates of the centroids and the radius in meters. 113 | 114 | ```python 115 | bcircles = [8.7137,49.4096, 100] 116 | bcircles = [[8.7137,49.4096, 100], [8.7137,49.4096, 300]] 117 | bcircles = {"Circle1": [8.695, 49.41, 200], 118 | "Circle2": [8.696, 49.41, 200]} 119 | ``` 120 | 121 | #### Time 122 | 123 | The [time](https://docs.ohsome.org/ohsome-api/stable/time.html) parameter must be ISO-8601 conform can be passed in several ways 124 | 125 | ```python 126 | time = '2018-01-01/2018-03-01/P1M' 127 | time = ['2018-01-01', '2018-02-01', '2018-03-01'] 128 | time = datetime.datetime(year=2018, month=3, day=1) 129 | time = pandas.date_range("2018-01-01", periods=3, freq="M") 130 | ``` 131 | ## Citation 132 | 133 | When using [ohsome-py](https://github.com/GIScience/ohsome-py) e.g. for a publication or elsewhere, please cite the ohsome-api as described in their [citation recommendation](https://github.com/GIScience/ohsome-api/blob/master/README.md#how-to-cite) for example like 134 | 135 | > M. Raifer, R. Troilo, F.-B. Mocnikand M. Schott, ‘OSHDB - OpenStreetMap History Data Analysis version 1.2.1 accessed via the ohsome-py library version 0.3.0’. Zenodo, Sep. 29, 2023. doi: 10.5281/zenodo.8391737. 136 | 137 | 138 | ```bibtex 139 | @software{raifer_2023_7713347, 140 | author = {Raifer, Martin and 141 | Troilo, Rafael and 142 | Mocnik, Franz-Benjamin and 143 | Schott, Moritz}, 144 | title = {OSHDB - OpenStreetMap History Data Analysis version 1.2.1 accessed via the ohsome-py library version 0.3.0}, 145 | month = sep, 146 | year = 2023, 147 | publisher = {Zenodo}, 148 | version = {1.2.1}, 149 | doi = {10.5281/zenodo.8391737}, 150 | url = {https://doi.org/10.5281/zenodo.8391737} 151 | } 152 | ``` 153 | 154 | ## Contribution Guidelines 155 | 156 | The easiest way to contribute is to file a comprehensive [issue](https://github.com/GIScience/ohsome-py/issues) with a reproducible example. Pull requests are always welcome, so if you want to contribute to this project, please fork the repository or create a new branch containing your changes. Follow the steps below to make sure that your contributed code follows the code style and does not break any functionality. Create a **pull request to the main/master** branch once it is ready to be merged. 157 | 158 | ### Install Package 159 | 160 | This package uses [poetry](https://python-poetry.org/) for dependency management. To install all packages necessary for testing and development run 161 | 162 | `poetry install` 163 | 164 | ### Install Pre-Commit Hooks 165 | 166 | **Install the pre-commit hooks** in our local git repo before committing to ensure homogenous code style. 167 | 168 | `poetry run pre-commit install` 169 | 170 | ### Run Tests 171 | 172 | **Before pushing your commits**, run the python unit tests 173 | 174 | `poetry run pytest` 175 | 176 | #### VCR 177 | 178 | ohsome-py records responses using [VCR](https://vcrpy.readthedocs.io/en/latest/) via [pytest-recording](https://github.com/kiwicom/pytest-recording) to prevent unnecessary network traffic and computing during testing. If you implement a test or change an existing one, make sure to update the recorded cassettes. In addition, you should delete all cassettes after a certain time (e.g. every 6m or on each new ohsome release) and re-record them. To do that run 179 | 180 | `poetry run pytest --record-mode=all` 181 | 182 | ## References 183 | 184 | The design of this package was inspired by the blog post [Using Python to Implement a Fluent Interface to Any REST API](https://sendgrid.com/blog/using-python-to-implement-a-fluent-interface-to-any-rest-api/) by Elmer Thomas. 185 | -------------------------------------------------------------------------------- /ohsome/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Ohsome API client for Python""" 5 | 6 | # The order of imports here must remain to prevent circular imports 7 | from .exceptions import OhsomeException # noqa 8 | from .response import OhsomeResponse # noqa 9 | from .clients import OhsomeClient # noqa 10 | -------------------------------------------------------------------------------- /ohsome/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """Constants and default values""" 4 | from pathlib import Path 5 | 6 | OHSOME_BASE_API_URL = "https://api.ohsome.org/v1/" 7 | DEFAULT_LOG = True 8 | DEFAULT_LOG_DIR = Path("./ohsome_log") 9 | # update version in pyproject.toml as well 10 | OHSOME_VERSION = "0.3.0" 11 | -------------------------------------------------------------------------------- /ohsome/exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Class to handle error codes of ohsome API""" 5 | 6 | import datetime as dt 7 | import json 8 | from pathlib import Path 9 | 10 | from curlify2 import Curlify 11 | 12 | 13 | class OhsomeException(Exception): 14 | """Exception to handle ohsome API errors""" 15 | 16 | def __init__( 17 | self, message=None, url=None, params=None, error_code=None, response=None 18 | ): 19 | """Initialize OhsomeException object""" 20 | super(Exception, self).__init__(message) 21 | self.message = message 22 | self.url = url 23 | if params: 24 | self.parameters = {k: v for k, v in params.items() if v is not None} 25 | self.error_code = error_code 26 | self.response = response 27 | self.timestamp = dt.datetime.now().isoformat() 28 | 29 | def log(self, log_dir: Path): 30 | """ 31 | Logs OhsomeException 32 | :return: 33 | """ 34 | log_file_name = f"ohsome_{dt.datetime.now().strftime('%Y-%m-%dT%H%M%S')}" 35 | self.log_bpolys(log_dir, log_file_name) 36 | self.log_parameter(log_dir, log_file_name) 37 | if self.response is not None: 38 | self.log_curl(log_dir, log_file_name) 39 | self.log_response(log_dir, log_file_name) 40 | 41 | def log_curl(self, log_dir: Path, log_file_name: str) -> None: 42 | """Log the respective curl command for the request for easy debugging and sharing.""" 43 | log_file = log_dir / f"{log_file_name}_curl.sh" 44 | curl = Curlify(self.response.request) 45 | curl_command = curl.to_curl() 46 | with log_file.open(mode="w") as dst: 47 | dst.write(curl_command) 48 | 49 | def log_response(self, log_dir: Path, log_file_name: str): 50 | """ 51 | Log raw response. This may duplicate much data but is helpful for debugging to know the exact raw answer by the 52 | ohsome-api. 53 | """ 54 | log_file = log_dir / f"{log_file_name}_raw.txt" 55 | with log_file.open(mode="w") as dst: 56 | dst.write(self.response.text) 57 | 58 | def log_parameter(self, log_dir: Path, log_file_name: str) -> None: 59 | """ 60 | Log query parameters to file 61 | :param log_dir: 62 | :param log_file_name: 63 | :return: 64 | """ 65 | log_file = log_dir / f"{log_file_name}.json" 66 | 67 | log = { 68 | "timestamp": self.timestamp, 69 | "status": self.error_code, 70 | "message": self.message, 71 | "requestUrl": self.url, 72 | "parameters": self.parameters, 73 | } 74 | with log_file.open(mode="w") as dst: 75 | json.dump(obj=log, fp=dst, indent=4) 76 | 77 | def log_bpolys(self, log_dir: Path, log_file_name: str) -> None: 78 | """ 79 | Log bpolys parameter to geojson file if it is included in the query 80 | :params log_file: Path to geojson file which should contain bpolys parameter 81 | :return: 82 | """ 83 | if "bpolys" in self.parameters: 84 | log_file_bpolys = log_dir / f"{log_file_name}_bpolys.geojson" 85 | bpolys = self.parameters.pop("bpolys") 86 | with log_file_bpolys.open(mode="w") as dst: 87 | json.dump(obj=json.loads(bpolys), fp=dst, indent=4) 88 | 89 | def __str__(self): 90 | return f"OhsomeException ({self.error_code}): {self.message}" 91 | -------------------------------------------------------------------------------- /ohsome/helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Ohsome utility functions""" 5 | 6 | import datetime 7 | import json 8 | import re 9 | from typing import Tuple, Union, List, Optional 10 | 11 | import geopandas as gpd 12 | import numpy as np 13 | import pandas as pd 14 | import shapely 15 | 16 | from ohsome import OhsomeException 17 | 18 | 19 | def convert_arrays(params: dict) -> dict: 20 | """Convert arrays to lists. 21 | 22 | params: the request parameters 23 | """ 24 | for i in params.keys(): 25 | if isinstance(params[i], np.ndarray): 26 | assert ( 27 | params[i].ndim == 1 28 | ), f"Only one dimensional arrays are supported for parameter {i}" 29 | params[i] = list(params[i]) 30 | 31 | return params 32 | 33 | 34 | def format_time(time: any) -> str: 35 | """ 36 | Formats the 'time' parameter 37 | :param time: 38 | :return: 39 | """ 40 | if isinstance(time, str): 41 | return time 42 | if isinstance(time, datetime.datetime) or isinstance(time, datetime.date): 43 | return time.isoformat() 44 | elif isinstance(time, list): 45 | return ",".join([format_time(t) for t in time]) 46 | if isinstance(time, pd.DatetimeIndex) or isinstance(time, pd.Series): 47 | return format_time(time.to_list()) 48 | else: 49 | raise ValueError( 50 | f"The given time format {type(time)} is not supported. Feel free to open an issue in " 51 | "the ohsome-py repository for a feature request." 52 | ) 53 | 54 | 55 | def format_boundary(params: dict) -> dict: 56 | """ 57 | Formats the boundary parameters 'bboxes', 'bcircles' and 'bpolys' 58 | :param params: 59 | :return: 60 | """ 61 | if params["bboxes"] is not None: 62 | params["bboxes"] = format_bboxes(params["bboxes"]) 63 | elif params["bpolys"] is not None: 64 | params["bpolys"] = format_bpolys(params["bpolys"]) 65 | elif params["bcircles"] is not None: 66 | params["bcircles"] = format_bcircles(params["bcircles"]) 67 | else: 68 | raise OhsomeException( 69 | message="No valid boundary parameter is given. Specify one of the parameters 'bboxes', 'bpolys' or " 70 | "'bcircles'.", 71 | error_code=440, 72 | params=params, 73 | ) 74 | 75 | return params 76 | 77 | 78 | def format_bcircles( 79 | bcircles: Union[ 80 | str, 81 | List[str], 82 | List[float], 83 | List[List[str]], 84 | List[List[float]], 85 | dict, 86 | gpd.GeoDataFrame, 87 | pd.DataFrame, 88 | ] 89 | ) -> str: 90 | """ 91 | Formats bcircles parameter to comply with ohsome API 92 | :param 93 | bcircles: Centroids and radius of the circles given as 94 | string (lon,lat,radius|lon,lat,radius|… or id1:lon,lat,radius|id2:lon,lat,radius|…) 95 | list ([[id1:lon1,lat1,radius],[id2:lon1,lat1,radius],...] 96 | pandas.DataFrame with columns 'lon', 'lat' and 'radius' or 97 | geopandas.GeoDataFrame with geometry column with Point geometries only and a column 'radius'. 98 | :return: 99 | """ 100 | if isinstance(bcircles, str): 101 | return bcircles 102 | elif isinstance(bcircles, list) or isinstance(bcircles, tuple): 103 | if isinstance(bcircles[0], list): 104 | return "|".join([",".join([str(x) for x in box]) for box in bcircles]) 105 | elif isinstance(bcircles[1], float) or isinstance(bcircles[1], int): 106 | return ",".join([str(x) for x in bcircles]) 107 | elif isinstance(bcircles[0], str) and (bcircles[0].find(",") != -1): 108 | return "|".join([str(c) for c in bcircles]) 109 | else: 110 | raise OhsomeException("'bcircles' parameter has invalid format.") 111 | elif isinstance(bcircles, dict): 112 | return "|".join( 113 | [ 114 | f"{bcircle_id}:" + ",".join([str(c) for c in coords]) 115 | for bcircle_id, coords in bcircles.items() 116 | ] 117 | ) 118 | elif isinstance(bcircles, gpd.GeoDataFrame): 119 | if (bcircles.geometry.geom_type.unique() != ["Point"]) or ( 120 | "radius" not in bcircles.columns 121 | ): 122 | raise OhsomeException( 123 | message="The geometry of the 'bcircles' GeoDataFrame may only include 'Point' geometry types and " 124 | "requires a 'radius' column." 125 | ) 126 | formatted = bcircles.apply( 127 | lambda r: f"{int(r.name)}:{r.geometry.x},{r.geometry.y},{r['radius']}", 128 | axis=1, 129 | ) 130 | return "|".join(formatted.to_list()) 131 | elif isinstance(bcircles, pd.DataFrame): 132 | try: 133 | formatted = bcircles.apply( 134 | lambda r: f"{int(r.name)}:{r['lon']},{r['lat']},{r['radius']}", 135 | axis=1, 136 | ) 137 | return "|".join(formatted.to_list()) 138 | except KeyError as e: 139 | raise OhsomeException( 140 | message=f"Column {e} is missing in the dataframe provided as 'bboxes'." 141 | ) 142 | else: 143 | raise OhsomeException(message="'bcircles' parameter has invalid format.") 144 | 145 | 146 | def format_bboxes( 147 | bboxes: Union[ 148 | str, 149 | dict, 150 | pd.DataFrame, 151 | List[str], 152 | List[float], 153 | List[List[str]], 154 | List[List[float]], 155 | ] 156 | ) -> str: 157 | """ 158 | Formats bboxes parameter to comply with ohsome API 159 | :param 160 | bboxes: Bounding boxes given as 161 | string: lon1,lat1,lon2,lat2|lon1,lat1,lon2,lat2|… or id1:lon1,lat1,lon2,lat2|id2:lon1,lat1,lon2,lat2|… 162 | list: [[id1,lon1,lat1,lon2,lat2],[id2,lon1,lat1,lon2,lat2],...] or [lon1,lat1,lon2,lat2] if it's just one box 163 | pandas.DataFrame: with columns minx, miny, maxx, maxy. These columns can be created from a GeoDataFrame using 164 | the 'GeoDataFrame.bounds' method. 165 | :return: Bounding boxes formatted as a string compliant with ohsome API 166 | """ 167 | if isinstance(bboxes, list) or isinstance(bboxes, tuple): 168 | if isinstance(bboxes[0], list): 169 | return "|".join([",".join([str(x) for x in box]) for box in bboxes]) 170 | elif isinstance(bboxes[1], float) or isinstance(bboxes[1], int): 171 | return ",".join([str(x) for x in bboxes]) 172 | elif isinstance(bboxes[0], str) and (bboxes[0].find(",") != -1): 173 | return "|".join([str(c) for c in bboxes]) 174 | else: 175 | raise OhsomeException(message="'bboxes' parameter has invalid format.") 176 | elif isinstance(bboxes, dict): 177 | return "|".join( 178 | [ 179 | f"{bbox_id}:" + ",".join([str(c) for c in coords]) 180 | for bbox_id, coords in bboxes.items() 181 | ] 182 | ) 183 | elif isinstance(bboxes, str): 184 | return bboxes 185 | elif isinstance(bboxes, gpd.GeoDataFrame) or isinstance(bboxes, gpd.GeoSeries): 186 | raise OhsomeException( 187 | message="Use the 'bpolys' parameter to specify the boundaries using a geopandas object." 188 | ) 189 | elif isinstance(bboxes, pd.DataFrame): 190 | try: 191 | formatted = bboxes.apply( 192 | lambda r: f"{r.name}:{r['minx']},{r['miny']},{r['maxx']},{r['maxy']}", 193 | axis=1, 194 | ) 195 | return "|".join(formatted.to_list()) 196 | except KeyError as e: 197 | raise OhsomeException( 198 | message=f"Column {e} is missing in the dataframe provided as 'bboxes'." 199 | ) 200 | else: 201 | raise OhsomeException( 202 | message="'bboxes' must be given as string, list or pandas.DataFrame." 203 | ) 204 | 205 | 206 | def format_bpolys( 207 | bpolys: Union[ 208 | gpd.GeoDataFrame, gpd.GeoSeries, shapely.Polygon, shapely.MultiPolygon, str 209 | ] 210 | ) -> str: 211 | """ 212 | Formats bpolys parameter to comply with ohsome API 213 | :param 214 | bpolys: Polygons given as geopandas.GeoDataFrame, geopandas.GeoSeries, Shapely.Polygon or GeoJSON FeatureCollection as string. 215 | :return: 216 | """ 217 | if isinstance(bpolys, gpd.GeoDataFrame): 218 | return bpolys.to_json(na="drop", show_bbox=False, drop_id=False, to_wgs84=True) 219 | elif isinstance(bpolys, gpd.GeoSeries): 220 | return format_bpolys(bpolys.to_frame("geometry")) 221 | elif isinstance(bpolys, shapely.Polygon) or isinstance( 222 | bpolys, shapely.MultiPolygon 223 | ): 224 | return format_bpolys(gpd.GeoDataFrame(geometry=[bpolys], crs="EPSG:4326")) 225 | elif isinstance(bpolys, str): 226 | try: 227 | return format_bpolys( 228 | gpd.GeoDataFrame.from_features(json.loads(bpolys), crs="EPSG:4326") 229 | ) 230 | except Exception as e: 231 | raise OhsomeException(message="Invalid geojson.") from e 232 | else: 233 | raise OhsomeException( 234 | message="bpolys must be a geojson string, a shapely polygonal object or a geopandas object" 235 | ) 236 | 237 | 238 | def format_list_parameters(parameters: dict) -> dict: 239 | """Converts parameters of type list to strings using ',' as seperator.""" 240 | list_parameters = ["groupByKeys", "groupByValues", "properties"] 241 | for param in list_parameters: 242 | if isinstance(parameters.get(param), list): 243 | parameters[param] = ",".join(parameters[param]) 244 | 245 | return parameters 246 | 247 | 248 | def find_groupby_names(url: Optional[str]) -> List[str]: 249 | """ 250 | Get the groupBy names 251 | :return: 252 | """ 253 | return [name.strip("/") for name in url.split("groupBy")[1:]] if url else [] 254 | 255 | 256 | def extract_error_message_from_invalid_json(responsetext: str) -> Tuple[int, str]: 257 | """ 258 | Extract error code and error message from invalid json returned from ohsome API 259 | Otherwise throws OhsomeException. 260 | :param responsetext: 261 | :return: 262 | 263 | """ 264 | message = "A broken response has been received" 265 | 266 | m = re.search('"message" : "(.*)"', responsetext) 267 | if m: 268 | message += ": " + m.group(1) 269 | 270 | m = re.search('"error" : "(.*)"', responsetext) 271 | if m: 272 | message += "; " + m.group(0) 273 | 274 | m = re.search('"timestamp" : "(.*)"', responsetext) 275 | if m: 276 | message += "; " + m.group(0) 277 | 278 | m = re.search('"path" : "(.*)"', responsetext) 279 | if m: 280 | message += "; " + m.group(0) 281 | 282 | m = re.search('"requestUrl" : "(.*)"', responsetext) 283 | if m: 284 | message += "; " + m.group(0) 285 | 286 | m = re.search(r'"status" : (\d+|".*")', responsetext) 287 | if m: 288 | status = m.group(1) 289 | message += "; " + m.group(0) 290 | else: 291 | status = None 292 | 293 | if status and status.isdigit() and not (int(status) == 200): 294 | error_code = int(status) 295 | elif "OutOfMemoryError" in message: 296 | error_code = 507 297 | else: 298 | error_code = 500 299 | 300 | return error_code, message 301 | -------------------------------------------------------------------------------- /ohsome/response.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Class for ohsome API response""" 5 | 6 | import json 7 | from typing import Optional, Union 8 | 9 | import geopandas as gpd 10 | import pandas as pd 11 | from pandas import DataFrame 12 | 13 | from ohsome.helper import find_groupby_names 14 | 15 | 16 | class OhsomeResponse: 17 | """Contains the response of the request to the ohsome API""" 18 | 19 | def __init__(self, data: dict, url: str = None): 20 | """Initialize the OhsomeResponse class.""" 21 | self.data = data 22 | self.url = url 23 | 24 | def as_dataframe( 25 | self, multi_index: Optional[bool] = True, explode_tags: Optional[tuple] = () 26 | ) -> Union[pd.DataFrame, gpd.GeoDataFrame]: 27 | """ 28 | Converts the ohsome response to a pandas.DataFrame or a geopandas.GeoDataFrame if the 29 | response contains geometries 30 | :param multi_index: If true returns the dataframe with a multi index 31 | :param explode_tags: By default, tags of extracted features are stored in a single dict-column. You can specify 32 | a tuple of tags that should be popped from this column. To disable it completely, pass None. Yet, be aware that 33 | you may get a large but sparse data frame. 34 | :return: pandas.DataFrame or geopandas.GeoDataFrame 35 | """ 36 | if "features" not in self.data.keys(): 37 | return self._as_dataframe(multi_index) 38 | else: 39 | return self._as_geodataframe(multi_index, explode_tags) 40 | 41 | def _as_dataframe(self, multi_index=True) -> pd.DataFrame: 42 | groupby_names = [] 43 | if "result" in self.data.keys(): 44 | result_df = pd.DataFrame().from_records(self.data["result"]) 45 | elif "ratioResult" in self.data.keys(): 46 | result_df = pd.DataFrame().from_records(self.data["ratioResult"]) 47 | elif "groupByResult" in self.data.keys(): 48 | groupby_names = find_groupby_names(self.url) 49 | result_df = self._create_groupby_dataframe( 50 | self.data["groupByResult"], 51 | groupby_names, 52 | ) 53 | elif "groupByBoundaryResult" in self.data.keys(): 54 | groupby_names = find_groupby_names(self.url) 55 | result_df = self._create_groupby_dataframe( 56 | self.data["groupByBoundaryResult"], 57 | groupby_names, 58 | ) 59 | else: 60 | raise TypeError("This result type is not implemented.") 61 | 62 | time_columns = result_df.columns.intersection( 63 | ["timestamp", "fromTimestamp", "toTimestamp"] 64 | ) 65 | result_df[time_columns] = result_df[time_columns].apply(self._format_timestamp) 66 | 67 | if multi_index: 68 | self._set_index(result_df, groupby_names) 69 | 70 | return result_df.sort_index() 71 | 72 | def _as_geodataframe( 73 | self, multi_index: Optional[bool] = True, explode_tags: Optional[tuple] = () 74 | ) -> gpd.GeoDataFrame: 75 | if len(self.data["features"]) == 0: 76 | return gpd.GeoDataFrame( 77 | crs="epsg:4326", 78 | columns=["@osmId", "geometry"] 79 | + ( 80 | list(explode_tags) + ["@other_tags"] 81 | if explode_tags is not None 82 | else [] 83 | ), 84 | ) 85 | 86 | try: 87 | if explode_tags is not None: 88 | for feature in self.data["features"]: 89 | properties = feature["properties"] 90 | tags = {} 91 | new_properties = {k: None for k in explode_tags} 92 | for k in properties.keys(): 93 | if ( 94 | (k.startswith("@")) 95 | or (k == "timestamp") 96 | or (k in explode_tags) 97 | ): 98 | new_properties[k] = properties.get(k) 99 | else: 100 | tags[k] = properties.get(k) 101 | new_properties["@other_tags"] = tags 102 | feature["properties"] = new_properties 103 | 104 | features = gpd.GeoDataFrame().from_features(self.data, crs="epsg:4326") 105 | 106 | except TypeError: 107 | raise TypeError( 108 | "This result type cannot be converted to a GeoPandas GeoDataFrame object." 109 | ) 110 | 111 | time_columns = ["@validFrom", "@validTo", "@snapshotTimestamp", "@timestamp"] 112 | existing_time_columns = features.columns.intersection(time_columns) 113 | features[existing_time_columns] = features[existing_time_columns].apply( 114 | self._format_timestamp 115 | ) 116 | 117 | if multi_index: 118 | index_columns = features.columns.intersection( 119 | ["@osmId"] + time_columns 120 | ).to_list() 121 | features = features.set_index(index_columns) 122 | 123 | return features.sort_index() 124 | 125 | def to_json(self, outfile) -> None: 126 | """ 127 | Write response to json file 128 | :return: 129 | """ 130 | assert outfile.endswith("json"), "Output file must be json" 131 | with open(outfile, "w", encoding="utf-8") as dst: 132 | json.dump(self.data, dst, indent=2, ensure_ascii=False) 133 | 134 | def _set_index(self, result_df, groupby_names) -> None: 135 | """ 136 | Set multi-index based on groupby names and time 137 | :param result_df: 138 | :param groupby_names: 139 | :return: 140 | """ 141 | if "timestamp" in result_df.columns: 142 | result_df.set_index([*groupby_names, "timestamp"], inplace=True) 143 | else: 144 | result_df.set_index( 145 | [*groupby_names, "fromTimestamp", "toTimestamp"], inplace=True 146 | ) 147 | 148 | def _create_groupby_dataframe(self, data, groupby_names) -> DataFrame: 149 | """ 150 | Formats groupby results 151 | :param data: 152 | :param groupby_names: 153 | :return: 154 | """ 155 | keys = list(data[0].keys()) 156 | keys.remove("groupByObject") 157 | record_dfs = [] 158 | if len(groupby_names) == 1: 159 | for record in data: 160 | record_dict = {groupby_names[0]: record["groupByObject"]} 161 | record_result = [{**record_dict, **x} for x in record[keys[0]]] 162 | record_dfs.extend(record_result) 163 | elif len(groupby_names) == 2: 164 | for record in data: 165 | record_dict = { 166 | groupby_names[0]: record["groupByObject"][0], 167 | groupby_names[1]: record["groupByObject"][1], 168 | } 169 | record_result = [{**record_dict, **x} for x in record[keys[0]]] 170 | record_dfs.extend(record_result) 171 | return pd.DataFrame().from_records(record_dfs) 172 | 173 | @staticmethod 174 | def _format_timestamp(dt: pd.Series) -> pd.Series: 175 | """Format timestamp column as datetime.""" 176 | return pd.to_datetime(dt.str.replace("Z", ""), format="ISO8601") 177 | -------------------------------------------------------------------------------- /ohsome/test/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """__description__""" 4 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_check_time_parameter_datetime.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bcircles=0%3A8.678770065307615%2C49.414435400453954%2C100%7C1%3A8.697137832641602%2C49.41007968889129%2C150&time=2018-01-01T00%3A00%3A00%2C2018-01-02T00%3A00%3A00&filter=amenity%3Drestaurant+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '205' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n 24 | \ \"value\" : 0.0\n }, {\n \"timestamp\" : \"2018-01-02T00:00:00Z\",\n 25 | \ \"value\" : 0.0\n } ]\n}" 26 | headers: 27 | Access-Control-Allow-Credentials: 28 | - 'true' 29 | Access-Control-Allow-Headers: 30 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 31 | Access-Control-Allow-Methods: 32 | - POST, GET 33 | Access-Control-Allow-Origin: 34 | - '*' 35 | Access-Control-Max-Age: 36 | - '3600' 37 | Cache-Control: 38 | - no-transform, public, max-age=31556926 39 | Connection: 40 | - Keep-Alive 41 | Content-Encoding: 42 | - gzip 43 | Content-Type: 44 | - application/json 45 | Date: 46 | - Wed, 06 Dec 2023 08:19:12 GMT 47 | Keep-Alive: 48 | - timeout=5, max=100 49 | Server: 50 | - Apache 51 | Strict-Transport-Security: 52 | - max-age=63072000; includeSubdomains; 53 | Transfer-Encoding: 54 | - chunked 55 | vary: 56 | - accept-encoding 57 | status: 58 | code: 200 59 | message: '' 60 | version: 1 61 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_check_time_parameter_list.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bcircles=0%3A8.678770065307615%2C49.414435400453954%2C100%7C1%3A8.697137832641602%2C49.41007968889129%2C150&time=2018-01-01T00%3A00%3A00%2C2018-01-02T00%3A00%3A00%2C2018-01-03T00%3A00%3A00&filter=amenity%3Drestaurant+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '231' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n 24 | \ \"value\" : 0.0\n }, {\n \"timestamp\" : \"2018-01-02T00:00:00Z\",\n 25 | \ \"value\" : 0.0\n }, {\n \"timestamp\" : \"2018-01-03T00:00:00Z\",\n 26 | \ \"value\" : 0.0\n } ]\n}" 27 | headers: 28 | Access-Control-Allow-Credentials: 29 | - 'true' 30 | Access-Control-Allow-Headers: 31 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 32 | Access-Control-Allow-Methods: 33 | - POST, GET 34 | Access-Control-Allow-Origin: 35 | - '*' 36 | Access-Control-Max-Age: 37 | - '3600' 38 | Cache-Control: 39 | - no-transform, public, max-age=31556926 40 | Connection: 41 | - Keep-Alive 42 | Content-Encoding: 43 | - gzip 44 | Content-Type: 45 | - application/json 46 | Date: 47 | - Wed, 06 Dec 2023 08:19:10 GMT 48 | Keep-Alive: 49 | - timeout=5, max=100 50 | Server: 51 | - Apache 52 | Strict-Transport-Security: 53 | - max-age=63072000; includeSubdomains; 54 | Transfer-Encoding: 55 | - chunked 56 | vary: 57 | - accept-encoding 58 | status: 59 | code: 200 60 | message: '' 61 | version: 1 62 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_end_timestamp_as_time_input.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bcircles=0%3A8.678770065307615%2C49.414435400453954%2C100%7C1%3A8.697137832641602%2C49.41007968889129%2C150&time=2023-11-25T13%3A00%3A00&filter=amenity%3Drestaurant+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '179' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2023-11-25T13:00:00Z\",\n 24 | \ \"value\" : 0.0\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:12 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_format_bboxes_dataframe.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=0%3A8.695077896118164%2C49.408711468953854%2C8.699712753295898%2C49.41155955732304%7C1%3A8.677010536193848%2C49.41370947536709%2C8.682074546813965%2C49.416641030041134&time=2010-01-01&filter=amenity%3Drestaurant+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '234' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2010-01-01T00:00:00Z\",\n 24 | \ \"value\" : 0.0\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:18 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_format_bboxes_list.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.67066%2C49.41423%2C8.68177%2C49.4204%7C8.67066%2C49.41423%2C8.68177%2C49.4204&time=2010-01-01&filter=amenity%3Drestaurant+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '146' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2010-01-01T00:00:00Z\",\n 24 | \ \"value\" : 0.0\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:19 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | - request: 60 | body: bboxes=1%3A8.67066%2C49.41423%2C8.68177%2C49.4204%7C2%3A8.67066%2C49.41423%2C8.68177%2C49.4204&time=2010-01-01&filter=amenity%3Drestaurant+and+type%3Anode 61 | headers: 62 | Accept: 63 | - '*/*' 64 | Accept-Encoding: 65 | - gzip, deflate 66 | Connection: 67 | - keep-alive 68 | Content-Length: 69 | - '154' 70 | Content-Type: 71 | - application/x-www-form-urlencoded 72 | user-agent: 73 | - ohsome-py/0.3.0 74 | method: POST 75 | uri: https://api.ohsome.org/v1/elements/count 76 | response: 77 | body: 78 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 79 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 80 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2010-01-01T00:00:00Z\",\n 81 | \ \"value\" : 0.0\n } ]\n}" 82 | headers: 83 | Access-Control-Allow-Credentials: 84 | - 'true' 85 | Access-Control-Allow-Headers: 86 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 87 | Access-Control-Allow-Methods: 88 | - POST, GET 89 | Access-Control-Allow-Origin: 90 | - '*' 91 | Access-Control-Max-Age: 92 | - '3600' 93 | Cache-Control: 94 | - no-transform, public, max-age=31556926 95 | Connection: 96 | - Keep-Alive 97 | Content-Encoding: 98 | - gzip 99 | Content-Type: 100 | - application/json 101 | Date: 102 | - Wed, 06 Dec 2023 08:19:19 GMT 103 | Keep-Alive: 104 | - timeout=5, max=100 105 | Server: 106 | - Apache 107 | Strict-Transport-Security: 108 | - max-age=63072000; includeSubdomains; 109 | Transfer-Encoding: 110 | - chunked 111 | vary: 112 | - accept-encoding 113 | status: 114 | code: 200 115 | message: '' 116 | - request: 117 | body: bboxes=8.67066%2C49.41423%2C8.68177%2C49.4204&time=2010-01-01&filter=amenity%3Drestaurant+and+type%3Anode 118 | headers: 119 | Accept: 120 | - '*/*' 121 | Accept-Encoding: 122 | - gzip, deflate 123 | Connection: 124 | - keep-alive 125 | Content-Length: 126 | - '105' 127 | Content-Type: 128 | - application/x-www-form-urlencoded 129 | user-agent: 130 | - ohsome-py/0.3.0 131 | method: POST 132 | uri: https://api.ohsome.org/v1/elements/count 133 | response: 134 | body: 135 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 136 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 137 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2010-01-01T00:00:00Z\",\n 138 | \ \"value\" : 0.0\n } ]\n}" 139 | headers: 140 | Access-Control-Allow-Credentials: 141 | - 'true' 142 | Access-Control-Allow-Headers: 143 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 144 | Access-Control-Allow-Methods: 145 | - POST, GET 146 | Access-Control-Allow-Origin: 147 | - '*' 148 | Access-Control-Max-Age: 149 | - '3600' 150 | Cache-Control: 151 | - no-transform, public, max-age=31556926 152 | Connection: 153 | - Keep-Alive 154 | Content-Encoding: 155 | - gzip 156 | Content-Type: 157 | - application/json 158 | Date: 159 | - Wed, 06 Dec 2023 08:19:21 GMT 160 | Keep-Alive: 161 | - timeout=5, max=100 162 | Server: 163 | - Apache 164 | Strict-Transport-Security: 165 | - max-age=63072000; includeSubdomains; 166 | Transfer-Encoding: 167 | - chunked 168 | vary: 169 | - accept-encoding 170 | status: 171 | code: 200 172 | message: '' 173 | - request: 174 | body: bboxes=8.67066%2C+49.41423%2C+8.68177%2C+49.4204%7C8.67066%2C+49.41423%2C+8.68177%2C+49.4204&time=2010-01-01&filter=amenity%3Drestaurant+and+type%3Anode 175 | headers: 176 | Accept: 177 | - '*/*' 178 | Accept-Encoding: 179 | - gzip, deflate 180 | Connection: 181 | - keep-alive 182 | Content-Length: 183 | - '152' 184 | Content-Type: 185 | - application/x-www-form-urlencoded 186 | user-agent: 187 | - ohsome-py/0.3.0 188 | method: POST 189 | uri: https://api.ohsome.org/v1/elements/count 190 | response: 191 | body: 192 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 193 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 194 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2010-01-01T00:00:00Z\",\n 195 | \ \"value\" : 0.0\n } ]\n}" 196 | headers: 197 | Access-Control-Allow-Credentials: 198 | - 'true' 199 | Access-Control-Allow-Headers: 200 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 201 | Access-Control-Allow-Methods: 202 | - POST, GET 203 | Access-Control-Allow-Origin: 204 | - '*' 205 | Access-Control-Max-Age: 206 | - '3600' 207 | Cache-Control: 208 | - no-transform, public, max-age=31556926 209 | Connection: 210 | - Keep-Alive 211 | Content-Encoding: 212 | - gzip 213 | Content-Type: 214 | - application/json 215 | Date: 216 | - Wed, 06 Dec 2023 08:19:21 GMT 217 | Keep-Alive: 218 | - timeout=5, max=100 219 | Server: 220 | - Apache 221 | Strict-Transport-Security: 222 | - max-age=63072000; includeSubdomains; 223 | Transfer-Encoding: 224 | - chunked 225 | vary: 226 | - accept-encoding 227 | status: 228 | code: 200 229 | message: '' 230 | - request: 231 | body: bboxes=8.67066%2C+49.41423%2C+8.68177%2C+49.4204&time=2010-01-01&filter=amenity%3Drestaurant+and+type%3Anode 232 | headers: 233 | Accept: 234 | - '*/*' 235 | Accept-Encoding: 236 | - gzip, deflate 237 | Connection: 238 | - keep-alive 239 | Content-Length: 240 | - '108' 241 | Content-Type: 242 | - application/x-www-form-urlencoded 243 | user-agent: 244 | - ohsome-py/0.3.0 245 | method: POST 246 | uri: https://api.ohsome.org/v1/elements/count 247 | response: 248 | body: 249 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 250 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 251 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2010-01-01T00:00:00Z\",\n 252 | \ \"value\" : 0.0\n } ]\n}" 253 | headers: 254 | Access-Control-Allow-Credentials: 255 | - 'true' 256 | Access-Control-Allow-Headers: 257 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 258 | Access-Control-Allow-Methods: 259 | - POST, GET 260 | Access-Control-Allow-Origin: 261 | - '*' 262 | Access-Control-Max-Age: 263 | - '3600' 264 | Cache-Control: 265 | - no-transform, public, max-age=31556926 266 | Connection: 267 | - Keep-Alive 268 | Content-Encoding: 269 | - gzip 270 | Content-Type: 271 | - application/json 272 | Date: 273 | - Wed, 06 Dec 2023 08:19:22 GMT 274 | Keep-Alive: 275 | - timeout=5, max=100 276 | Server: 277 | - Apache 278 | Strict-Transport-Security: 279 | - max-age=63072000; includeSubdomains; 280 | Transfer-Encoding: 281 | - chunked 282 | vary: 283 | - accept-encoding 284 | status: 285 | code: 200 286 | message: '' 287 | version: 1 288 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_format_bcircles_dataframe.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bcircles=0%3A8.695%2C49.41%2C500.0%7C1%3A8.696%2C49.41%2C500.0&time=2018-01-01&filter=amenity%3Drestaurant+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '121' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/boundary 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"0\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n \"value\" 25 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"1\",\n \"result\" : [ 26 | {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n \"value\" : 2.0\n 27 | \ } ]\n } ]\n}" 28 | headers: 29 | Access-Control-Allow-Credentials: 30 | - 'true' 31 | Access-Control-Allow-Headers: 32 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 33 | Access-Control-Allow-Methods: 34 | - POST, GET 35 | Access-Control-Allow-Origin: 36 | - '*' 37 | Access-Control-Max-Age: 38 | - '3600' 39 | Cache-Control: 40 | - no-transform, public, max-age=31556926 41 | Connection: 42 | - Keep-Alive 43 | Content-Encoding: 44 | - gzip 45 | Content-Type: 46 | - application/json 47 | Date: 48 | - Wed, 06 Dec 2023 08:19:13 GMT 49 | Keep-Alive: 50 | - timeout=5, max=100 51 | Server: 52 | - Apache 53 | Strict-Transport-Security: 54 | - max-age=63072000; includeSubdomains; 55 | Transfer-Encoding: 56 | - chunked 57 | vary: 58 | - accept-encoding 59 | status: 60 | code: 200 61 | message: '' 62 | version: 1 63 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_format_bcircles_list.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bcircles=8.695%2C49.41%2C200%7C8.696%2C49.41%2C200&time=2018-01-01&filter=amenity%3Drestaurant+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '110' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n 24 | \ \"value\" : 2.0\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:13 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | - request: 60 | body: bcircles=1%3A8.695%2C49.41%2C200%7C2%3A8.696%2C49.41%2C200&time=2018-01-01&filter=amenity%3Drestaurant+and+type%3Anode 61 | headers: 62 | Accept: 63 | - '*/*' 64 | Accept-Encoding: 65 | - gzip, deflate 66 | Connection: 67 | - keep-alive 68 | Content-Length: 69 | - '118' 70 | Content-Type: 71 | - application/x-www-form-urlencoded 72 | user-agent: 73 | - ohsome-py/0.3.0 74 | method: POST 75 | uri: https://api.ohsome.org/v1/elements/count/groupBy/boundary 76 | response: 77 | body: 78 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 79 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 80 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"1\",\n 81 | \ \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n \"value\" 82 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"2\",\n \"result\" : [ 83 | {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n \"value\" : 1.0\n 84 | \ } ]\n } ]\n}" 85 | headers: 86 | Access-Control-Allow-Credentials: 87 | - 'true' 88 | Access-Control-Allow-Headers: 89 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 90 | Access-Control-Allow-Methods: 91 | - POST, GET 92 | Access-Control-Allow-Origin: 93 | - '*' 94 | Access-Control-Max-Age: 95 | - '3600' 96 | Cache-Control: 97 | - no-transform, public, max-age=31556926 98 | Connection: 99 | - Keep-Alive 100 | Content-Encoding: 101 | - gzip 102 | Content-Type: 103 | - application/json 104 | Date: 105 | - Wed, 06 Dec 2023 08:19:15 GMT 106 | Keep-Alive: 107 | - timeout=5, max=100 108 | Server: 109 | - Apache 110 | Strict-Transport-Security: 111 | - max-age=63072000; includeSubdomains; 112 | Transfer-Encoding: 113 | - chunked 114 | vary: 115 | - accept-encoding 116 | status: 117 | code: 200 118 | message: '' 119 | - request: 120 | body: bcircles=1%3A8.695%2C+49.41%2C+200%7C2%3A8.696%2C+49.41%2C+200&time=2018-01-01&filter=amenity%3Drestaurant+and+type%3Anode 121 | headers: 122 | Accept: 123 | - '*/*' 124 | Accept-Encoding: 125 | - gzip, deflate 126 | Connection: 127 | - keep-alive 128 | Content-Length: 129 | - '122' 130 | Content-Type: 131 | - application/x-www-form-urlencoded 132 | user-agent: 133 | - ohsome-py/0.3.0 134 | method: POST 135 | uri: https://api.ohsome.org/v1/elements/count 136 | response: 137 | body: 138 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 139 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 140 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n 141 | \ \"value\" : 2.0\n } ]\n}" 142 | headers: 143 | Access-Control-Allow-Credentials: 144 | - 'true' 145 | Access-Control-Allow-Headers: 146 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 147 | Access-Control-Allow-Methods: 148 | - POST, GET 149 | Access-Control-Allow-Origin: 150 | - '*' 151 | Access-Control-Max-Age: 152 | - '3600' 153 | Cache-Control: 154 | - no-transform, public, max-age=31556926 155 | Connection: 156 | - Keep-Alive 157 | Content-Encoding: 158 | - gzip 159 | Content-Type: 160 | - application/json 161 | Date: 162 | - Wed, 06 Dec 2023 08:19:15 GMT 163 | Keep-Alive: 164 | - timeout=5, max=100 165 | Server: 166 | - Apache 167 | Strict-Transport-Security: 168 | - max-age=63072000; includeSubdomains; 169 | Transfer-Encoding: 170 | - chunked 171 | vary: 172 | - accept-encoding 173 | status: 174 | code: 200 175 | message: '' 176 | - request: 177 | body: bcircles=1%3A8.695%2C+49.41%2C+200&time=2018-01-01&filter=amenity%3Drestaurant+and+type%3Anode 178 | headers: 179 | Accept: 180 | - '*/*' 181 | Accept-Encoding: 182 | - gzip, deflate 183 | Connection: 184 | - keep-alive 185 | Content-Length: 186 | - '94' 187 | Content-Type: 188 | - application/x-www-form-urlencoded 189 | user-agent: 190 | - ohsome-py/0.3.0 191 | method: POST 192 | uri: https://api.ohsome.org/v1/elements/count 193 | response: 194 | body: 195 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 196 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 197 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n 198 | \ \"value\" : 1.0\n } ]\n}" 199 | headers: 200 | Access-Control-Allow-Credentials: 201 | - 'true' 202 | Access-Control-Allow-Headers: 203 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 204 | Access-Control-Allow-Methods: 205 | - POST, GET 206 | Access-Control-Allow-Origin: 207 | - '*' 208 | Access-Control-Max-Age: 209 | - '3600' 210 | Cache-Control: 211 | - no-transform, public, max-age=31556926 212 | Connection: 213 | - Keep-Alive 214 | Content-Encoding: 215 | - gzip 216 | Content-Type: 217 | - application/json 218 | Date: 219 | - Wed, 06 Dec 2023 08:19:17 GMT 220 | Keep-Alive: 221 | - timeout=5, max=100 222 | Server: 223 | - Apache 224 | Strict-Transport-Security: 225 | - max-age=63072000; includeSubdomains; 226 | Transfer-Encoding: 227 | - chunked 228 | vary: 229 | - accept-encoding 230 | status: 231 | code: 200 232 | message: '' 233 | version: 1 234 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_format_bcircles_pandas.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bcircles=0%3A8.678770065307615%2C49.414435400453954%2C100%7C1%3A8.697137832641602%2C49.41007968889129%2C150&time=2014-01-01%2F2017-01-01%2FP1Y&filter=amenity%3Drestaurant+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '185' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/boundary 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"0\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2014-01-01T00:00:00Z\",\n \"value\" 25 | : 0.0\n }, {\n \"timestamp\" : \"2015-01-01T00:00:00Z\",\n \"value\" 26 | : 0.0\n }, {\n \"timestamp\" : \"2016-01-01T00:00:00Z\",\n \"value\" 27 | : 0.0\n }, {\n \"timestamp\" : \"2017-01-01T00:00:00Z\",\n \"value\" 28 | : 0.0\n } ]\n }, {\n \"groupByObject\" : \"1\",\n \"result\" : [ 29 | {\n \"timestamp\" : \"2014-01-01T00:00:00Z\",\n \"value\" : 0.0\n 30 | \ }, {\n \"timestamp\" : \"2015-01-01T00:00:00Z\",\n \"value\" 31 | : 0.0\n }, {\n \"timestamp\" : \"2016-01-01T00:00:00Z\",\n \"value\" 32 | : 0.0\n }, {\n \"timestamp\" : \"2017-01-01T00:00:00Z\",\n \"value\" 33 | : 1.0\n } ]\n } ]\n}" 34 | headers: 35 | Access-Control-Allow-Credentials: 36 | - 'true' 37 | Access-Control-Allow-Headers: 38 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 39 | Access-Control-Allow-Methods: 40 | - POST, GET 41 | Access-Control-Allow-Origin: 42 | - '*' 43 | Access-Control-Max-Age: 44 | - '3600' 45 | Cache-Control: 46 | - no-transform, public, max-age=31556926 47 | Connection: 48 | - Keep-Alive 49 | Content-Encoding: 50 | - gzip 51 | Content-Type: 52 | - application/json 53 | Date: 54 | - Wed, 06 Dec 2023 08:19:17 GMT 55 | Keep-Alive: 56 | - timeout=5, max=100 57 | Server: 58 | - Apache 59 | Strict-Transport-Security: 60 | - max-age=63072000; includeSubdomains; 61 | Transfer-Encoding: 62 | - chunked 63 | vary: 64 | - accept-encoding 65 | status: 66 | code: 200 67 | message: '' 68 | version: 1 69 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_post_with_endpoint_string.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '109' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/contributions/latest/bbox 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 24 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Polygon\",\n 25 | \ \"coordinates\" : [\n [\n [\n 8.7160632,\n 26 | \ 49.4101846\n ],\n [\n 8.7164024,\n 27 | \ 49.4101846\n ],\n [\n 8.7164024,\n 28 | \ 49.4103952\n ],\n [\n 8.7160632,\n 29 | \ 49.4103952\n ],\n [\n 8.7160632,\n 30 | \ 49.4101846\n ]\n ]\n ]\n },\n \"properties\" 31 | : {\n \"@contributionChangesetId\" : 30687511,\n \"@osmId\" : \"way/24885641\",\n 32 | \ \"@timestamp\" : \"2015-05-01T10:34:11Z\"\n }\n }]\n}\n" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Connection: 45 | - Keep-Alive 46 | Content-Encoding: 47 | - gzip 48 | Content-Type: 49 | - application/geo+json;charset=utf-8 50 | Content-disposition: 51 | - attachment;filename=ohsome.geojson 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:22 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | - request: 68 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm+and+type%3Away 69 | headers: 70 | Accept: 71 | - '*/*' 72 | Accept-Encoding: 73 | - gzip, deflate 74 | Connection: 75 | - keep-alive 76 | Content-Length: 77 | - '109' 78 | Content-Type: 79 | - application/x-www-form-urlencoded 80 | user-agent: 81 | - ohsome-py/0.3.0 82 | method: POST 83 | uri: https://api.ohsome.org/v1/contributions/latest/bbox 84 | response: 85 | body: 86 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 87 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 88 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 89 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Polygon\",\n 90 | \ \"coordinates\" : [\n [\n [\n 8.7160632,\n 91 | \ 49.4101846\n ],\n [\n 8.7164024,\n 92 | \ 49.4101846\n ],\n [\n 8.7164024,\n 93 | \ 49.4103952\n ],\n [\n 8.7160632,\n 94 | \ 49.4103952\n ],\n [\n 8.7160632,\n 95 | \ 49.4101846\n ]\n ]\n ]\n },\n \"properties\" 96 | : {\n \"@contributionChangesetId\" : 30687511,\n \"@osmId\" : \"way/24885641\",\n 97 | \ \"@timestamp\" : \"2015-05-01T10:34:11Z\"\n }\n }]\n}\n" 98 | headers: 99 | Access-Control-Allow-Credentials: 100 | - 'true' 101 | Access-Control-Allow-Headers: 102 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 103 | Access-Control-Allow-Methods: 104 | - POST, GET 105 | Access-Control-Allow-Origin: 106 | - '*' 107 | Access-Control-Max-Age: 108 | - '3600' 109 | Connection: 110 | - Keep-Alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Type: 114 | - application/geo+json;charset=utf-8 115 | Content-disposition: 116 | - attachment;filename=ohsome.geojson 117 | Date: 118 | - Wed, 06 Dec 2023 08:19:24 GMT 119 | Keep-Alive: 120 | - timeout=5, max=100 121 | Server: 122 | - Apache 123 | Strict-Transport-Security: 124 | - max-age=63072000; includeSubdomains; 125 | Transfer-Encoding: 126 | - chunked 127 | vary: 128 | - accept-encoding 129 | status: 130 | code: 200 131 | message: '' 132 | version: 1 133 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_client/test_user_agent.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | user-agent: 12 | - ohsome-py/0.3.0 13 | method: GET 14 | uri: https://api.ohsome.org/v1/metadata 15 | response: 16 | body: 17 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 18 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 19 | : \"1.10.1\",\n \"timeout\" : 600.0,\n \"extractRegion\" : {\n \"spatialExtent\" 20 | : {\n \"type\" : \"Polygon\",\n \"coordinates\" : [ [ [ -180.0, 21 | -90.0 ], [ 180.0, -90.0 ], [ 180.0, 90.0 ], [ -180.0, 90.0 ], [ -180.0, -90.0 22 | ] ] ]\n },\n \"temporalExtent\" : {\n \"fromTimestamp\" : \"2007-10-08T00:00:00Z\",\n 23 | \ \"toTimestamp\" : \"2023-11-25T13:00Z\"\n },\n \"replicationSequenceNumber\" 24 | : 98190\n }\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-cache, no-store, must-revalidate 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:10 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_disable_logging.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.67555%2C49.39885%2C8.69637%2C49.41122&filter=building%3D%2A+and+type%3Away&timeout=0.001 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '97' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/geometry 19 | response: 20 | body: 21 | string: "{\n \"timestamp\" : \"2023-12-06T08:19:25.216152546\",\n \"status\" 22 | : 413,\n \"message\" : \"The given query is too large in respect to the given 23 | timeout. Please use a smaller region and/or coarser time period.\",\n \"requestUrl\" 24 | : \"https://api.ohsome.org/v1/elements/geometry\"\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-cache, no-store, must-revalidate 38 | Connection: 39 | - close 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Content-disposition: 45 | - attachment;filename=ohsome.geojson 46 | Date: 47 | - Wed, 06 Dec 2023 08:19:24 GMT 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 413 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_exception_connection_reset.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bpolys=%7B%22type%22%3A+%22FeatureCollection%22%2C+%22features%22%3A+%5B%7B%22id%22%3A+%220%22%2C+%22type%22%3A+%22Feature%22%2C+%22properties%22%3A+%7B%22id%22%3A+%220%22%7D%2C+%22geometry%22%3A+%7B%22type%22%3A+%22Polygon%22%2C+%22coordinates%22%3A+%5B%5B%5B8.695077896118164%2C+49.408711468953854%5D%2C+%5B8.699712753295898%2C+49.408711468953854%5D%2C+%5B8.699712753295898%2C+49.41155955732304%5D%2C+%5B8.695077896118164%2C+49.41155955732304%5D%2C+%5B8.695077896118164%2C+49.408711468953854%5D%5D%5D%7D%7D%2C+%7B%22id%22%3A+%221%22%2C+%22type%22%3A+%22Feature%22%2C+%22properties%22%3A+%7B%22id%22%3A+%221%22%7D%2C+%22geometry%22%3A+%7B%22type%22%3A+%22Polygon%22%2C+%22coordinates%22%3A+%5B%5B%5B8.677010536193848%2C+49.41370947536709%5D%2C+%5B8.682074546813965%2C+49.41370947536709%5D%2C+%5B8.682074546813965%2C+49.416641030041134%5D%2C+%5B8.677010536193848%2C+49.416641030041134%5D%2C+%5B8.677010536193848%2C+49.41370947536709%5D%5D%5D%7D%7D%5D%7D&time=2018-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '1008' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2018-01-01T00:00:00Z\",\n 24 | \ \"value\" : 0.0\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:32 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_exception_invalid_parameters.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6577%2C49.3958%2C8.7122%2C49.4296&time=2010-01-01%2F2020-01-01%2FP1M&filter=highway%3D%2A+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '113' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/tag 19 | response: 20 | body: 21 | string: "{\n \"timestamp\" : \"2023-12-06T08:19:32.5042067\",\n \"status\" 22 | : 400,\n \"message\" : \"You need to give one groupByKey parameter, if you 23 | want to use groupBy/tag.\",\n \"requestUrl\" : \"https://api.ohsome.org/v1/elements/count/groupBy/tag\"\n}" 24 | headers: 25 | Access-Control-Allow-Credentials: 26 | - 'true' 27 | Access-Control-Allow-Headers: 28 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 29 | Access-Control-Allow-Methods: 30 | - POST, GET 31 | Access-Control-Allow-Origin: 32 | - '*' 33 | Access-Control-Max-Age: 34 | - '3600' 35 | Cache-Control: 36 | - no-cache, no-store, must-revalidate 37 | Connection: 38 | - close 39 | Content-Encoding: 40 | - gzip 41 | Content-Type: 42 | - application/json 43 | Date: 44 | - Wed, 06 Dec 2023 08:19:32 GMT 45 | Server: 46 | - Apache 47 | Strict-Transport-Security: 48 | - max-age=63072000; includeSubdomains; 49 | Transfer-Encoding: 50 | - chunked 51 | vary: 52 | - accept-encoding 53 | status: 54 | code: 400 55 | message: '' 56 | version: 1 57 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_invalid_url.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2018-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '96' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/elements/count 19 | response: 20 | body: 21 | string: "\n\n \n Couldn't find the 22 | requested file\n \n \n 25 | \ \n \n

Couldn't find the requested file

\n\t

\n\t

Sorry 27 | for the inconvenience, it seems like you requested the wrong file or the backend 28 | experiences some problems.

\n \n\n" 29 | headers: 30 | Accept-Ranges: 31 | - bytes 32 | Cache-Control: 33 | - max-age=0, no-store 34 | Connection: 35 | - Upgrade, Keep-Alive 36 | Content-Length: 37 | - '604' 38 | Content-Type: 39 | - text/html 40 | Date: 41 | - Wed, 06 Dec 2023 08:19:24 GMT 42 | ETag: 43 | - '"25c-5c7180820e5fc"' 44 | Keep-Alive: 45 | - timeout=5, max=100 46 | Last-Modified: 47 | - Wed, 14 Jul 2021 16:41:53 GMT 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Upgrade: 53 | - h2 54 | status: 55 | code: 404 56 | message: Not Found 57 | version: 1 58 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_log_bpolys.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bpolys=%7B%22type%22%3A+%22FeatureCollection%22%2C+%22features%22%3A+%5B%7B%22id%22%3A+%220%22%2C+%22type%22%3A+%22Feature%22%2C+%22properties%22%3A+%7B%22id%22%3A+%220%22%7D%2C+%22geometry%22%3A+%7B%22type%22%3A+%22Polygon%22%2C+%22coordinates%22%3A+%5B%5B%5B8.695077896118164%2C+49.408711468953854%5D%2C+%5B8.699712753295898%2C+49.408711468953854%5D%2C+%5B8.699712753295898%2C+49.41155955732304%5D%2C+%5B8.695077896118164%2C+49.41155955732304%5D%2C+%5B8.695077896118164%2C+49.408711468953854%5D%5D%5D%7D%7D%2C+%7B%22id%22%3A+%221%22%2C+%22type%22%3A+%22Feature%22%2C+%22properties%22%3A+%7B%22id%22%3A+%221%22%7D%2C+%22geometry%22%3A+%7B%22type%22%3A+%22Polygon%22%2C+%22coordinates%22%3A+%5B%5B%5B8.677010536193848%2C+49.41370947536709%5D%2C+%5B8.682074546813965%2C+49.41370947536709%5D%2C+%5B8.682074546813965%2C+49.416641030041134%5D%2C+%5B8.677010536193848%2C+49.416641030041134%5D%2C+%5B8.677010536193848%2C+49.41370947536709%5D%5D%5D%7D%7D%5D%7D&time=2018-01-01&filter=amenity%3Drestaurant+and+type%3Anode&timeout=0.001 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '1027' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"timestamp\" : \"2023-12-06T08:19:25.726901274\",\n \"status\" 22 | : 413,\n \"message\" : \"The given query is too large in respect to the given 23 | timeout. Please use a smaller region and/or coarser time period.\",\n \"requestUrl\" 24 | : \"https://api.ohsome.org/v1/elements/count\"\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-cache, no-store, must-revalidate 38 | Connection: 39 | - close 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:25 GMT 46 | Server: 47 | - Apache 48 | Strict-Transport-Security: 49 | - max-age=63072000; includeSubdomains; 50 | Transfer-Encoding: 51 | - chunked 52 | vary: 53 | - accept-encoding 54 | status: 55 | code: 413 56 | message: '' 57 | version: 1 58 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_log_curl.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.67555%2C49.39885%2C8.69637%2C49.41122&timeout=0.001 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '60' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"timestamp\" : \"2023-12-06T08:19:26.004501208\",\n \"status\" 22 | : 413,\n \"message\" : \"The given query is too large in respect to the given 23 | timeout. Please use a smaller region and/or coarser time period.\",\n \"requestUrl\" 24 | : \"https://api.ohsome.org/v1/elements/count\"\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-cache, no-store, must-revalidate 38 | Connection: 39 | - close 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:25 GMT 46 | Server: 47 | - Apache 48 | Strict-Transport-Security: 49 | - max-age=63072000; includeSubdomains; 50 | Transfer-Encoding: 51 | - chunked 52 | vary: 53 | - accept-encoding 54 | status: 55 | code: 413 56 | message: '' 57 | version: 1 58 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_exceptions/test_timeout_error.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.67066%2C49.41423%2C8.68177%2C49.4204&time=2010-01-01%2F2011-01-01%2FP1Y&filter=building%3D%2A+and+type%3Away&timeout=0 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '127' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/geometry 19 | response: 20 | body: 21 | string: "{\n \"timestamp\" : \"2023-12-06T08:19:24.649051175\",\n \"status\" 22 | : 413,\n \"message\" : \"The given query is too large in respect to the given 23 | timeout. Please use a smaller region and/or coarser time period.\",\n \"requestUrl\" 24 | : \"https://api.ohsome.org/v1/elements/geometry\"\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-cache, no-store, must-revalidate 38 | Connection: 39 | - close 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Content-disposition: 45 | - attachment;filename=ohsome.geojson 46 | Date: 47 | - Wed, 06 Dec 2023 08:19:24 GMT 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 413 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_contributions_centroid.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '109' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/contributions/centroid 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 24 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Point\",\n 25 | \ \"coordinates\" : [\n 8.716229,\n 49.4102928\n ]\n 26 | \ },\n \"properties\" : {\n \"@contributionChangesetId\" : 30687511,\n 27 | \ \"@osmId\" : \"way/24885641\",\n \"@timestamp\" : \"2015-05-01T10:34:11Z\"\n 28 | \ }\n }]\n}\n" 29 | headers: 30 | Access-Control-Allow-Credentials: 31 | - 'true' 32 | Access-Control-Allow-Headers: 33 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 34 | Access-Control-Allow-Methods: 35 | - POST, GET 36 | Access-Control-Allow-Origin: 37 | - '*' 38 | Access-Control-Max-Age: 39 | - '3600' 40 | Connection: 41 | - Keep-Alive 42 | Content-Encoding: 43 | - gzip 44 | Content-Type: 45 | - application/geo+json;charset=utf-8 46 | Content-disposition: 47 | - attachment;filename=ohsome.geojson 48 | Date: 49 | - Wed, 06 Dec 2023 08:19:45 GMT 50 | Keep-Alive: 51 | - timeout=5, max=100 52 | Server: 53 | - Apache 54 | Strict-Transport-Security: 55 | - max-age=63072000; includeSubdomains; 56 | Transfer-Encoding: 57 | - chunked 58 | vary: 59 | - accept-encoding 60 | status: 61 | code: 200 62 | message: '' 63 | version: 1 64 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_contributions_count_density_groupbyboundary.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '109' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/contributions/count/density/groupBy/boundary 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"boundary1\",\n 24 | \ \"result\" : [ {\n \"fromTimestamp\" : \"2015-01-01T00:00:00Z\",\n 25 | \ \"toTimestamp\" : \"2016-01-01T00:00:00Z\",\n \"value\" : 16.32\n 26 | \ } ]\n } ]\n}" 27 | headers: 28 | Access-Control-Allow-Credentials: 29 | - 'true' 30 | Access-Control-Allow-Headers: 31 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 32 | Access-Control-Allow-Methods: 33 | - POST, GET 34 | Access-Control-Allow-Origin: 35 | - '*' 36 | Access-Control-Max-Age: 37 | - '3600' 38 | Cache-Control: 39 | - no-transform, public, max-age=31556926 40 | Connection: 41 | - Keep-Alive 42 | Content-Encoding: 43 | - gzip 44 | Content-Type: 45 | - application/json 46 | Date: 47 | - Wed, 06 Dec 2023 08:19:45 GMT 48 | Keep-Alive: 49 | - timeout=5, max=100 50 | Server: 51 | - Apache 52 | Strict-Transport-Security: 53 | - max-age=63072000; includeSubdomains; 54 | Transfer-Encoding: 55 | - chunked 56 | vary: 57 | - accept-encoding 58 | status: 59 | code: 200 60 | message: '' 61 | version: 1 62 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_contributions_latest.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '109' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/contributions/latest/bbox 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 24 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Polygon\",\n 25 | \ \"coordinates\" : [\n [\n [\n 8.7160632,\n 26 | \ 49.4101846\n ],\n [\n 8.7164024,\n 27 | \ 49.4101846\n ],\n [\n 8.7164024,\n 28 | \ 49.4103952\n ],\n [\n 8.7160632,\n 29 | \ 49.4103952\n ],\n [\n 8.7160632,\n 30 | \ 49.4101846\n ]\n ]\n ]\n },\n \"properties\" 31 | : {\n \"@contributionChangesetId\" : 30687511,\n \"@osmId\" : \"way/24885641\",\n 32 | \ \"@timestamp\" : \"2015-05-01T10:34:11Z\"\n }\n }]\n}\n" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Connection: 45 | - Keep-Alive 46 | Content-Encoding: 47 | - gzip 48 | Content-Type: 49 | - application/geo+json;charset=utf-8 50 | Content-disposition: 51 | - attachment;filename=ohsome.geojson 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:47 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | version: 1 68 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elementsFullHistory_geometry.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '109' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elementsFullHistory/centroid 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 24 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Point\",\n 25 | \ \"coordinates\" : [\n 8.716229,\n 49.4102928\n ]\n 26 | \ },\n \"properties\" : {\n \"@osmId\" : \"way/24885641\",\n \"@validFrom\" 27 | : \"2015-01-01T00:00:00Z\",\n \"@validTo\" : \"2015-05-01T10:34:11Z\"\n 28 | \ }\n }, {\n \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" 29 | : \"Point\",\n \"coordinates\" : [\n 8.716229,\n 49.4102928\n 30 | \ ]\n },\n \"properties\" : {\n \"@osmId\" : \"way/24885641\",\n 31 | \ \"@validFrom\" : \"2015-05-01T10:34:11Z\",\n \"@validTo\" : \"2016-01-01T00:00:00Z\"\n 32 | \ }\n }]\n}\n" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Connection: 45 | - Keep-Alive 46 | Content-Encoding: 47 | - gzip 48 | Content-Type: 49 | - application/geo+json;charset=utf-8 50 | Content-disposition: 51 | - attachment;filename=ohsome.geojson 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:44 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | version: 1 68 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10&filter=amenity%3Dcafe+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '99' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n 24 | \ \"value\" : 12.0\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:33 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_groupby_boundary.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=1%3A8.6933%2C49.40893%2C8.69797%2C49.41106%7C2%3A8.6887%2C49.41325%2C8.69462%2C49.4166&time=2019-12-10&filter=amenity%3Dcafe+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '147' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/boundary 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"1\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 25 | : 12.0\n } ]\n }, {\n \"groupByObject\" : \"2\",\n \"result\" : 26 | [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 11.0\n 27 | \ } ]\n } ]\n}" 28 | headers: 29 | Access-Control-Allow-Credentials: 30 | - 'true' 31 | Access-Control-Allow-Headers: 32 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 33 | Access-Control-Allow-Methods: 34 | - POST, GET 35 | Access-Control-Allow-Origin: 36 | - '*' 37 | Access-Control-Max-Age: 38 | - '3600' 39 | Cache-Control: 40 | - no-transform, public, max-age=31556926 41 | Connection: 42 | - Keep-Alive 43 | Content-Encoding: 44 | - gzip 45 | Content-Type: 46 | - application/json 47 | Date: 48 | - Wed, 06 Dec 2023 08:19:38 GMT 49 | Keep-Alive: 50 | - timeout=5, max=100 51 | Server: 52 | - Apache 53 | Strict-Transport-Security: 54 | - max-age=63072000; includeSubdomains; 55 | Transfer-Encoding: 56 | - chunked 57 | vary: 58 | - accept-encoding 59 | status: 60 | code: 200 61 | message: '' 62 | version: 1 63 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_groupby_boundary_groupby_tag.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106%7C8.6887%2C49.41325%2C8.69462%2C49.4166&time=2019-12-10&filter=amenity%3Dcafe+and+type%3Anode&groupByKey=amenity 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '158' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/boundary/groupBy/tag 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : [ \"boundary1\", 24 | \"amenity=cafe\" ],\n \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n 25 | \ \"value\" : 12.0\n } ]\n }, {\n \"groupByObject\" : [ \"boundary2\", 26 | \"amenity=cafe\" ],\n \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n 27 | \ \"value\" : 11.0\n } ]\n } ]\n}" 28 | headers: 29 | Access-Control-Allow-Credentials: 30 | - 'true' 31 | Access-Control-Allow-Headers: 32 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 33 | Access-Control-Allow-Methods: 34 | - POST, GET 35 | Access-Control-Allow-Origin: 36 | - '*' 37 | Access-Control-Max-Age: 38 | - '3600' 39 | Cache-Control: 40 | - no-transform, public, max-age=31556926 41 | Connection: 42 | - Keep-Alive 43 | Content-Encoding: 44 | - gzip 45 | Content-Type: 46 | - application/json 47 | Date: 48 | - Wed, 06 Dec 2023 08:19:40 GMT 49 | Keep-Alive: 50 | - timeout=5, max=100 51 | Server: 52 | - Apache 53 | Strict-Transport-Security: 54 | - max-age=63072000; includeSubdomains; 55 | Transfer-Encoding: 56 | - chunked 57 | vary: 58 | - accept-encoding 59 | status: 60 | code: 200 61 | message: '' 62 | version: 1 63 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_groupby_key.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10%2C2019-12-11&filter=type%3Anode&groupByKeys=amenity%2Cshop 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '120' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/key 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"remainder\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 25 | : 131.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 26 | : 131.0\n } ]\n }, {\n \"groupByObject\" : \"amenity\",\n \"result\" 27 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 28 | 83.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 29 | : 83.0\n } ]\n }, {\n \"groupByObject\" : \"shop\",\n \"result\" 30 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 31 | 89.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 32 | : 89.0\n } ]\n } ]\n}" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Cache-Control: 45 | - no-transform, public, max-age=31556926 46 | Connection: 47 | - Keep-Alive 48 | Content-Encoding: 49 | - gzip 50 | Content-Type: 51 | - application/json 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:35 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | version: 1 68 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_groupby_tag.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10%2C2019-12-11&filter=type%3Anode&groupByKey=amenity 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '112' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/tag 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"remainder\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 25 | : 216.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 26 | : 216.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=parking\",\n \"result\" 27 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 28 | 3.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 29 | : 3.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=bench\",\n \"result\" 30 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 31 | 10.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 32 | : 10.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=school\",\n \"result\" 33 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 34 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 35 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=restaurant\",\n 36 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 37 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 38 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=waste_basket\",\n 39 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 40 | : 10.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 41 | : 10.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=fast_food\",\n 42 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 43 | : 6.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 44 | : 6.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=cafe\",\n \"result\" 45 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 46 | 12.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 47 | : 12.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=bicycle_parking\",\n 48 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 49 | : 7.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 50 | : 7.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=bank\",\n \"result\" 51 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 52 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 53 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=toilets\",\n \"result\" 54 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 55 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 56 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=pharmacy\",\n \"result\" 57 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 58 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 59 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=kindergarten\",\n 60 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 61 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 62 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=post_box\",\n \"result\" 63 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 64 | 3.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 65 | : 3.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=vending_machine\",\n 66 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 67 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 68 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=atm\",\n \"result\" 69 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 70 | 6.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 71 | : 6.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=clinic\",\n \"result\" 72 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 73 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 74 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=doctors\",\n \"result\" 75 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 76 | 3.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 77 | : 3.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=parking_entrance\",\n 78 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 79 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 80 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=fountain\",\n \"result\" 81 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 82 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 83 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=public_building\",\n 84 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 85 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 86 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=telephone\",\n \"result\" 87 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 88 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 89 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=dentist\",\n \"result\" 90 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 91 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 92 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=ice_cream\",\n \"result\" 93 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 94 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 95 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=taxi\",\n \"result\" 96 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 97 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 98 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=nightclub\",\n \"result\" 99 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 100 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 101 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=clock\",\n \"result\" 102 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 103 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 104 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=public_bookcase\",\n 105 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 106 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 107 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=photo_booth\",\n 108 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 109 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 110 | : 1.0\n } ]\n } ]\n}" 111 | headers: 112 | Access-Control-Allow-Credentials: 113 | - 'true' 114 | Access-Control-Allow-Headers: 115 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 116 | Access-Control-Allow-Methods: 117 | - POST, GET 118 | Access-Control-Allow-Origin: 119 | - '*' 120 | Access-Control-Max-Age: 121 | - '3600' 122 | Cache-Control: 123 | - no-transform, public, max-age=31556926 124 | Connection: 125 | - Keep-Alive 126 | Content-Encoding: 127 | - gzip 128 | Content-Type: 129 | - application/json 130 | Date: 131 | - Wed, 06 Dec 2023 08:19:36 GMT 132 | Keep-Alive: 133 | - timeout=5, max=100 134 | Server: 135 | - Apache 136 | Strict-Transport-Security: 137 | - max-age=63072000; includeSubdomains; 138 | Transfer-Encoding: 139 | - chunked 140 | vary: 141 | - accept-encoding 142 | status: 143 | code: 200 144 | message: '' 145 | version: 1 146 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_groupby_type.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10%2C2019-12-11&filter=amenity%3D%2A+and+%28type%3Away+or+type%3Anode%29 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '131' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/type 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"node\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 25 | : 83.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 26 | : 83.0\n } ]\n }, {\n \"groupByObject\" : \"way\",\n \"result\" 27 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 28 | 9.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 29 | : 9.0\n } ]\n }, {\n \"groupByObject\" : \"relation\",\n \"result\" 30 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 31 | 0.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 32 | : 0.0\n } ]\n } ]\n}" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Cache-Control: 45 | - no-transform, public, max-age=31556926 46 | Connection: 47 | - Keep-Alive 48 | Content-Encoding: 49 | - gzip 50 | Content-Type: 51 | - application/json 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:38 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | version: 1 68 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_ratio.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10&filter=amenity%3D%2A+and+type%3Anode&filter2=amenity%3Dcafe+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '137' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/ratio 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"ratioResult\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n 24 | \ \"value\" : 83.0,\n \"value2\" : 12.0,\n \"ratio\" : 0.144578\n 25 | \ } ]\n}" 26 | headers: 27 | Access-Control-Allow-Credentials: 28 | - 'true' 29 | Access-Control-Allow-Headers: 30 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 31 | Access-Control-Allow-Methods: 32 | - POST, GET 33 | Access-Control-Allow-Origin: 34 | - '*' 35 | Access-Control-Max-Age: 36 | - '3600' 37 | Cache-Control: 38 | - no-transform, public, max-age=31556926 39 | Connection: 40 | - Keep-Alive 41 | Content-Encoding: 42 | - gzip 43 | Content-Type: 44 | - application/json 45 | Date: 46 | - Wed, 06 Dec 2023 08:19:40 GMT 47 | Keep-Alive: 48 | - timeout=5, max=100 49 | Server: 50 | - Apache 51 | Strict-Transport-Security: 52 | - max-age=63072000; includeSubdomains; 53 | Transfer-Encoding: 54 | - chunked 55 | vary: 56 | - accept-encoding 57 | status: 58 | code: 200 59 | message: '' 60 | version: 1 61 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_count_ratio_groupby_boundary.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=A%3A8.6933%2C49.40893%2C8.69797%2C49.41106%7CB%3A8.6887%2C49.41325%2C8.69462%2C49.4166&time=2019-12-10%2C+2020-07-23&filter=amenity%3Dhotel+and+type%3Anode&filter2=amenity%3Dcafe+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '201' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/ratio/groupBy/boundary 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByBoundaryResult\" : [ {\n \"groupByObject\" : 24 | \"A\",\n \"ratioResult\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00\",\n 25 | \ \"value\" : 0.0,\n \"value2\" : 12.0,\n \"ratio\" : \"Infinity\"\n 26 | \ }, {\n \"timestamp\" : \"2020-07-23T00:00:00\",\n \"value\" 27 | : 0.0,\n \"value2\" : 10.0,\n \"ratio\" : \"Infinity\"\n } ]\n 28 | \ }, {\n \"groupByObject\" : \"B\",\n \"ratioResult\" : [ {\n \"timestamp\" 29 | : \"2019-12-10T00:00:00\",\n \"value\" : 0.0,\n \"value2\" : 11.0,\n 30 | \ \"ratio\" : \"Infinity\"\n }, {\n \"timestamp\" : \"2020-07-23T00:00:00\",\n 31 | \ \"value\" : 0.0,\n \"value2\" : 12.0,\n \"ratio\" : \"Infinity\"\n 32 | \ } ]\n } ]\n}" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Cache-Control: 45 | - no-transform, public, max-age=31556926 46 | Connection: 47 | - Keep-Alive 48 | Content-Encoding: 49 | - gzip 50 | Content-Type: 51 | - application/json 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:41 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | version: 1 68 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_density.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10&filter=amenity%3Dcafe+and+type%3Anode 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '99' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/density 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n 24 | \ \"value\" : 149.47\n } ]\n}" 25 | headers: 26 | Access-Control-Allow-Credentials: 27 | - 'true' 28 | Access-Control-Allow-Headers: 29 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 30 | Access-Control-Allow-Methods: 31 | - POST, GET 32 | Access-Control-Allow-Origin: 33 | - '*' 34 | Access-Control-Max-Age: 35 | - '3600' 36 | Cache-Control: 37 | - no-transform, public, max-age=31556926 38 | Connection: 39 | - Keep-Alive 40 | Content-Encoding: 41 | - gzip 42 | Content-Type: 43 | - application/json 44 | Date: 45 | - Wed, 06 Dec 2023 08:19:33 GMT 46 | Keep-Alive: 47 | - timeout=5, max=100 48 | Server: 49 | - Apache 50 | Strict-Transport-Security: 51 | - max-age=63072000; includeSubdomains; 52 | Transfer-Encoding: 53 | - chunked 54 | vary: 55 | - accept-encoding 56 | status: 57 | code: 200 58 | message: '' 59 | version: 1 60 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_elements_geometry.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2016-01-01&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '96' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/geometry 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 24 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Polygon\",\n 25 | \ \"coordinates\" : [\n [\n [\n 8.7160632,\n 26 | \ 49.4102899\n ],\n [\n 8.7160749,\n 27 | \ 49.4103121\n ],\n [\n 8.7160827,\n 28 | \ 49.4103235\n ],\n [\n 8.7160963,\n 29 | \ 49.4103374\n ],\n [\n 8.716121,\n 30 | \ 49.4103549\n ],\n [\n 8.7161392,\n 31 | \ 49.4103691\n ],\n [\n 8.7161626,\n 32 | \ 49.4103819\n ],\n [\n 8.716186,\n 33 | \ 49.4103894\n ],\n [\n 8.716225,\n 34 | \ 49.4103952\n ],\n [\n 8.7162679,\n 35 | \ 49.4103926\n ],\n [\n 8.7162893,\n 36 | \ 49.4103882\n ],\n [\n 8.7163176,\n 37 | \ 49.410378\n ],\n [\n 8.7163507,\n 38 | \ 49.4103615\n ],\n [\n 8.7163829,\n 39 | \ 49.4103317\n ],\n [\n 8.7163975,\n 40 | \ 49.4103057\n ],\n [\n 8.7164024,\n 41 | \ 49.4102791\n ],\n [\n 8.7164004,\n 42 | \ 49.4102506\n ],\n [\n 8.7163868,\n 43 | \ 49.4102277\n ],\n [\n 8.7162815,\n 44 | \ 49.4102258\n ],\n [\n 8.7162659,\n 45 | \ 49.4102189\n ],\n [\n 8.7162503,\n 46 | \ 49.4102144\n ],\n [\n 8.7162289,\n 47 | \ 49.4102106\n ],\n [\n 8.7162113,\n 48 | \ 49.4102093\n ],\n [\n 8.7161987,\n 49 | \ 49.4101992\n ],\n [\n 8.7161665,\n 50 | \ 49.4101992\n ],\n [\n 8.7161519,\n 51 | \ 49.4101954\n ],\n [\n 8.7161343,\n 52 | \ 49.4101846\n ],\n [\n 8.7161119,\n 53 | \ 49.4101967\n ],\n [\n 8.7160934,\n 54 | \ 49.4102119\n ],\n [\n 8.7160807,\n 55 | \ 49.4102277\n ],\n [\n 8.7160719,\n 56 | \ 49.4102449\n ],\n [\n 8.7160671,\n 57 | \ 49.4102594\n ],\n [\n 8.7160641,\n 58 | \ 49.4102753\n ],\n [\n 8.7160632,\n 59 | \ 49.4102899\n ]\n ]\n ]\n },\n \"properties\" 60 | : {\n \"@osmId\" : \"way/24885641\",\n \"@snapshotTimestamp\" : 61 | \"2016-01-01T00:00:00Z\"\n }\n }]\n}\n" 62 | headers: 63 | Access-Control-Allow-Credentials: 64 | - 'true' 65 | Access-Control-Allow-Headers: 66 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 67 | Access-Control-Allow-Methods: 68 | - POST, GET 69 | Access-Control-Allow-Origin: 70 | - '*' 71 | Access-Control-Max-Age: 72 | - '3600' 73 | Connection: 74 | - Keep-Alive 75 | Content-Encoding: 76 | - gzip 77 | Content-Type: 78 | - application/geo+json;charset=utf-8 79 | Content-disposition: 80 | - attachment;filename=ohsome.geojson 81 | Date: 82 | - Wed, 06 Dec 2023 08:19:41 GMT 83 | Keep-Alive: 84 | - timeout=5, max=100 85 | Server: 86 | - Apache 87 | Strict-Transport-Security: 88 | - max-age=63072000; includeSubdomains; 89 | Transfer-Encoding: 90 | - chunked 91 | vary: 92 | - accept-encoding 93 | status: 94 | code: 200 95 | message: '' 96 | version: 1 97 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_empty_geodataframe.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2C2016-01-01&filter=name%3DKrautturm1+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '110' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/bbox 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : []\n}\n" 24 | headers: 25 | Access-Control-Allow-Credentials: 26 | - 'true' 27 | Access-Control-Allow-Headers: 28 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 29 | Access-Control-Allow-Methods: 30 | - POST, GET 31 | Access-Control-Allow-Origin: 32 | - '*' 33 | Access-Control-Max-Age: 34 | - '3600' 35 | Connection: 36 | - Keep-Alive 37 | Content-Encoding: 38 | - gzip 39 | Content-Type: 40 | - application/geo+json;charset=utf-8 41 | Content-disposition: 42 | - attachment;filename=ohsome.geojson 43 | Date: 44 | - Wed, 06 Dec 2023 08:19:47 GMT 45 | Keep-Alive: 46 | - timeout=5, max=100 47 | Server: 48 | - Apache 49 | Strict-Transport-Security: 50 | - max-age=63072000; includeSubdomains; 51 | Transfer-Encoding: 52 | - chunked 53 | vary: 54 | - accept-encoding 55 | status: 56 | code: 200 57 | message: '' 58 | version: 1 59 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_extra_tags_argument.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2016-01-01&filter=name%3DKrautturm+and+type%3Away&properties=tags%2Cmetadata 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '123' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/geometry 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"type\" : \"FeatureCollection\",\n \"features\" : [{\n 24 | \ \"type\" : \"Feature\",\n \"geometry\" : {\n \"type\" : \"Polygon\",\n 25 | \ \"coordinates\" : [\n [\n [\n 8.7160632,\n 26 | \ 49.4102899\n ],\n [\n 8.7160749,\n 27 | \ 49.4103121\n ],\n [\n 8.7160827,\n 28 | \ 49.4103235\n ],\n [\n 8.7160963,\n 29 | \ 49.4103374\n ],\n [\n 8.716121,\n 30 | \ 49.4103549\n ],\n [\n 8.7161392,\n 31 | \ 49.4103691\n ],\n [\n 8.7161626,\n 32 | \ 49.4103819\n ],\n [\n 8.716186,\n 33 | \ 49.4103894\n ],\n [\n 8.716225,\n 34 | \ 49.4103952\n ],\n [\n 8.7162679,\n 35 | \ 49.4103926\n ],\n [\n 8.7162893,\n 36 | \ 49.4103882\n ],\n [\n 8.7163176,\n 37 | \ 49.410378\n ],\n [\n 8.7163507,\n 38 | \ 49.4103615\n ],\n [\n 8.7163829,\n 39 | \ 49.4103317\n ],\n [\n 8.7163975,\n 40 | \ 49.4103057\n ],\n [\n 8.7164024,\n 41 | \ 49.4102791\n ],\n [\n 8.7164004,\n 42 | \ 49.4102506\n ],\n [\n 8.7163868,\n 43 | \ 49.4102277\n ],\n [\n 8.7162815,\n 44 | \ 49.4102258\n ],\n [\n 8.7162659,\n 45 | \ 49.4102189\n ],\n [\n 8.7162503,\n 46 | \ 49.4102144\n ],\n [\n 8.7162289,\n 47 | \ 49.4102106\n ],\n [\n 8.7162113,\n 48 | \ 49.4102093\n ],\n [\n 8.7161987,\n 49 | \ 49.4101992\n ],\n [\n 8.7161665,\n 50 | \ 49.4101992\n ],\n [\n 8.7161519,\n 51 | \ 49.4101954\n ],\n [\n 8.7161343,\n 52 | \ 49.4101846\n ],\n [\n 8.7161119,\n 53 | \ 49.4101967\n ],\n [\n 8.7160934,\n 54 | \ 49.4102119\n ],\n [\n 8.7160807,\n 55 | \ 49.4102277\n ],\n [\n 8.7160719,\n 56 | \ 49.4102449\n ],\n [\n 8.7160671,\n 57 | \ 49.4102594\n ],\n [\n 8.7160641,\n 58 | \ 49.4102753\n ],\n [\n 8.7160632,\n 59 | \ 49.4102899\n ]\n ]\n ]\n },\n \"properties\" 60 | : {\n \"@changesetId\" : 30687511,\n \"@lastEdit\" : \"2015-05-01T10:33:22Z\",\n 61 | \ \"@osmId\" : \"way/24885641\",\n \"@osmType\" : \"way\",\n \"@snapshotTimestamp\" 62 | : \"2016-01-01T00:00:00Z\",\n \"@version\" : 4,\n \"building\" : 63 | \"yes\",\n \"name\" : \"Krautturm\"\n }\n }]\n}\n" 64 | headers: 65 | Access-Control-Allow-Credentials: 66 | - 'true' 67 | Access-Control-Allow-Headers: 68 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 69 | Access-Control-Allow-Methods: 70 | - POST, GET 71 | Access-Control-Allow-Origin: 72 | - '*' 73 | Access-Control-Max-Age: 74 | - '3600' 75 | Connection: 76 | - Keep-Alive 77 | Content-Encoding: 78 | - gzip 79 | Content-Type: 80 | - application/geo+json;charset=utf-8 81 | Content-disposition: 82 | - attachment;filename=ohsome.geojson 83 | Date: 84 | - Wed, 06 Dec 2023 08:19:43 GMT 85 | Keep-Alive: 86 | - timeout=5, max=100 87 | Server: 88 | - Apache 89 | Strict-Transport-Security: 90 | - max-age=63072000; includeSubdomains; 91 | Transfer-Encoding: 92 | - chunked 93 | vary: 94 | - accept-encoding 95 | status: 96 | code: 200 97 | message: '' 98 | version: 1 99 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_multi_index_false.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10%2C2019-12-11&filter=type%3Anode&groupByKey=amenity 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '112' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/tag 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"remainder\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 25 | : 216.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 26 | : 216.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=parking\",\n \"result\" 27 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 28 | 3.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 29 | : 3.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=bench\",\n \"result\" 30 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 31 | 10.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 32 | : 10.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=school\",\n \"result\" 33 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 34 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 35 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=restaurant\",\n 36 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 37 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 38 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=waste_basket\",\n 39 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 40 | : 10.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 41 | : 10.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=fast_food\",\n 42 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 43 | : 6.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 44 | : 6.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=cafe\",\n \"result\" 45 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 46 | 12.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 47 | : 12.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=bicycle_parking\",\n 48 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 49 | : 7.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 50 | : 7.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=bank\",\n \"result\" 51 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 52 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 53 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=toilets\",\n \"result\" 54 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 55 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 56 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=pharmacy\",\n \"result\" 57 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 58 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 59 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=kindergarten\",\n 60 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 61 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 62 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=post_box\",\n \"result\" 63 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 64 | 3.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 65 | : 3.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=vending_machine\",\n 66 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 67 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 68 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=atm\",\n \"result\" 69 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 70 | 6.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 71 | : 6.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=clinic\",\n \"result\" 72 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 73 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 74 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=doctors\",\n \"result\" 75 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 76 | 3.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 77 | : 3.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=parking_entrance\",\n 78 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 79 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 80 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=fountain\",\n \"result\" 81 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 82 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 83 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=public_building\",\n 84 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 85 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 86 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=telephone\",\n \"result\" 87 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 88 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 89 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=dentist\",\n \"result\" 90 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 91 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 92 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=ice_cream\",\n \"result\" 93 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 94 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 95 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=taxi\",\n \"result\" 96 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 97 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 98 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=nightclub\",\n \"result\" 99 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 100 | 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 101 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=clock\",\n \"result\" 102 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 103 | 2.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 104 | : 2.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=public_bookcase\",\n 105 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 106 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 107 | : 1.0\n } ]\n }, {\n \"groupByObject\" : \"amenity=photo_booth\",\n 108 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 109 | : 1.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 110 | : 1.0\n } ]\n } ]\n}" 111 | headers: 112 | Access-Control-Allow-Credentials: 113 | - 'true' 114 | Access-Control-Allow-Headers: 115 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 116 | Access-Control-Allow-Methods: 117 | - POST, GET 118 | Access-Control-Allow-Origin: 119 | - '*' 120 | Access-Control-Max-Age: 121 | - '3600' 122 | Cache-Control: 123 | - no-transform, public, max-age=31556926 124 | Connection: 125 | - Keep-Alive 126 | Content-Encoding: 127 | - gzip 128 | Content-Type: 129 | - application/json 130 | Date: 131 | - Wed, 06 Dec 2023 08:19:36 GMT 132 | Keep-Alive: 133 | - timeout=5, max=100 134 | Server: 135 | - Apache 136 | Strict-Transport-Security: 137 | - max-age=63072000; includeSubdomains; 138 | Transfer-Encoding: 139 | - chunked 140 | vary: 141 | - accept-encoding 142 | status: 143 | code: 200 144 | message: '' 145 | version: 1 146 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_not_implemented_query.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.6933%2C49.40893%2C8.69797%2C49.41106&time=2019-12-10%2C2019-12-11&filter=type%3Anode&groupByKeys=amenity%2Cshop 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '120' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/elements/count/groupBy/key 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"groupByResult\" : [ {\n \"groupByObject\" : \"remainder\",\n 24 | \ \"result\" : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" 25 | : 131.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 26 | : 131.0\n } ]\n }, {\n \"groupByObject\" : \"amenity\",\n \"result\" 27 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 28 | 83.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 29 | : 83.0\n } ]\n }, {\n \"groupByObject\" : \"shop\",\n \"result\" 30 | : [ {\n \"timestamp\" : \"2019-12-10T00:00:00Z\",\n \"value\" : 31 | 89.0\n }, {\n \"timestamp\" : \"2019-12-11T00:00:00Z\",\n \"value\" 32 | : 89.0\n } ]\n } ]\n}" 33 | headers: 34 | Access-Control-Allow-Credentials: 35 | - 'true' 36 | Access-Control-Allow-Headers: 37 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 38 | Access-Control-Allow-Methods: 39 | - POST, GET 40 | Access-Control-Allow-Origin: 41 | - '*' 42 | Access-Control-Max-Age: 43 | - '3600' 44 | Cache-Control: 45 | - no-transform, public, max-age=31556926 46 | Connection: 47 | - Keep-Alive 48 | Content-Encoding: 49 | - gzip 50 | Content-Type: 51 | - application/json 52 | Date: 53 | - Wed, 06 Dec 2023 08:19:35 GMT 54 | Keep-Alive: 55 | - timeout=5, max=100 56 | Server: 57 | - Apache 58 | Strict-Transport-Security: 59 | - max-age=63072000; includeSubdomains; 60 | Transfer-Encoding: 61 | - chunked 62 | vary: 63 | - accept-encoding 64 | status: 65 | code: 200 66 | message: '' 67 | version: 1 68 | -------------------------------------------------------------------------------- /ohsome/test/cassettes/test_response/test_users_timestamp.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: bboxes=8.7137%2C49.4096%2C8.717%2C49.4119&time=2015-01-01%2F2016-01-01%2FP1Y&filter=name%3DKrautturm+and+type%3Away 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | Content-Length: 12 | - '115' 13 | Content-Type: 14 | - application/x-www-form-urlencoded 15 | user-agent: 16 | - ohsome-py/0.3.0 17 | method: POST 18 | uri: https://api.ohsome.org/v1/users/count 19 | response: 20 | body: 21 | string: "{\n \"attribution\" : {\n \"url\" : \"https://ohsome.org/copyrights\",\n 22 | \ \"text\" : \"\xA9 OpenStreetMap contributors\"\n },\n \"apiVersion\" 23 | : \"1.10.1\",\n \"result\" : [ {\n \"fromTimestamp\" : \"2015-01-01T00:00:00Z\",\n 24 | \ \"toTimestamp\" : \"2016-01-01T00:00:00Z\",\n \"value\" : 1.0\n } 25 | ]\n}" 26 | headers: 27 | Access-Control-Allow-Credentials: 28 | - 'true' 29 | Access-Control-Allow-Headers: 30 | - Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization 31 | Access-Control-Allow-Methods: 32 | - POST, GET 33 | Access-Control-Allow-Origin: 34 | - '*' 35 | Access-Control-Max-Age: 36 | - '3600' 37 | Cache-Control: 38 | - no-transform, public, max-age=31556926 39 | Connection: 40 | - Keep-Alive 41 | Content-Encoding: 42 | - gzip 43 | Content-Type: 44 | - application/json 45 | Date: 46 | - Wed, 06 Dec 2023 08:19:44 GMT 47 | Keep-Alive: 48 | - timeout=5, max=100 49 | Server: 50 | - Apache 51 | Strict-Transport-Security: 52 | - max-age=63072000; includeSubdomains; 53 | Transfer-Encoding: 54 | - chunked 55 | vary: 56 | - accept-encoding 57 | status: 58 | code: 200 59 | message: '' 60 | version: 1 61 | -------------------------------------------------------------------------------- /ohsome/test/conftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """Conftest for shared pytest fixtures""" 4 | import logging 5 | from unittest.mock import patch, PropertyMock 6 | 7 | import geopandas as gpd 8 | import pytest 9 | from requests import Response 10 | from shapely import Point 11 | from urllib3 import Retry 12 | 13 | import ohsome 14 | from ohsome import OhsomeResponse 15 | 16 | logger = logging.getLogger(__name__) 17 | 18 | 19 | @pytest.fixture 20 | def mocked_metadata(): 21 | """A default metadata dictionary. 22 | 23 | @return: 24 | """ 25 | return { 26 | "attribution": { 27 | "url": "https://ohsome.org/copyrights", 28 | "text": "© OpenStreetMap contributors", 29 | }, 30 | "apiVersion": "1.10.1", 31 | "timeout": 600.0, 32 | "extractRegion": { 33 | "spatialExtent": { 34 | "type": "Polygon", 35 | "coordinates": [ 36 | [ 37 | [-180.0, -90.0], 38 | [180.0, -90.0], 39 | [180.0, 90.0], 40 | [-180.0, 90.0], 41 | [-180.0, -90.0], 42 | ] 43 | ], 44 | }, 45 | "temporalExtent": { 46 | "fromTimestamp": "2007-10-08T00:00:00Z", 47 | "toTimestamp": "2023-11-25T13:00:00Z", 48 | }, 49 | "replicationSequenceNumber": 99919, 50 | }, 51 | } 52 | 53 | 54 | @pytest.fixture 55 | def base_client(mocked_metadata, tmpdir_factory): 56 | """Session-wide test client.""" 57 | temp_directory = tmpdir_factory.mktemp("base_client").mkdir("logs").strpath 58 | with patch( 59 | "ohsome.clients._OhsomeInfoClient.metadata", 60 | new_callable=PropertyMock, 61 | return_value=mocked_metadata, 62 | ): 63 | client = ohsome.OhsomeClient(log_dir=temp_directory) 64 | yield client 65 | 66 | 67 | @pytest.fixture 68 | def base_client_without_log(mocked_metadata): 69 | """Session-wide test client.""" 70 | with patch( 71 | "ohsome.clients._OhsomeInfoClient.metadata", 72 | new_callable=PropertyMock, 73 | return_value=mocked_metadata, 74 | ): 75 | client = ohsome.OhsomeClient(log=False) 76 | yield client 77 | 78 | 79 | @pytest.fixture 80 | def custom_client_with_wrong_url(tmpdir_factory): 81 | """Session-wide test client.""" 82 | temp_directory = tmpdir_factory.mktemp("base_client").mkdir("logs").strpath 83 | client = ohsome.OhsomeClient( 84 | base_api_url="https://imwrong", log_dir=temp_directory, retry=Retry(total=0) 85 | ) 86 | yield client 87 | 88 | 89 | @pytest.fixture(scope="module") 90 | def vcr_config(): 91 | """Get custom VCR configuration for tests.""" 92 | return { 93 | "match_on": [ 94 | "method", 95 | "host", 96 | "path", 97 | "query", 98 | "body", 99 | "headers", 100 | ] 101 | } 102 | 103 | 104 | @pytest.fixture() 105 | def dummy_ohsome_response() -> OhsomeResponse: 106 | """Mocked ohsome response with a single point geometry.""" 107 | test_gdf = gpd.GeoDataFrame( 108 | data={ 109 | "highway": ["primary"], 110 | "width": ["10"], 111 | "@snapshotTimestamp": ["2024-01-01"], 112 | "@osmId": ["node/1234"], 113 | }, 114 | geometry=[Point(0, 0)], 115 | crs="EPSG:4326", 116 | ) 117 | response = Response() 118 | response._content = test_gdf.to_json().encode() 119 | return OhsomeResponse(data=response.json()) 120 | -------------------------------------------------------------------------------- /ohsome/test/data/invalid_response.txt: -------------------------------------------------------------------------------- 1 | { 2 | "attribution" : { 3 | "url" : "https://ohsome.org/copyrights", 4 | "text" : "© OpenStreetMap contributors" 5 | }, 6 | "apiVersion" : "0.9", 7 | "type" : "FeatureCollection", 8 | "features" : [{ 9 | "type" : "Feature", 10 | "geometry" : { 11 | "type" : "Polygon", 12 | "coordinates" : [ 13 | [ 14 | [ 15 | 13.644420799999999, 16 | 50.9673861 17 | ], 18 | [ 19 | 13.6446461, 20 | 50.967762699999994 21 | ], 22 | [ 23 | 13.6435705, 24 | 50.9680009 25 | ], 26 | [ 27 | 13.6433485, 28 | 50.9676301 29 | ], 30 | [ 31 | 13.644420799999999, 32 | 50.9673861 33 | ] 34 | ] 35 | ] 36 | }, 37 | "properties" : { 38 | "@osmId" : "way/437313075", 39 | "@snapshotTimestamp" : "2019-12-10T00:00:00Z", 40 | "leisure" : "park" 41 | } 42 | }{ 43 | "timestamp" : "2020-05-19T07:07:25.356+0000", 44 | "status" : 200, 45 | "error" : "OK", 46 | "message" : "java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.", 47 | "path" : "/elements/geometry" 48 | } 49 | -------------------------------------------------------------------------------- /ohsome/test/data/invalid_response_customCode.txt: -------------------------------------------------------------------------------- 1 | "attribution" : { 2 | "url" : "https://ohsome.org/copyrights", 3 | "text" : "© OpenStreetMap contributors" 4 | }, 5 | "apiVersion" : "1.3.2", 6 | "type" : "FeatureCollection", 7 | "features" : [{ 8 | "timestamp" : "2021-06-02T10:07:46.438591", 9 | "status" : 413, 10 | "message" : "The given query is too large in respect to the given timeout. Please use a smaller region and/or coarser time period.", 11 | "requestUrl" : "http://localhost:8080/elements/geometry" 12 | } 13 | -------------------------------------------------------------------------------- /ohsome/test/data/invalid_response_no_message.txt: -------------------------------------------------------------------------------- 1 | , { 2 | "type" : "Feature", 3 | "geometry" : { 4 | "type" : "Polygon", 5 | "coordinates" : [ 6 | [ 7 | [ 8 | 8.3162482, 9 | -------------------------------------------------------------------------------- /ohsome/test/data/invalid_response_outOfMemory.txt: -------------------------------------------------------------------------------- 1 | { 2 | "attribution" : { 3 | "url" : "https://ohsome.org/copyrights", 4 | "text" : "© OpenStreetMap contributors" 5 | }, 6 | "apiVersion" : "1.4.1", 7 | "type" : "FeatureCollection", 8 | "features" : [{ 9 | "type" : "Feature", 10 | "geometry" : { 11 | "type" : "Polygon", 12 | "coordinates" : [ 13 | [ 14 | [ 15 | 8.7833329, 16 | 49.5470456 17 | ], 18 | [ 19 | 8.7836152, 20 | 49.5466073 21 | ], 22 | [ 23 | 8.7851933, 24 | 49.5470193 25 | ], 26 | [ 27 | 8.785043, 28 | 49.5473679 29 | ], 30 | [ 31 | 8.7849303, 32 | 49.5473947 33 | ], 34 | [ 35 | 8.7833329, 36 | 49.5470456 37 | ] 38 | ] 39 | ] 40 | }{ 41 | "timestamp" : "2021-06-01T11:38:52.821+0000", 42 | "status" : 200, 43 | "error" : "OK", 44 | "message" : "java.lang.OutOfMemoryError", 45 | "path" : "/elements/geometry" 46 | } 47 | -------------------------------------------------------------------------------- /ohsome/test/data/points.geojson: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "id": 1, 8 | "radius": 100 9 | }, 10 | "geometry": { 11 | "type": "Point", 12 | "coordinates": [ 13 | 8.678770065307615, 14 | 49.414435400453954 15 | ] 16 | } 17 | }, 18 | { 19 | "type": "Feature", 20 | "properties": { 21 | "id": 2, 22 | "radius": 150 23 | }, 24 | "geometry": { 25 | "type": "Point", 26 | "coordinates": [ 27 | 8.697137832641602, 28 | 49.41007968889129 29 | ] 30 | } 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /ohsome/test/data/polygons.geojson: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": {}, 7 | "id": "0", 8 | "geometry": { 9 | "type": "Polygon", 10 | "coordinates": [ 11 | [ 12 | [ 13 | 8.695077896118164, 14 | 49.408711468953854 15 | ], 16 | [ 17 | 8.699712753295898, 18 | 49.408711468953854 19 | ], 20 | [ 21 | 8.699712753295898, 22 | 49.41155955732304 23 | ], 24 | [ 25 | 8.695077896118164, 26 | 49.41155955732304 27 | ], 28 | [ 29 | 8.695077896118164, 30 | 49.408711468953854 31 | ] 32 | ] 33 | ] 34 | } 35 | }, 36 | { 37 | "type": "Feature", 38 | "properties": {}, 39 | "id": "1", 40 | "geometry": { 41 | "type": "Polygon", 42 | "coordinates": [ 43 | [ 44 | [ 45 | 8.677010536193848, 46 | 49.41370947536709 47 | ], 48 | [ 49 | 8.682074546813965, 50 | 49.41370947536709 51 | ], 52 | [ 53 | 8.682074546813965, 54 | 49.416641030041134 55 | ], 56 | [ 57 | 8.677010536193848, 58 | 49.416641030041134 59 | ], 60 | [ 61 | 8.677010536193848, 62 | 49.41370947536709 63 | ] 64 | ] 65 | ] 66 | } 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /ohsome/test/test_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Tests for ohsome client""" 5 | import datetime as dt 6 | import logging 7 | import os 8 | 9 | import geopandas as gpd 10 | import pandas as pd 11 | import pytest 12 | 13 | import ohsome 14 | from ohsome import OhsomeClient 15 | from ohsome.constants import OHSOME_VERSION 16 | 17 | script_path = os.path.dirname(os.path.realpath(__file__)) 18 | logger = logging.getLogger(__name__) 19 | 20 | 21 | def test_start_end_time_is_datetime(base_client): 22 | """Test if the start_ end end_timestamp is in datetime format without timezone.""" 23 | assert isinstance(base_client.start_timestamp, dt.datetime) 24 | assert isinstance(base_client.end_timestamp, dt.datetime) 25 | assert base_client.start_timestamp.tzinfo is None 26 | assert base_client.end_timestamp.tzinfo is None 27 | 28 | 29 | def test_api_version(base_client): 30 | """ 31 | Get ohsome API version 32 | :return: 33 | """ 34 | assert isinstance(base_client.api_version, str) 35 | 36 | 37 | @pytest.mark.vcr(match_on=["method", "headers"]) 38 | def test_user_agent(base_client): 39 | """ 40 | Checks user agent set by ohsome-py 41 | :return: 42 | """ 43 | resp = base_client._session().get(base_client._metadata_url) 44 | used_user_agent = resp.request.headers["user-agent"] 45 | assert used_user_agent == f"ohsome-py/{OHSOME_VERSION}" 46 | 47 | 48 | @pytest.mark.vcr 49 | def test_check_time_parameter_list(base_client): 50 | """ 51 | Checks whether time provided as list of strings is converted correctly 52 | :return: 53 | """ 54 | time = pd.date_range("2018-01-01", periods=3, freq="D") 55 | time = time.strftime("%Y-%m-%dT%H:%M:%S").tolist() 56 | bcircles = gpd.read_file(f"{script_path}/data/points.geojson") 57 | fltr = "amenity=restaurant and type:way" 58 | 59 | client = base_client 60 | client.elements.count.post(bcircles=bcircles, time=time, filter=fltr) 61 | 62 | 63 | @pytest.mark.vcr 64 | def test_check_time_parameter_datetime(base_client): 65 | """ 66 | Checks whether time provided as pandas.Series is converted correctly 67 | :return: 68 | """ 69 | bcircles = gpd.read_file(f"{script_path}/data/points.geojson") 70 | fltr = "amenity=restaurant and type:way" 71 | client = base_client 72 | 73 | time = [ 74 | dt.datetime.strptime("2018-01-01", "%Y-%m-%d"), 75 | dt.datetime.strptime("2018-01-02", "%Y-%m-%d"), 76 | ] 77 | response = client.elements.count.post(bcircles=bcircles, time=time, filter=fltr) 78 | result = response.as_dataframe() 79 | assert len(result) == 2 80 | 81 | 82 | @pytest.mark.vcr 83 | def test_end_timestamp_as_time_input(base_client): 84 | """ 85 | Test whether the end_timestamp value can be used as input to a query as time 86 | :return: 87 | """ 88 | bcircles = gpd.read_file(f"{script_path}/data/points.geojson") 89 | fltr = "amenity=restaurant and type:way" 90 | client = base_client 91 | 92 | time = client.end_timestamp 93 | response = client.elements.count.post(bcircles=bcircles, time=time, filter=fltr) 94 | result = response.as_dataframe() 95 | assert len(result) == 1 96 | 97 | 98 | @pytest.mark.vcr 99 | def test_format_bcircles_dataframe(base_client): 100 | """ 101 | Test whether a DataFrame object given as 'bcircles' is formatted correctly. 102 | :return: 103 | """ 104 | bcircles = pd.DataFrame( 105 | { 106 | "id": [1, 2], 107 | "lon": [8.695, 8.696], 108 | "lat": [49.41, 49.41], 109 | "radius": [500, 500], 110 | } 111 | ) 112 | time = "2018-01-01" 113 | fltr = "amenity=restaurant and type:way" 114 | 115 | client = base_client 116 | client.elements.count.groupByBoundary.post( 117 | bcircles=bcircles, time=time, filter=fltr 118 | ) 119 | 120 | 121 | @pytest.mark.vcr 122 | def test_format_bcircles_list(base_client): 123 | """ 124 | Test whether a DataFrame object given as 'bcircles' is formatted correctly. 125 | :return: 126 | """ 127 | time = "2018-01-01" 128 | fltr = "amenity=restaurant and type:node" 129 | client = base_client 130 | 131 | bcircles = [[8.695, 49.41, 200], [8.696, 49.41, 200]] 132 | client.elements.count.post(bcircles=bcircles, time=time, filter=fltr) 133 | 134 | bcircles = {1: [8.695, 49.41, 200], 2: [8.696, 49.41, 200]} 135 | client.elements.count.groupByBoundary.post( 136 | bcircles=bcircles, time=time, filter=fltr 137 | ) 138 | 139 | bcircles = ["1:8.695, 49.41, 200", "2:8.696, 49.41, 200"] 140 | client.elements.count.post(bcircles=bcircles, time=time, filter=fltr) 141 | 142 | bcircles = "1:8.695, 49.41, 200" 143 | client.elements.count.post(bcircles=bcircles, time=time, filter=fltr) 144 | 145 | 146 | @pytest.mark.vcr 147 | def test_format_bcircles_pandas(base_client): 148 | """ 149 | Test whether a pandas.DataFrame object given as 'bcircles' is formatted correctly. 150 | :return: 151 | """ 152 | bcircles = gpd.read_file(f"{script_path}/data/points.geojson") 153 | time = "2014-01-01/2017-01-01/P1Y" 154 | fltr = "amenity=restaurant and type:way" 155 | 156 | client = base_client 157 | client.elements.count.groupByBoundary.post( 158 | bcircles=bcircles, time=time, filter=fltr 159 | ) 160 | 161 | 162 | @pytest.mark.vcr 163 | def test_format_bcircles_geodataframe_geometry_error(base_client): 164 | """ 165 | Test whether a GeoDataFrame object given as 'bcircles' is formatted correctly. 166 | :return: 167 | """ 168 | bcircles = gpd.read_file(f"{script_path}/data/polygons.geojson") 169 | time = "2018-01-01" 170 | fltr = "amenity=restaurant and type:way" 171 | 172 | client = base_client 173 | with pytest.raises(ohsome.OhsomeException) as e_info: 174 | client.elements.count.groupByBoundary.post( 175 | bcircles=bcircles, time=time, filter=fltr 176 | ) 177 | assert ( 178 | "The geometry of the 'bcircles' GeoDataFrame may only include 'Point' geometry types and requires a 'radius' " 179 | "column." in e_info.value.message 180 | ) 181 | del client 182 | 183 | 184 | @pytest.mark.vcr 185 | def test_format_bboxes_dataframe(base_client): 186 | """ 187 | Tests whether input parameter given as a pandas.DataFrame is formatted correctly to a string 188 | :return: 189 | """ 190 | data = gpd.read_file(f"{script_path}/data/polygons.geojson") 191 | bboxes = data.bounds 192 | time = "2010-01-01" 193 | fltr = "amenity=restaurant and type:node" 194 | 195 | client = base_client 196 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 197 | 198 | 199 | @pytest.mark.vcr 200 | def test_format_bboxes_dataframe_missing_columns(base_client): 201 | """ 202 | Tests whether input parameter given as a pandas.DataFrame is formatted correctly to a string 203 | :return: 204 | """ 205 | data = gpd.read_file(f"{script_path}/data/polygons.geojson") 206 | bboxes = data.bounds 207 | bboxes.drop(columns="minx", inplace=True) 208 | time = "2010-01-01" 209 | fltr = "amenity=restaurant and type:node" 210 | 211 | client = base_client 212 | with pytest.raises(ohsome.OhsomeException) as e_info: 213 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 214 | if "occurred at index 0" in e_info.value.message: 215 | # Python 3.6 does some weird stuff with the output. So it differs a bit. 216 | assert ( 217 | "Column ('minx', 'occurred at index 0') is missing in the dataframe provided as 'bboxes'." 218 | in e_info.value.message 219 | ) 220 | else: 221 | assert ( 222 | "Column 'minx' is missing in the dataframe provided as 'bboxes'." 223 | in e_info.value.message 224 | ) 225 | 226 | 227 | @pytest.mark.vcr 228 | def test_format_bboxes_geodataframe(base_client): 229 | """ 230 | Tests whether input parameter given as a pandas.DataFrame is formatted correctly to a string 231 | :return: 232 | """ 233 | data = gpd.read_file(f"{script_path}/data/polygons.geojson") 234 | time = "2010-01-01/2011-01-01/P1Y" 235 | fltr = "amenity=restaurant and type:node" 236 | 237 | client = base_client 238 | with pytest.raises(ohsome.OhsomeException) as e_info: 239 | client.elements.count.post(bboxes=data, time=time, filter=fltr) 240 | 241 | assert ( 242 | "Use the 'bpolys' parameter to specify the boundaries using a " 243 | "geopandas object." in e_info.value.message 244 | ) 245 | 246 | 247 | @pytest.mark.vcr 248 | def test_format_bboxes_list(base_client): 249 | """ 250 | Tests whether parameter bboxes given as a list is formatted correctly 251 | :return: 252 | """ 253 | time = "2010-01-01" 254 | fltr = "amenity=restaurant and type:node" 255 | 256 | client = base_client 257 | 258 | bboxes = [ 259 | [8.67066, 49.41423, 8.68177, 49.4204], 260 | [8.67066, 49.41423, 8.68177, 49.4204], 261 | ] 262 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 263 | 264 | bboxes = { 265 | "1": [8.67066, 49.41423, 8.68177, 49.4204], 266 | "2": [8.67066, 49.41423, 8.68177, 49.4204], 267 | } 268 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 269 | 270 | bboxes = [8.67066, 49.41423, 8.68177, 49.4204] 271 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 272 | 273 | bboxes = [ 274 | "8.67066, 49.41423, 8.68177, 49.4204", 275 | "8.67066, 49.41423, 8.68177, 49.4204", 276 | ] 277 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 278 | 279 | bboxes = "8.67066, 49.41423, 8.68177, 49.4204" 280 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 281 | 282 | 283 | @pytest.mark.vcr 284 | def test_post_with_endpoint_string(base_client): 285 | """ 286 | Tests whether a request can be sent of by providing the endpoint url as a string to post() 287 | :return: 288 | """ 289 | bboxes = "8.7137,49.4096,8.717,49.4119" 290 | time = "2015-01-01,2016-01-01" 291 | filter = "name=Krautturm and type:way" 292 | 293 | endpoint = "contributions/latest/bbox" 294 | client = base_client 295 | response = client.post(endpoint=endpoint, bboxes=bboxes, time=time, filter=filter) 296 | result = response.as_dataframe() 297 | assert isinstance(result, gpd.GeoDataFrame) 298 | assert len(result) == 1 299 | 300 | # Test query with leading and ending slashes 301 | endpoint = "/contributions/latest/bbox/" 302 | client = base_client 303 | response = client.post(endpoint=endpoint, bboxes=bboxes, time=time, filter=filter) 304 | result = response.as_dataframe() 305 | 306 | assert isinstance(result, gpd.GeoDataFrame) 307 | assert len(result) == 1 308 | 309 | 310 | def test_none_init(): 311 | """Test if the input parameters can set to None explicitly.""" 312 | assert OhsomeClient( 313 | base_api_url=None, 314 | log=None, 315 | log_dir=None, 316 | cache=None, 317 | user_agent=None, 318 | retry=None, 319 | ) 320 | -------------------------------------------------------------------------------- /ohsome/test/test_exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """Test OhsomeExceptions""" 4 | 5 | import logging 6 | import os 7 | from pathlib import Path 8 | from unittest.mock import patch, MagicMock 9 | 10 | import geopandas as gpd 11 | import pytest 12 | import responses 13 | from requests.exceptions import RequestException 14 | from responses import registries 15 | from urllib3 import Retry 16 | 17 | import ohsome 18 | from ohsome import OhsomeClient, OhsomeException 19 | 20 | script_path = os.path.dirname(os.path.realpath(__file__)) 21 | logger = logging.getLogger(__name__) 22 | 23 | 24 | @pytest.mark.vcr 25 | def test_timeout_error(base_client): 26 | """ 27 | Test whether an OhsomeException is raised, if the ohsome API contains a JSONDecodeError 28 | :return: 29 | """ 30 | bboxes = "8.67066,49.41423,8.68177,49.4204" 31 | time = "2010-01-01/2011-01-01/P1Y" 32 | fltr = "building=* and type:way" 33 | timeout = 0 34 | 35 | client = base_client 36 | with pytest.raises(ohsome.OhsomeException) as e_info: 37 | client.elements.geometry.post( 38 | bboxes=bboxes, time=time, filter=fltr, timeout=timeout 39 | ) 40 | assert ( 41 | "The given query is too large in respect to the given timeout. Please use a smaller region and/or coarser " 42 | "time period." in e_info.value.message 43 | ) 44 | 45 | 46 | def test_broken_response_timeout_error(base_client): 47 | """Test whether an OhsomeException is raised in case of a JSONDecodeError.""" 48 | 49 | bboxes = "8.67066,49.41423,8.68177,49.4204" 50 | time = "2010-01-01/2011-01-01/P1Y" 51 | fltr = "building=* and type:way" 52 | timeout = 30 53 | 54 | client = base_client 55 | with pytest.raises(ohsome.OhsomeException) as e_info: 56 | with responses.RequestsMock() as rsps: 57 | rsps.post( 58 | "https://api.ohsome.org/v1/elements/geometry", 59 | body=b'{\n "attribution" : {\n "url" : "https://ohsome.org/copyrights",\n "text" : "\xc2\xa9 OpenStreetMap contributors"\n },\n "apiVersion" : "1.10.3",\n "type" : "FeatureCollection",\n "features" : [{\n "timestamp" : "2024-07-31T10:37:31.603661767",\n "status" : 413,\n "message" : "The given query is too large in respect to the given timeout. Please use a smaller region and/or coarser time period.",\n "requestUrl" : "https://api.ohsome.org/v1/elements/geometry"\n}', 60 | ) 61 | client.elements.geometry.post( 62 | bboxes=bboxes, time=time, filter=fltr, timeout=timeout 63 | ) 64 | assert ( 65 | "The given query is too large in respect to the given timeout. Please use a smaller region and/or coarser " 66 | "time period." in e_info.value.message 67 | ) 68 | assert e_info.value.error_code == 413 69 | 70 | 71 | @pytest.mark.vcr 72 | def test_invalid_url(): 73 | """ 74 | Test whether an OhsomeException is raises if the ohsome API url is invalid, i.e. 75 | https://api.ohsome.org/ instead of https://api.ohsome.org/v1 76 | :return: 77 | """ 78 | base_api_url = "https://api.ohsome.org/" 79 | bboxes = "8.7137,49.4096,8.717,49.4119" 80 | time = "2018-01-01" 81 | fltr = "name=Krautturm and type:way" 82 | 83 | client = ohsome.OhsomeClient(base_api_url=base_api_url, log=False) 84 | with pytest.raises(ohsome.OhsomeException) as e_info: 85 | client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 86 | assert "Invalid URL:" in e_info.value.message 87 | 88 | 89 | @pytest.mark.vcr 90 | def test_invalid_endpoint(): 91 | """ 92 | Test whether request can be sent to alternative url 93 | :return: 94 | """ 95 | base_api_url = "https://api.ohsme.org/v0.9/" 96 | bboxes = "8.7137,49.4096,8.717,49.4119" 97 | time = "2018-01-01" 98 | fltr = "name=Krautturm and type:way" 99 | 100 | client = ohsome.OhsomeClient(base_api_url=base_api_url, log=False) 101 | with pytest.raises(AttributeError): 102 | client.elements.cout.post(bboxes=bboxes, time=time, filter=fltr) 103 | 104 | 105 | @pytest.mark.vcr 106 | def test_disable_logging(base_client): 107 | """ 108 | Tests whether logging is disabled so no new log file is created if an OhsomeException occurs 109 | :return: 110 | """ 111 | base_client.log = False 112 | bboxes = [8.67555, 49.39885, 8.69637, 49.41122] 113 | fltr = "building=* and type:way" 114 | timeout = 0.001 115 | try: 116 | n_log_files_before = len(os.listdir(base_client.log_dir)) 117 | except FileNotFoundError: 118 | n_log_files_before = 0 119 | with pytest.raises(ohsome.OhsomeException): 120 | base_client.elements.geometry.post(bboxes=bboxes, filter=fltr, timeout=timeout) 121 | 122 | if os.path.exists(base_client.log_dir): 123 | n_log_files_after = len(os.listdir(base_client.log_dir)) 124 | assert n_log_files_after == n_log_files_before 125 | 126 | 127 | @pytest.mark.vcr 128 | def test_log_bpolys(base_client_without_log, tmpdir): 129 | """ 130 | Test whether three log files are created when request fails (*bpolys.geojson, *.json and *_raw.txt) 131 | :return: 132 | """ 133 | 134 | base_client_without_log.log = True 135 | base_client_without_log.log_dir = tmpdir.mkdir("logs").strpath 136 | 137 | bpolys = gpd.read_file(f"{script_path}/data/polygons.geojson") 138 | time = "2018-01-01" 139 | fltr = "amenity=restaurant and type:node" 140 | timeout = 0.001 141 | 142 | with pytest.raises(ohsome.OhsomeException): 143 | base_client_without_log.elements.count.post( 144 | bpolys=bpolys, time=time, filter=fltr, timeout=timeout 145 | ) 146 | log_file_patterns = [ 147 | "ohsome_*_bpolys.geojson", 148 | "ohsome_*_curl.sh", 149 | "ohsome_*.json", 150 | "ohsome_*raw.txt", 151 | ] 152 | for p in log_file_patterns: 153 | log_file = list(Path(base_client_without_log.log_dir).glob(p)) 154 | assert len(log_file) == 1, f"Log file {p} not found" 155 | logger.info(f"Found log file: {log_file[0].name}") 156 | log_file[0].unlink() 157 | 158 | 159 | @pytest.mark.vcr 160 | def test_log_curl(base_client_without_log, tmpdir): 161 | """ 162 | Test whether log file containing curl command is created when request fails 163 | :return: 164 | """ 165 | 166 | base_client_without_log.log = True 167 | base_client_without_log.log_dir = tmpdir.mkdir("logs").strpath 168 | 169 | bboxes = [8.67555, 49.39885, 8.69637, 49.41122] 170 | timeout = 0.001 171 | 172 | with pytest.raises(ohsome.OhsomeException): 173 | base_client_without_log.elements.count.post(bboxes=bboxes, timeout=timeout) 174 | 175 | log_file = list(Path(base_client_without_log.log_dir).glob("ohsome_*_curl.sh")) 176 | with open(log_file[0]) as file: 177 | assert file.read() == ( 178 | 'curl -X POST -H "user-agent: ohsome-py/0.3.0" -H "Accept-Encoding: gzip, ' 179 | 'deflate" -H "Accept: */*" -H "Connection: keep-alive" -H "Content-Length: 60" ' 180 | '-H "Content-Type: application/x-www-form-urlencoded" ' 181 | "-d 'bboxes=8.67555%2C49.39885%2C8.69637%2C49.41122&timeout=0.001' " 182 | "https://api.ohsome.org/v1/elements/count" 183 | ) 184 | 185 | 186 | def test_metadata_invalid_baseurl(custom_client_with_wrong_url): 187 | """ 188 | Throw exception if the ohsome API is not available 189 | :return: 190 | """ 191 | 192 | with pytest.raises(ohsome.OhsomeException): 193 | _ = custom_client_with_wrong_url.metadata 194 | 195 | 196 | @pytest.mark.vcr 197 | def test_exception_invalid_parameters(base_client): 198 | """ 199 | Test whether error message from ohsome API is forwarded to user 200 | :param base_client: 201 | :return: 202 | """ 203 | bboxes = [8.6577, 49.3958, 8.7122, 49.4296] 204 | time = "2010-01-01/2020-01-01/P1M" 205 | fltr = "highway=* and type:way" 206 | with pytest.raises(ohsome.OhsomeException) as e_info: 207 | base_client.elements.count.groupByTag.post( 208 | bboxes=bboxes, time=time, filter=fltr 209 | ) 210 | assert "You need to give one groupByKey parameter" in e_info.value.message 211 | 212 | 213 | @pytest.mark.vcr 214 | def test_exception_connection_reset(base_client): 215 | """ 216 | Test whether error without response (e.g. connection reset) is handled correctly 217 | :param base_client: 218 | :return: 219 | """ 220 | 221 | with patch( 222 | "requests.sessions.Session.post", 223 | MagicMock( 224 | side_effect=RequestException( 225 | "This request was failed on purpose without response!" 226 | ) 227 | ), 228 | ), patch("ohsome.OhsomeException.log_response", MagicMock()) as mock_func: 229 | bpolys = gpd.read_file(f"{script_path}/data/polygons.geojson") 230 | time = "2018-01-01" 231 | fltr = "name=Krautturm and type:way" 232 | 233 | with pytest.raises(ohsome.OhsomeException): 234 | base_client.elements.count.post(bpolys=bpolys, time=time, filter=fltr) 235 | 236 | mock_func.assert_not_called() 237 | 238 | 239 | @responses.activate 240 | def test_connection_error(): 241 | """Test if the connection error response is correctly given.""" 242 | url = "https://mock.com/" 243 | bboxes = "8.7137,49.4096,8.717,49.4119" 244 | 245 | responses.add( 246 | responses.PUT, 247 | url, 248 | status=503, 249 | ) 250 | 251 | client = OhsomeClient(base_api_url=url, retry=False) 252 | 253 | with pytest.raises(OhsomeException) as e: 254 | client.post(bboxes=bboxes) 255 | 256 | assert e.value.message == ( 257 | "Connection Error: Query could not be sent. Make sure there are no network problems " 258 | f"and that the ohsome API URL {url} is valid." 259 | ) 260 | 261 | 262 | @responses.activate(registry=registries.OrderedRegistry) 263 | def test_max_retry_error(): 264 | """Test if the retry mechnaism can be set and works as expected. 265 | 266 | Especially if a last retry is done, does not shadow its cause or enter an infinite recursion loop. 267 | """ 268 | url = "https://mock.com" 269 | bboxes = "8.7137,49.4096,8.717,49.4119" 270 | 271 | rsp1 = responses.post(url, json={"message": "Try: ignored"}, status=500) 272 | rsp2 = responses.post(url, json={"message": "Retry 1: ignored"}, status=500) 273 | rsp3 = responses.post(url, json={"message": "Final try: raised"}, status=500) 274 | 275 | client = OhsomeClient( 276 | base_api_url=url, 277 | retry=Retry(total=1, status_forcelist=[500], allowed_methods=["GET", "POST"]), 278 | ) 279 | 280 | with pytest.raises(OhsomeException, match="Final try: raised") as e: 281 | client.post(bboxes=bboxes) 282 | 283 | assert e.value.error_code == 500 284 | assert rsp1.call_count == 1 285 | assert rsp2.call_count == 1 286 | assert rsp3.call_count == 1 287 | -------------------------------------------------------------------------------- /ohsome/test/test_helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Tests for utility functions""" 5 | import datetime 6 | import json 7 | import logging 8 | import os 9 | 10 | import geopandas as gpd 11 | import numpy as np 12 | import pandas as pd 13 | import pytest 14 | from shapely import Polygon 15 | 16 | from ohsome import OhsomeException 17 | from ohsome.helper import ( 18 | find_groupby_names, 19 | extract_error_message_from_invalid_json, 20 | format_time, 21 | convert_arrays, 22 | format_list_parameters, 23 | format_bpolys, 24 | ) 25 | 26 | script_path = os.path.dirname(os.path.realpath(__file__)) 27 | logger = logging.getLogger(__name__) 28 | 29 | 30 | def test_find_groupby_names_one_group(): 31 | """ 32 | Tests counting elements within a bounding box for two timestamps 33 | :return: 34 | """ 35 | url = "https://api.ohsome.org/v0.9/elements/count/groupBy/boundary" 36 | expected = ["boundary"] 37 | result = find_groupby_names(url) 38 | assert expected == result 39 | 40 | 41 | def test_find_groupby_names_two_groups(): 42 | """ 43 | Tests counting elements within a bounding box for two timestamps 44 | :return: 45 | """ 46 | url = "https://api.ohsome.org/v0.9/elements/count/groupBy/boundary/groupBy/tag" 47 | expected = ["boundary", "tag"] 48 | result = find_groupby_names(url) 49 | assert expected == result 50 | 51 | 52 | def test_extract_error_message_from_invalid_json(): 53 | """ 54 | Test whether error code and message are extracted correctly 55 | :return: 56 | """ 57 | 58 | invalid_response = f"{script_path}/data/invalid_response.txt" 59 | with open(invalid_response) as src: 60 | invalid_response_text = src.read() 61 | 62 | expected_error_code = 500 63 | expected_message = ( 64 | "A broken response has been received: java.lang.RuntimeException: " 65 | "java.lang.RuntimeException: java.lang.RuntimeException: " 66 | "java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request " 67 | 'timed out after 30000ms.; "error" : "OK"; "timestamp" : "2020-05-19T07:07:25.356+0000"; ' 68 | '"path" : "/elements/geometry"; "status" : 200' 69 | ) 70 | 71 | error_code, message = extract_error_message_from_invalid_json(invalid_response_text) 72 | 73 | assert expected_message == message 74 | assert expected_error_code == error_code 75 | 76 | 77 | def test_extract_error_message_from_invalid_json_no_message(): 78 | """ 79 | Test whether error code and message are extracted correctly if there is no message in the json response 80 | :return: 81 | """ 82 | 83 | invalid_response = f"{script_path}/data/invalid_response_no_message.txt" 84 | with open(invalid_response) as src: 85 | invalid_response_text = src.read() 86 | 87 | expected_error_code = 500 88 | expected_message = "A broken response has been received" 89 | 90 | error_code, message = extract_error_message_from_invalid_json(invalid_response_text) 91 | 92 | assert expected_message == message 93 | assert expected_error_code == error_code 94 | 95 | 96 | def test_extract_error_message_from_invalid_json_outOfMemory(): 97 | """ 98 | Test whether error code and message are extracted correctly if the server reports out of memory 99 | :return: 100 | """ 101 | 102 | invalid_response = f"{script_path}/data/invalid_response_outOfMemory.txt" 103 | with open(invalid_response) as src: 104 | invalid_response_text = src.read() 105 | 106 | expected_error_code = 507 107 | expected_message = ( 108 | 'A broken response has been received: java.lang.OutOfMemoryError; "error" : "OK"; ' 109 | '"timestamp" : "2021-06-01T11:38:52.821+0000"; "path" : "/elements/geometry"; "status" : 200' 110 | ) 111 | 112 | error_code, message = extract_error_message_from_invalid_json(invalid_response_text) 113 | 114 | assert expected_message == message 115 | assert expected_error_code == error_code 116 | 117 | 118 | def test_extract_error_message_from_invalid_json_custonErrorCode(): 119 | """ 120 | Test whether error code and message are extracted correctly if the server reports out of memory 121 | :return: 122 | """ 123 | 124 | invalid_response = f"{script_path}/data/invalid_response_customCode.txt" 125 | with open(invalid_response) as src: 126 | invalid_response_text = src.read() 127 | 128 | expected_error_code = 413 129 | expected_message = ( 130 | "A broken response has been received: The given query is too large in respect to the given " 131 | 'timeout. Please use a smaller region and/or coarser time period.; "timestamp" : ' 132 | '"2021-06-02T10:07:46.438591"; "requestUrl" : "http://localhost:8080/elements/geometry"; ' 133 | '"status" : 413' 134 | ) 135 | 136 | error_code, message = extract_error_message_from_invalid_json(invalid_response_text) 137 | 138 | assert error_code == expected_error_code 139 | assert message == expected_message 140 | 141 | 142 | def test_array_conversion(): 143 | """Tests whether numpy arrays are supported as input parameters""" 144 | method_input = {"bbox": np.ones(3)} 145 | 146 | output = convert_arrays(method_input) 147 | 148 | assert isinstance(output["bbox"], list) 149 | 150 | 151 | def test_convert_arrays_multi_dim(): 152 | """Test error raising on multi dim array.""" 153 | method_input = {"bbox": np.ndarray(shape=(2, 2))} 154 | with pytest.raises( 155 | AssertionError, 156 | match="Only one dimensional arrays are supported for parameter bbox", 157 | ): 158 | convert_arrays(method_input) 159 | 160 | 161 | def test_format_time(): 162 | """Test if the time formatter covers all cases.""" 163 | parameters = { 164 | "time_str": {"input": "2022-01-01", "output": "2022-01-01"}, 165 | "time_datetime": { 166 | "input": datetime.datetime(2022, 1, 1), 167 | "output": "2022-01-01T00:00:00", 168 | }, 169 | "time_date": {"input": datetime.date(2022, 1, 1), "output": "2022-01-01"}, 170 | "time_list": { 171 | "input": ["2022-01-01", "2022-01-02"], 172 | "output": "2022-01-01,2022-01-02", 173 | }, 174 | "time_pandas_index": { 175 | "input": pd.date_range("2022-01-01", periods=2, freq="D"), 176 | "output": "2022-01-01T00:00:00,2022-01-02T00:00:00", 177 | }, 178 | "time_pandas_series": { 179 | "input": pd.Series(["2022-01-01", "2022-01-02"]), 180 | "output": "2022-01-01,2022-01-02", 181 | }, 182 | } 183 | 184 | for k, v in parameters.items(): 185 | output = format_time(v["input"]) 186 | assert v["output"] == output, f"Input type {k} not correctly formatted." 187 | 188 | 189 | def test_format_time_error_format_not_supported(): 190 | """Test weather a time with wrong type (e.g. a dict) raises an error.""" 191 | with pytest.raises( 192 | ValueError, 193 | match="The given time format is not supported. Feel free to open an " 194 | "issue in the ohsome-py repository for a feature request.", 195 | ): 196 | format_time({}) 197 | 198 | 199 | def test_format_list_parameters(): 200 | """Test if formatting of list-like parameters works, and does not affect other parameters.""" 201 | method_input = { 202 | "groupByKeys": ["k1", "k2"], 203 | "groupByValues": ["v1", "v2"], 204 | "otherParam": ["l"], 205 | "properties": ["p1"], 206 | } 207 | 208 | expected_output = { 209 | "groupByKeys": "k1,k2", 210 | "groupByValues": "v1,v2", 211 | "otherParam": ["l"], 212 | "properties": "p1", 213 | } 214 | 215 | output = format_list_parameters(method_input) 216 | 217 | assert output == expected_output 218 | 219 | 220 | def test_format_bpolys(): 221 | """Test if the formatting of bounding polys works correctly.""" 222 | with pytest.raises(OhsomeException) as e: 223 | format_bpolys({}) 224 | assert ( 225 | e.value.message 226 | == "bolys must be a geojson string, a shapely polygonal object or a geopandas object" 227 | ) 228 | 229 | geojson = json.dumps( 230 | { 231 | "type": "FeatureCollection", 232 | "features": [ 233 | { 234 | "id": "0", 235 | "type": "Feature", 236 | "properties": {}, 237 | "geometry": { 238 | "type": "Polygon", 239 | "coordinates": [ 240 | [[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]] 241 | ], 242 | }, 243 | } 244 | ], 245 | } 246 | ) 247 | 248 | assert format_bpolys(geojson) == geojson 249 | 250 | polygon = Polygon(((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0))) 251 | assert format_bpolys(polygon) == geojson 252 | 253 | series = gpd.GeoSeries( 254 | data=[polygon], 255 | crs="EPSG:4326", 256 | ) 257 | assert format_bpolys(series) == geojson 258 | 259 | df = gpd.GeoDataFrame( 260 | geometry=[polygon], 261 | crs="EPSG:4326", 262 | ) 263 | assert format_bpolys(df) == geojson 264 | -------------------------------------------------------------------------------- /ohsome/test/test_response.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """Tests for ohsome API response""" 4 | import warnings 5 | from datetime import datetime 6 | 7 | import geopandas as gpd 8 | import pandas as pd 9 | import pytest 10 | from geopandas.testing import assert_geodataframe_equal 11 | from requests import Response 12 | from shapely import Point 13 | 14 | from ohsome import OhsomeResponse 15 | 16 | 17 | @pytest.mark.vcr 18 | def test_elements_count(base_client): 19 | """ 20 | Tests whether the result of elements.count is formatted correctly as a pandas.DataFrame. If this works 21 | .area, .length and .perimeter should work as well. 22 | :return: 23 | """ 24 | bboxes = "8.6933,49.40893,8.69797,49.41106" 25 | time = "2019-12-10" 26 | fltr = "amenity=cafe and type:node" 27 | 28 | client = base_client 29 | response = client.elements.count.post(bboxes=bboxes, time=time, filter=fltr) 30 | result = response.as_dataframe() 31 | 32 | assert isinstance(result, pd.DataFrame) 33 | assert len(result) == 1 34 | assert list(result.index.names) == ["timestamp"] 35 | 36 | 37 | @pytest.mark.vcr 38 | def test_elements_density(base_client): 39 | """ 40 | Tests whether the result of elements.count.density is formatted correctly as a pandas.DataFrame 41 | :return: 42 | """ 43 | bboxes = "8.6933,49.40893,8.69797,49.41106" 44 | time = "2019-12-10" 45 | fltr = "amenity=cafe and type:node" 46 | 47 | client = base_client 48 | response = client.elements.count.density.post(bboxes=bboxes, time=time, filter=fltr) 49 | result = response.as_dataframe() 50 | 51 | assert isinstance(result, pd.DataFrame) 52 | assert len(result) == 1 53 | assert list(result.index.names) == ["timestamp"] 54 | 55 | 56 | @pytest.mark.vcr 57 | def test_elements_count_groupby_key(base_client): 58 | """ 59 | Tests whether the result of elements.count.groupBy.key is formatted correctly as a pandas.DataFrame 60 | :return: 61 | """ 62 | bboxes = "8.6933,49.40893,8.69797,49.41106" 63 | time = "2019-12-10,2019-12-11" 64 | fltr = "type:node" 65 | groupByKeys = ["amenity", "shop"] 66 | 67 | client = base_client 68 | response = client.elements.count.groupByKey.post( 69 | bboxes=bboxes, time=time, filter=fltr, groupByKeys=groupByKeys 70 | ) 71 | result = response.as_dataframe() 72 | 73 | assert isinstance(result, pd.DataFrame) 74 | assert len(result) == 6 75 | assert list(result.index.names) == ["key", "timestamp"] 76 | 77 | 78 | @pytest.mark.vcr 79 | def test_not_implemented_query(base_client): 80 | """ 81 | Tests whether a query which is not implemented in ohsome-py still works 82 | :return: 83 | """ 84 | bboxes = "8.6933,49.40893,8.69797,49.41106" 85 | time = "2019-12-10,2019-12-11" 86 | fltr = "type:node" 87 | groupByKeys = ["amenity", "shop"] 88 | 89 | client = base_client 90 | response = client.elements.count.groupBy.key.post( 91 | bboxes=bboxes, time=time, filter=fltr, groupByKeys=groupByKeys 92 | ) 93 | result = response.as_dataframe() 94 | 95 | assert isinstance(result, pd.DataFrame) 96 | assert len(result) == 6 97 | assert list(result.index.names) == ["key", "timestamp"] 98 | 99 | 100 | @pytest.mark.vcr 101 | def test_elements_count_groupby_tag(base_client): 102 | """ 103 | Tests whether the result of elements.count.groupBy.tag is formatted correctly as a pandas.DataFrame 104 | :return: 105 | """ 106 | bboxes = "8.6933,49.40893,8.69797,49.41106" 107 | time = "2019-12-10,2019-12-11" 108 | fltr = "type:node" 109 | groupByKey = "amenity" 110 | 111 | client = base_client 112 | response = client.elements.count.groupByTag.post( 113 | bboxes=bboxes, time=time, filter=fltr, groupByKey=groupByKey 114 | ) 115 | result = response.as_dataframe() 116 | 117 | assert isinstance(result, pd.DataFrame) 118 | assert len(result) == 58 119 | assert list(result.index.names) == ["tag", "timestamp"] 120 | 121 | 122 | @pytest.mark.vcr 123 | def test_multi_index_false(base_client): 124 | """ 125 | Tests whether the response is formatted correctly as a pandas.DataFrame without a multiindex 126 | :return: 127 | """ 128 | bboxes = "8.6933,49.40893,8.69797,49.41106" 129 | time = "2019-12-10,2019-12-11" 130 | fltr = "type:node" 131 | groupByKey = "amenity" 132 | 133 | client = base_client 134 | response = client.elements.count.groupByTag.post( 135 | bboxes=bboxes, time=time, filter=fltr, groupByKey=groupByKey 136 | ) 137 | result = response.as_dataframe(multi_index=False) 138 | 139 | assert isinstance(result, pd.DataFrame) 140 | assert len(result) == 58 141 | assert isinstance(result.index, pd.RangeIndex) 142 | 143 | 144 | @pytest.mark.vcr 145 | def test_elements_count_groupby_type(base_client): 146 | """ 147 | Tests whether the result of elements.count.groupBy.type is formatted correctly as a pandas.DataFrame 148 | :return: 149 | """ 150 | bboxes = "8.6933,49.40893,8.69797,49.41106" 151 | time = "2019-12-10,2019-12-11" 152 | fltr = "amenity=* and (type:way or type:node)" 153 | 154 | client = base_client 155 | response = client.elements.count.groupByType.post( 156 | bboxes=bboxes, time=time, filter=fltr 157 | ) 158 | result = response.as_dataframe() 159 | 160 | assert isinstance(result, pd.DataFrame) 161 | assert len(result) == 6 162 | assert list(result.index.names) == ["type", "timestamp"] 163 | 164 | 165 | @pytest.mark.vcr 166 | def test_elements_count_groupby_boundary(base_client): 167 | """ 168 | Tests whether the result of elements.count.groupBy.boundary is formatted correctly as a pandas.DataFrame 169 | :return: 170 | """ 171 | bboxes = { 172 | 1: [8.6933, 49.40893, 8.69797, 49.41106], 173 | 2: [8.6887, 49.41325, 8.69462, 49.4166], 174 | } 175 | time = "2019-12-10" 176 | fltr = "amenity=cafe and type:node" 177 | 178 | client = base_client 179 | response = client.elements.count.groupByBoundary.post( 180 | bboxes=bboxes, time=time, filter=fltr 181 | ) 182 | result = response.as_dataframe() 183 | 184 | assert isinstance(result, pd.DataFrame) 185 | assert len(result) == 2 186 | assert list(result.index.names) == ["boundary", "timestamp"] 187 | 188 | 189 | @pytest.mark.vcr 190 | def test_elements_count_groupby_boundary_groupby_tag(base_client): 191 | """ 192 | Tests whether the result of elements.count.groupBy.boundary.groupBy.tag is formatted correctly as a pandas.DataFrame 193 | :return: 194 | """ 195 | bboxes = "8.6933,49.40893,8.69797,49.41106|8.6887,49.41325,8.69462,49.4166" 196 | time = "2019-12-10" 197 | fltr = "amenity=cafe and type:node" 198 | groupByKey = "amenity" 199 | 200 | client = base_client 201 | response = client.elements.count.groupByBoundary.groupByTag.post( 202 | bboxes=bboxes, time=time, filter=fltr, groupByKey=groupByKey 203 | ) 204 | result = response.as_dataframe() 205 | 206 | assert isinstance(result, pd.DataFrame) 207 | assert len(result) == 2 208 | assert list(result.index.names) == ["boundary", "tag", "timestamp"] 209 | 210 | 211 | @pytest.mark.vcr 212 | def test_elements_count_ratio(base_client): 213 | """ 214 | Tests whether the result of elements.count.ratio is formatted correctly as a pandas.DataFrame 215 | :return: 216 | """ 217 | bboxes = "8.6933,49.40893,8.69797,49.41106" 218 | time = "2019-12-10" 219 | fltr = "amenity=* and type:node" 220 | fltr2 = "amenity=cafe and type:node" 221 | 222 | client = base_client 223 | response = client.elements.count.ratio.post( 224 | bboxes=bboxes, time=time, filter=fltr, filter2=fltr2 225 | ) 226 | result = response.as_dataframe() 227 | 228 | assert isinstance(result, pd.DataFrame) 229 | assert len(result) == 1 230 | assert list(result.index.names) == ["timestamp"] 231 | 232 | 233 | @pytest.mark.vcr 234 | def test_elements_count_ratio_groupby_boundary(base_client): 235 | """ 236 | Tests whether the result of elements.count.ratio.groupBy.boundary is formatted correctly as a pandas.DataFrame 237 | :return: 238 | """ 239 | bboxes = "A:8.6933,49.40893,8.69797,49.41106|B:8.6887,49.41325,8.69462,49.4166" 240 | time = "2019-12-10, 2020-07-23" 241 | fltr = "amenity=hotel and type:node" 242 | fltr2 = "amenity=cafe and type:node" 243 | 244 | client = base_client 245 | response = client.elements.count.ratio.groupByBoundary.post( 246 | bboxes=bboxes, time=time, filter=fltr, filter2=fltr2 247 | ) 248 | result = response.as_dataframe() 249 | 250 | assert isinstance(result, pd.DataFrame) 251 | assert len(result) == 4 252 | assert list(result.index.names) == ["boundary", "timestamp"] 253 | 254 | 255 | @pytest.mark.vcr 256 | def test_elements_geometry(base_client): 257 | """ 258 | Tests whether the result of elements.geometry is converted to a geopandas.GeoDataFrame 259 | :return: 260 | """ 261 | bboxes = "8.7137,49.4096,8.717,49.4119" 262 | time = "2016-01-01" 263 | flter = "name=Krautturm and type:way" 264 | 265 | client = base_client 266 | response = client.elements.geometry.post(bboxes=bboxes, time=time, filter=flter) 267 | result = response.as_dataframe() 268 | del client 269 | 270 | assert isinstance(result, gpd.GeoDataFrame) 271 | assert len(result) == 1 272 | 273 | 274 | @pytest.mark.vcr 275 | def test_extra_tags_argument(base_client): 276 | """ 277 | Tests whether the result of elements.geometry is converted to a geopandas.GeoDataFrame 278 | :return: 279 | """ 280 | bboxes = "8.7137,49.4096,8.717,49.4119" 281 | time = "2016-01-01" 282 | flter = "name=Krautturm and type:way" 283 | 284 | response = base_client.elements.geometry.post( 285 | bboxes=bboxes, time=time, filter=flter, properties="tags,metadata" 286 | ) 287 | result = response.as_dataframe() 288 | 289 | assert "@other_tags" in result.columns 290 | assert "@version" in result.columns 291 | 292 | assert result["@other_tags"].to_list() == [{"building": "yes", "name": "Krautturm"}] 293 | assert result["@version"].to_list() == [4] 294 | 295 | 296 | @pytest.mark.vcr 297 | def test_elementsFullHistory_geometry(base_client): 298 | """ 299 | Tests whether the result of elementsFullHistory.centroid is converted to a geopandas.GeoDataFrame 300 | :return: 301 | """ 302 | bboxes = "8.7137,49.4096,8.717,49.4119" 303 | time = "2015-01-01,2016-01-01" 304 | flter = "name=Krautturm and type:way" 305 | 306 | client = base_client 307 | response = client.elementsFullHistory.centroid.post( 308 | bboxes=bboxes, time=time, filter=flter 309 | ) 310 | result = response.as_dataframe() 311 | 312 | assert isinstance(result, gpd.GeoDataFrame) 313 | assert len(result) == 2 314 | 315 | 316 | @pytest.mark.vcr 317 | def test_users_timestamp(base_client): 318 | """ 319 | Tests whether the result of users.count is converted to a pandas.DataFrame 320 | :return: 321 | """ 322 | bboxes = "8.7137,49.4096,8.717,49.4119" 323 | time = "2015-01-01/2016-01-01/P1Y" 324 | flter = "name=Krautturm and type:way" 325 | 326 | client = base_client 327 | response = client.users.count.post(bboxes=bboxes, time=time, filter=flter) 328 | result = response.as_dataframe() 329 | 330 | assert isinstance(result, pd.DataFrame) 331 | assert len(result) == 1 332 | 333 | 334 | @pytest.mark.vcr 335 | def test_contributions_centroid(base_client): 336 | """ 337 | Test whether the result of conributions.centroid is converted to a geopandas.GeoDataFrame 338 | :return: 339 | """ 340 | bboxes = "8.7137,49.4096,8.717,49.4119" 341 | time = "2015-01-01,2016-01-01" 342 | filter = "name=Krautturm and type:way" 343 | 344 | client = base_client 345 | response = client.contributions.centroid.post( 346 | bboxes=bboxes, time=time, filter=filter 347 | ) 348 | result = response.as_dataframe() 349 | 350 | assert isinstance(result, gpd.GeoDataFrame) 351 | assert len(result) == 1 352 | 353 | 354 | @pytest.mark.vcr 355 | def test_contributions_count_density_groupbyboundary(base_client): 356 | """ 357 | Tests whether the result of contributions.count.density.groupbyboundary.post is converted to a pandas.DataFrame 358 | :return: 359 | """ 360 | bboxes = "8.7137,49.4096,8.717,49.4119" 361 | time = "2015-01-01,2016-01-01" 362 | filter = "name=Krautturm and type:way" 363 | 364 | client = base_client 365 | response = client.contributions.count.density.groupByBoundary.post( 366 | bboxes=bboxes, time=time, filter=filter 367 | ) 368 | result = response.as_dataframe() 369 | 370 | assert isinstance(result, pd.DataFrame) 371 | assert len(result) == 1 372 | 373 | 374 | @pytest.mark.vcr 375 | def test_contributions_latest(base_client): 376 | """ 377 | Test whether the result of conributions.latest.bbox is converted to a geopandas.GeoDataFrame 378 | :return: 379 | """ 380 | bboxes = "8.7137,49.4096,8.717,49.4119" 381 | time = "2015-01-01,2016-01-01" 382 | filter = "name=Krautturm and type:way" 383 | 384 | client = base_client 385 | response = client.contributions.latest.bbox.post( 386 | bboxes=bboxes, time=time, filter=filter 387 | ) 388 | result = response.as_dataframe() 389 | 390 | assert isinstance(result, gpd.GeoDataFrame) 391 | assert len(result) == 1 392 | 393 | 394 | @pytest.mark.vcr 395 | def test_empty_geodataframe(base_client): 396 | """ 397 | Tests whether an empty GeoDataFrame is created without a warning if no features are returned from ohsome 398 | :return: 399 | """ 400 | bboxes = "8.7137,49.4096,8.717,49.4119" 401 | time = "2015-01-01,2016-01-01" 402 | filter = "name=Krautturm1 and type:way" 403 | 404 | client = base_client 405 | response = client.elements.bbox.post(bboxes=bboxes, time=time, filter=filter) 406 | with warnings.catch_warnings(): 407 | warnings.simplefilter(action="error") 408 | result = response.as_dataframe() 409 | 410 | assert isinstance(result, gpd.GeoDataFrame) 411 | assert result.empty 412 | assert result.columns.to_list() == ["@osmId", "geometry", "@other_tags"] 413 | 414 | 415 | @pytest.mark.vcr 416 | def test_all_columns_with_timestamps_to_be_without_timezone(base_client): 417 | """Test whether all the columns with timestamp like 'timestamp', '@timestamp','@validFrom', '@validTo', 418 | 'fromTimestamp', 'toTimestamp' and '@snapshotTimestamp' are without timezone 419 | """ 420 | bbox = "8.67,49.39,8.71,49.42" 421 | time = "2008-01-01/2023-01-01/P1Y" 422 | time2iso = "2020-02-01,2020-06-29" 423 | fltr = "amenity=cafe and type:node" 424 | client = base_client 425 | 426 | fromTimestamp = ( 427 | client.contributions.count.density.post(time=time, bboxes=bbox, filter=fltr) 428 | .as_dataframe() 429 | .index.levels[0][0] 430 | ) 431 | toTimestamp = ( 432 | client.contributions.count.density.post(time=time, bboxes=bbox, filter=fltr) 433 | .as_dataframe() 434 | .index.levels[0][1] 435 | ) 436 | at_validFrom = ( 437 | client.elementsFullHistory.geometry.post( 438 | time=time2iso, bboxes=bbox, filter=fltr 439 | ) 440 | .as_dataframe() 441 | .index.levels[1][0] 442 | ) 443 | at_validTo = ( 444 | client.elementsFullHistory.geometry.post( 445 | time=time2iso, bboxes=bbox, filter=fltr 446 | ) 447 | .as_dataframe() 448 | .index.levels[2][0] 449 | ) 450 | at_timestamp = ( 451 | client.contributions.geometry.post(time=time2iso, bboxes=bbox, filter=fltr) 452 | .as_dataframe() 453 | .index[0][1] 454 | ) 455 | timestamp = ( 456 | client.elements.count.groupByBoundary.post(bboxes=bbox, time=time, filter=fltr) 457 | .as_dataframe() 458 | .index.levels[1][0] 459 | ) 460 | at_snapshotTimestamp = ( 461 | client.elements.geometry.post(bboxes=bbox, time=time, filter=fltr) 462 | .as_dataframe() 463 | .index.levels[1][0] 464 | ) 465 | 466 | assert fromTimestamp.tz is None 467 | assert toTimestamp.tz is None 468 | assert at_validFrom.tz is None 469 | assert at_validTo.tz is None 470 | assert at_timestamp.tz is None 471 | assert timestamp.tz is None 472 | assert at_snapshotTimestamp.tz is None 473 | 474 | 475 | def test_explode_tags(dummy_ohsome_response): 476 | """Test if the explode_tags parameter explodes tags.""" 477 | expected_df = gpd.GeoDataFrame( 478 | data={ 479 | "highway": ["primary"], 480 | "@other_tags": [{"width": "10"}], 481 | "@snapshotTimestamp": [datetime(2024, 1, 1)], 482 | "@osmId": ["node/1234"], 483 | }, 484 | geometry=[Point(0, 0)], 485 | crs="EPSG:4326", 486 | ) 487 | 488 | computed_df = dummy_ohsome_response.as_dataframe( 489 | explode_tags=("highway",), multi_index=False 490 | ) 491 | 492 | assert_geodataframe_equal(computed_df, expected_df, check_like=True) 493 | 494 | 495 | def test_explode_tags_none(dummy_ohsome_response): 496 | """Test if the explode_tags parameter can be set to explode all (to get previous behaviour).""" 497 | expected_df = gpd.GeoDataFrame( 498 | data={ 499 | "highway": ["primary"], 500 | "width": ["10"], 501 | "@snapshotTimestamp": [datetime(2024, 1, 1)], 502 | "@osmId": ["node/1234"], 503 | }, 504 | geometry=[Point(0, 0)], 505 | crs="EPSG:4326", 506 | ) 507 | 508 | computed_df = dummy_ohsome_response.as_dataframe( 509 | explode_tags=None, multi_index=False 510 | ) 511 | 512 | assert_geodataframe_equal(computed_df, expected_df, check_like=True) 513 | 514 | 515 | def test_explode_tags_empy(dummy_ohsome_response): 516 | """Test if explode_tags parameter can be disabled.""" 517 | expected_df = gpd.GeoDataFrame( 518 | data={ 519 | "@other_tags": [{"width": "10", "highway": "primary"}], 520 | "@snapshotTimestamp": [datetime(2024, 1, 1)], 521 | "@osmId": ["node/1234"], 522 | }, 523 | geometry=[Point(0, 0)], 524 | crs="EPSG:4326", 525 | ) 526 | 527 | computed_df = dummy_ohsome_response.as_dataframe(explode_tags=(), multi_index=False) 528 | 529 | assert_geodataframe_equal(computed_df, expected_df, check_like=True) 530 | 531 | 532 | def test_explode_tags_missing_in_response(dummy_ohsome_response): 533 | """Test if the explode_tags keys are always present in the result, even if they are not part of the response.""" 534 | expected_df = gpd.GeoDataFrame( 535 | data={ 536 | "this_key_does_not_exist": [None], 537 | "@other_tags": [{"width": "10", "highway": "primary"}], 538 | "@snapshotTimestamp": [datetime(2024, 1, 1)], 539 | "@osmId": ["node/1234"], 540 | }, 541 | geometry=[Point(0, 0)], 542 | crs="EPSG:4326", 543 | ) 544 | 545 | computed_df = dummy_ohsome_response.as_dataframe( 546 | explode_tags=("this_key_does_not_exist",), multi_index=False 547 | ) 548 | 549 | assert_geodataframe_equal(computed_df, expected_df, check_like=True) 550 | 551 | 552 | def test_explode_tags_present_on_empty_result(): 553 | """Test if exploded tags are present in an empty results.""" 554 | expected_df = gpd.GeoDataFrame( 555 | columns=["@osmId", "some_key", "some_other_key", "@other_tags", "geometry"], 556 | crs="EPSG:4326", 557 | ) 558 | 559 | response = Response() 560 | response._content = ( 561 | '{"attribution":{"url":"https://ohsome.org/copyrights","text":"© OpenStreetMap contributors"},' 562 | '"apiVersion":"1.10.1","type":"FeatureCollection","features":[]}' 563 | ).encode() 564 | computed_df = OhsomeResponse(data=response.json()).as_dataframe( 565 | explode_tags=("some_key", "some_other_key") 566 | ) 567 | 568 | assert_geodataframe_equal(computed_df, expected_df, check_like=True) 569 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ohsome" 3 | version = "0.4.0" 4 | description = "A Python client for the ohsome API" 5 | authors = ["HeiGIT ohsome team ", "GIScience Research Group, Heidelberg University"] 6 | repository = "https://github.com/GIScience/ohsome-py" 7 | readme = 'README.md' 8 | license = "GPL-3.0" 9 | 10 | [tool.poetry.dependencies] 11 | python = "^3.10" 12 | requests = "^2.25.1" 13 | pandas = "^2.1.3" 14 | numpy = "^2.1.2" 15 | geopandas = "^1.0.1" 16 | urllib3 = "^2.0.2" 17 | curlify2 = "^2.0.0" 18 | 19 | [tool.poetry.group.test.dependencies] 20 | pytest = "^7.4.3" 21 | pytest-random-order = "^1.1.0" 22 | pytest-recording = "^0.13.0" 23 | responses = "^0.24.1" 24 | 25 | [tool.poetry.group.dev.dependencies] 26 | black = "^23.11.0" 27 | pre-commit = "^3.5.0" 28 | jupyter = "^1.0.0" 29 | 30 | [tool.dephell.main] 31 | from = { format = "poetry", path = "pyproject.toml" } 32 | to = { format = "setuppy", path = "setup.py" } 33 | 34 | [build-system] 35 | requires = ["poetry-core>=1.0.0"] 36 | build-backend = "poetry.core.masonry.api" 37 | 38 | 39 | [tool.black] 40 | line-length = 88 41 | include = '\.pyi?$' 42 | exclude = ''' 43 | /( 44 | \.git 45 | | \.hg 46 | | \.mypy_cache 47 | | \.tox 48 | | \.venv 49 | | _build 50 | | buck-out 51 | | build 52 | | dist 53 | )/ 54 | ''' 55 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = 3 | ignore:distutils Version classes are deprecated:DeprecationWarning 4 | --------------------------------------------------------------------------------