diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f3442494..25f4cde44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: run: SKIP=no-commit-to-branch pre-commit run --all-files - name: Test docs - run: make -C ./docs html + run: make -C ./docs html SPHINXOPTS="-W --keep-going" - name: Test code run: pytest --maxfail=1 --typeguard-packages=osmnx --cov=./osmnx --cov-report=xml --cov-report=term-missing --verbose diff --git a/.github/workflows/test-minimal.yml b/.github/workflows/test-minimal.yml index 7fcf28218..170b99172 100644 --- a/.github/workflows/test-minimal.yml +++ b/.github/workflows/test-minimal.yml @@ -46,7 +46,7 @@ jobs: - name: Test docs run: | - make -C ./docs html + make -C ./docs html SPHINXOPTS="-W --keep-going" python -m sphinx -b linkcheck ./docs/source ./docs/build/linkcheck - name: Test code diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 27bf41e94..2f4efb3f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,4 +40,5 @@ repos: rev: "v1.8.0" hooks: - id: mypy - additional_dependencies: [matplotlib, pandas-stubs, types-requests] + additional_dependencies: + [matplotlib, pandas-stubs, pytest, types-requests] diff --git a/CHANGELOG.md b/CHANGELOG.md index f8b14026f..388a51dee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,17 @@ ## 2.0.0 (Unreleased) -- add type annotations throughout the package for user type hinting and type checking (#1107) +- add type annotations to all public and private functions throughout the package (#1107) - remove functionality previously deprecated in v1 (#1113) +- drop Python 3.8 support (#1106) +- make which_result function parameter consistently able to accept a list throughout package (#1113) +- make utils_geo.bbox_from_point function return a tuple of floats for consistency with rest of package (#1113) +- fix bug in \_downloader.\_save_to_cache function usage (#1107) +- fix bug in handling requests ConnectionError when querying Overpass status endpoint (#1113) +- minor fixes throughout to address inconsistencies revealed by type enforcement (#1107 #1114) +- rename osm_xml module to \_osm_xml to make it private, as all its functions are private (#1113) +- rename private \_downloader module to \_http (#1114) +- remove unnecessary private \_api module (#1114) ## 1.9.0 (Unreleased) diff --git a/docs/source/internals-reference.rst b/docs/source/internals-reference.rst index 327ca328f..61a8f5211 100644 --- a/docs/source/internals-reference.rst +++ b/docs/source/internals-reference.rst @@ -3,14 +3,6 @@ Internals Reference This is the complete OSMnx internals reference for developers, including private internal modules and functions. If you are instead looking for a user guide to OSMnx's public API, see the :doc:`user-reference`. -osmnx._api module ------------------ - -.. automodule:: osmnx._api - :members: - :private-members: - :noindex: - osmnx.bearing module -------------------- @@ -27,14 +19,6 @@ osmnx.distance module :private-members: :noindex: -osmnx._downloader module ------------------------- - -.. automodule:: osmnx._downloader - :members: - :private-members: - :noindex: - osmnx.elevation module ---------------------- @@ -75,6 +59,14 @@ osmnx.graph module :private-members: :noindex: +osmnx._http module +------------------ + +.. automodule:: osmnx._http + :members: + :private-members: + :noindex: + osmnx.io module --------------- diff --git a/docs/source/user-reference.rst b/docs/source/user-reference.rst index b2ebc7ca8..cb7e1bf19 100644 --- a/docs/source/user-reference.rst +++ b/docs/source/user-reference.rst @@ -1,114 +1,112 @@ -User Reference -============== - -This is the User Reference for the OSMnx package. If you are looking for an introduction to OSMnx, read the :doc:`getting-started` guide. - -This guide describes the usage of OSMnx's public API. Every function can be accessed via ``ox.module_name.function_name()`` and many can also be accessed directly via ``ox.function_name()`` as a shortcut. - -osmnx.bearing module --------------------- - -.. automodule:: osmnx.bearing - :members: - -osmnx.distance module ---------------------- - -.. automodule:: osmnx.distance - :members: - -osmnx.elevation module ----------------------- - -.. automodule:: osmnx.elevation - :members: - -osmnx.features module ---------------------- - -.. automodule:: osmnx.features - :members: - -osmnx.geocoder module ---------------------- - -.. automodule:: osmnx.geocoder - :members: - -osmnx.graph module ------------------- - -.. automodule:: osmnx.graph - :members: - -osmnx.io module ---------------- - -.. automodule:: osmnx.io - :members: - -osmnx.plot module ------------------ - -.. automodule:: osmnx.plot - :members: - -osmnx.projection module ------------------------ - -.. automodule:: osmnx.projection - :members: - -osmnx.routing module ------------------------ - -.. automodule:: osmnx.routing - :members: - -osmnx.settings module ---------------------- - -.. automodule:: osmnx.settings - :members: - -osmnx.simplification module ---------------------------- - -.. automodule:: osmnx.simplification - :members: - -osmnx.speed module ------------------- - -.. automodule:: osmnx.speed - :members: - -osmnx.stats module ------------------- - -.. automodule:: osmnx.stats - :members: - -osmnx.truncate module ---------------------- - -.. automodule:: osmnx.truncate - :members: - -osmnx.utils module ------------------- - -.. automodule:: osmnx.utils - :members: - -osmnx.utils_geo module ----------------------- - -.. automodule:: osmnx.utils_geo - :members: - -osmnx.utils_graph module ------------------------- - -.. automodule:: osmnx.utils_graph - :members: +User Reference +============== + +This is the User Reference for the OSMnx package. If you are looking for an introduction to OSMnx, read the :doc:`getting-started` guide. This guide describes the usage of OSMnx's public API. + +osmnx.bearing module +-------------------- + +.. automodule:: osmnx.bearing + :members: + +osmnx.distance module +--------------------- + +.. automodule:: osmnx.distance + :members: + +osmnx.elevation module +---------------------- + +.. automodule:: osmnx.elevation + :members: + +osmnx.features module +--------------------- + +.. automodule:: osmnx.features + :members: + +osmnx.geocoder module +--------------------- + +.. automodule:: osmnx.geocoder + :members: + +osmnx.graph module +------------------ + +.. automodule:: osmnx.graph + :members: + +osmnx.io module +--------------- + +.. automodule:: osmnx.io + :members: + +osmnx.plot module +----------------- + +.. automodule:: osmnx.plot + :members: + +osmnx.projection module +----------------------- + +.. automodule:: osmnx.projection + :members: + +osmnx.routing module +----------------------- + +.. automodule:: osmnx.routing + :members: + +osmnx.settings module +--------------------- + +.. automodule:: osmnx.settings + :members: + +osmnx.simplification module +--------------------------- + +.. automodule:: osmnx.simplification + :members: + +osmnx.speed module +------------------ + +.. automodule:: osmnx.speed + :members: + +osmnx.stats module +------------------ + +.. automodule:: osmnx.stats + :members: + +osmnx.truncate module +--------------------- + +.. automodule:: osmnx.truncate + :members: + +osmnx.utils module +------------------ + +.. automodule:: osmnx.utils + :members: + +osmnx.utils_geo module +---------------------- + +.. automodule:: osmnx.utils_geo + :members: + +osmnx.utils_graph module +------------------------ + +.. automodule:: osmnx.utils_graph + :members: diff --git a/osmnx/__init__.py b/osmnx/__init__.py index e21f2e708..ccf41e870 100644 --- a/osmnx/__init__.py +++ b/osmnx/__init__.py @@ -1,4 +1,56 @@ -"""OSMnx init.""" +# ruff: noqa: F401,PLC0414 +"""Define the OSMnx package's namespace.""" -from ._api import * # noqa: F401, F403 -from ._version import __version__ # noqa: F401 +# expose the package version +from ._version import __version__ as __version__ + +# expose the old pre-v2 API for backwards compatibility. this allows common +# functionality to be accessed directly via the ox.function_name() shortcut +# by exposing these functions directly in the package's namespace. +from .bearing import add_edge_bearings as add_edge_bearings +from .bearing import orientation_entropy as orientation_entropy +from .distance import nearest_edges as nearest_edges +from .distance import nearest_nodes as nearest_nodes +from .elevation import add_edge_grades as add_edge_grades +from .elevation import add_node_elevations_google as add_node_elevations_google +from .elevation import add_node_elevations_raster as add_node_elevations_raster +from .features import features_from_address as features_from_address +from .features import features_from_bbox as features_from_bbox +from .features import features_from_place as features_from_place +from .features import features_from_point as features_from_point +from .features import features_from_polygon as features_from_polygon +from .features import features_from_xml as features_from_xml +from .geocoder import geocode as geocode +from .geocoder import geocode_to_gdf as geocode_to_gdf +from .graph import graph_from_address as graph_from_address +from .graph import graph_from_bbox as graph_from_bbox +from .graph import graph_from_place as graph_from_place +from .graph import graph_from_point as graph_from_point +from .graph import graph_from_polygon as graph_from_polygon +from .graph import graph_from_xml as graph_from_xml +from .io import load_graphml as load_graphml +from .io import save_graph_geopackage as save_graph_geopackage +from .io import save_graph_xml as save_graph_xml +from .io import save_graphml as save_graphml +from .plot import plot_figure_ground as plot_figure_ground +from .plot import plot_footprints as plot_footprints +from .plot import plot_graph as plot_graph +from .plot import plot_graph_route as plot_graph_route +from .plot import plot_graph_routes as plot_graph_routes +from .plot import plot_orientation as plot_orientation +from .projection import project_gdf as project_gdf +from .projection import project_graph as project_graph +from .routing import k_shortest_paths as k_shortest_paths +from .routing import shortest_path as shortest_path +from .simplification import consolidate_intersections as consolidate_intersections +from .simplification import simplify_graph as simplify_graph +from .speed import add_edge_speeds as add_edge_speeds +from .speed import add_edge_travel_times as add_edge_travel_times +from .stats import basic_stats as basic_stats +from .utils import citation as citation +from .utils import log as log +from .utils import ts as ts +from .utils_graph import get_digraph as get_digraph +from .utils_graph import get_undirected as get_undirected +from .utils_graph import graph_from_gdfs as graph_from_gdfs +from .utils_graph import graph_to_gdfs as graph_to_gdfs diff --git a/osmnx/_api.py b/osmnx/_api.py deleted file mode 100644 index cd9ff8c50..000000000 --- a/osmnx/_api.py +++ /dev/null @@ -1,50 +0,0 @@ -# ruff: noqa: F401 -"""Expose most common parts of public API directly in package namespace.""" - -from .bearing import add_edge_bearings -from .bearing import orientation_entropy -from .distance import nearest_edges -from .distance import nearest_nodes -from .elevation import add_edge_grades -from .elevation import add_node_elevations_google -from .elevation import add_node_elevations_raster -from .features import features_from_address -from .features import features_from_bbox -from .features import features_from_place -from .features import features_from_point -from .features import features_from_polygon -from .features import features_from_xml -from .geocoder import geocode -from .geocoder import geocode_to_gdf -from .graph import graph_from_address -from .graph import graph_from_bbox -from .graph import graph_from_place -from .graph import graph_from_point -from .graph import graph_from_polygon -from .graph import graph_from_xml -from .io import load_graphml -from .io import save_graph_geopackage -from .io import save_graph_xml -from .io import save_graphml -from .plot import plot_figure_ground -from .plot import plot_footprints -from .plot import plot_graph -from .plot import plot_graph_route -from .plot import plot_graph_routes -from .plot import plot_orientation -from .projection import project_gdf -from .projection import project_graph -from .routing import k_shortest_paths -from .routing import shortest_path -from .simplification import consolidate_intersections -from .simplification import simplify_graph -from .speed import add_edge_speeds -from .speed import add_edge_travel_times -from .stats import basic_stats -from .utils import citation -from .utils import log -from .utils import ts -from .utils_graph import get_digraph -from .utils_graph import get_undirected -from .utils_graph import graph_from_gdfs -from .utils_graph import graph_to_gdfs diff --git a/osmnx/_downloader.py b/osmnx/_http.py similarity index 98% rename from osmnx/_downloader.py rename to osmnx/_http.py index e25938f5a..71ccdb564 100644 --- a/osmnx/_downloader.py +++ b/osmnx/_http.py @@ -55,11 +55,7 @@ def _save_to_cache( """ if settings.use_cache: if not ok: # pragma: no cover - utils.log("Did not save to cache because response status_code is not OK") - - elif response_json is None: # pragma: no cover - utils.log("Did not save to cache because response_json is None") - + utils.log("Did not save to cache because HTTP status code is not OK.", level=lg.WARNING) else: # create the folder on the disk if it doesn't already exist cache_folder = Path(settings.cache_folder) diff --git a/osmnx/_nominatim.py b/osmnx/_nominatim.py index aff4b85e8..a340415c4 100644 --- a/osmnx/_nominatim.py +++ b/osmnx/_nominatim.py @@ -9,7 +9,7 @@ import requests -from . import _downloader +from . import _http from . import settings from . import utils from ._errors import InsufficientResponseError @@ -69,7 +69,7 @@ def _download_nominatim_element( for key in sorted(query): params[key] = query[key] else: # pragma: no cover - msg = "query must be a dict or a string" + msg = "each query must be a dict or a string" # type: ignore[unreachable] raise TypeError(msg) # request the URL, return the JSON @@ -112,12 +112,12 @@ def _nominatim_request( # prepare Nominatim API URL and see if request already exists in cache url = settings.nominatim_endpoint.rstrip("/") + "/" + request_type prepared_url = str(requests.Request("GET", url, params=params).prepare().url) - cached_response_json = _downloader._retrieve_from_cache(prepared_url) + cached_response_json = _http._retrieve_from_cache(prepared_url) if isinstance(cached_response_json, list): return cached_response_json # pause then request this URL - domain = _downloader._hostname_from_url(url) + domain = _http._hostname_from_url(url) utils.log(f"Pausing {pause} second(s) before making HTTP GET request to {domain!r}") time.sleep(pause) @@ -127,7 +127,7 @@ def _nominatim_request( url, params=params, timeout=settings.timeout, - headers=_downloader._get_http_headers(), + headers=_http._get_http_headers(), **settings.requests_kwargs, ) @@ -141,9 +141,9 @@ def _nominatim_request( time.sleep(error_pause) return _nominatim_request(params, request_type, pause, error_pause) - response_json = _downloader._parse_response(response) + response_json = _http._parse_response(response) if not isinstance(response_json, list): msg = "Nominatim API did not return a list of results." raise InsufficientResponseError(msg) - _downloader._save_to_cache(prepared_url, response_json, response.ok) + _http._save_to_cache(prepared_url, response_json, response.ok) return response_json diff --git a/osmnx/_overpass.py b/osmnx/_overpass.py index a20c12f00..6f4641e44 100644 --- a/osmnx/_overpass.py +++ b/osmnx/_overpass.py @@ -15,7 +15,7 @@ from shapely.geometry import MultiPolygon from shapely.geometry import Polygon -from . import _downloader +from . import _http from . import projection from . import settings from . import utils @@ -142,7 +142,7 @@ def _get_overpass_pause( url = base_endpoint.rstrip("/") + "/status" response = requests.get( url, - headers=_downloader._get_http_headers(), + headers=_http._get_http_headers(), timeout=settings.timeout, **settings.requests_kwargs, ) @@ -391,19 +391,19 @@ def _overpass_request( response_json : dict or list """ # resolve url to same IP even if there is server round-robin redirecting - _downloader._config_dns(settings.overpass_endpoint) + _http._config_dns(settings.overpass_endpoint) # prepare the Overpass API URL and see if request already exists in cache url = settings.overpass_endpoint.rstrip("/") + "/interpreter" prepared_url = str(requests.Request("GET", url, params=data).prepare().url) - cached_response_json = _downloader._retrieve_from_cache(prepared_url) + cached_response_json = _http._retrieve_from_cache(prepared_url) if isinstance(cached_response_json, dict): return cached_response_json # pause then request this URL if pause is None: this_pause = _get_overpass_pause(settings.overpass_endpoint) - domain = _downloader._hostname_from_url(url) + domain = _http._hostname_from_url(url) utils.log(f"Pausing {this_pause} second(s) before making HTTP POST request to {domain!r}") time.sleep(this_pause) @@ -413,7 +413,7 @@ def _overpass_request( url, data=data, timeout=settings.timeout, - headers=_downloader._get_http_headers(), + headers=_http._get_http_headers(), **settings.requests_kwargs, ) @@ -428,9 +428,9 @@ def _overpass_request( time.sleep(this_pause) return _overpass_request(data, pause, error_pause) - response_json = _downloader._parse_response(response) + response_json = _http._parse_response(response) if not isinstance(response_json, dict): # pragma: no cover msg = "Overpass API did not return a dict of results." raise InsufficientResponseError(msg) - _downloader._save_to_cache(prepared_url, response_json, response.ok) + _http._save_to_cache(prepared_url, response_json, response.ok) return response_json diff --git a/osmnx/elevation.py b/osmnx/elevation.py index f84b7d8fe..b8d75358a 100644 --- a/osmnx/elevation.py +++ b/osmnx/elevation.py @@ -14,7 +14,7 @@ import pandas as pd import requests -from . import _downloader +from . import _http from . import settings from . import utils from . import utils_graph @@ -200,7 +200,7 @@ def add_node_elevations_google( {node: f'{data["y"]:.5f},{data["x"]:.5f}' for node, data in G.nodes(data=True)} ) n_calls = int(np.ceil(len(node_points) / batch_size)) - domain = _downloader._hostname_from_url(settings.elevation_url_template) + domain = _http._hostname_from_url(settings.elevation_url_template) utils.log(f"Requesting node elevations from {domain!r} in {n_calls} request(s)") # break the series of coordinates into chunks of batch_size @@ -250,12 +250,12 @@ def _elevation_request(url: str, pause: float) -> dict[str, Any]: response_json : dict """ # check if request already exists in cache - cached_response_json = _downloader._retrieve_from_cache(url) + cached_response_json = _http._retrieve_from_cache(url) if isinstance(cached_response_json, dict): return cached_response_json # pause then request this URL - domain = _downloader._hostname_from_url(url) + domain = _http._hostname_from_url(url) utils.log(f"Pausing {pause} second(s) before making HTTP GET request to {domain!r}") time.sleep(pause) @@ -264,13 +264,13 @@ def _elevation_request(url: str, pause: float) -> dict[str, Any]: response = requests.get( url, timeout=settings.timeout, - headers=_downloader._get_http_headers(), + headers=_http._get_http_headers(), **settings.requests_kwargs, ) - response_json = _downloader._parse_response(response) + response_json = _http._parse_response(response) if not isinstance(response_json, dict): # pragma: no cover msg = "Elevation API did not return a dict of results." raise InsufficientResponseError(msg) - _downloader._save_to_cache(url, response_json, response.ok) + _http._save_to_cache(url, response_json, response.ok) return response_json diff --git a/osmnx/features.py b/osmnx/features.py index ac617956a..39b4e3f4f 100644 --- a/osmnx/features.py +++ b/osmnx/features.py @@ -263,16 +263,8 @@ def features_from_place( ------- gdf : geopandas.GeoDataFrame """ - # create a GeoDataFrame with the spatial boundaries of the place(s) - if isinstance(query, (str, dict, list)): - # if string (place name) or dict (structured place query), this is a - # single place. if list, it contains multiple places to retrieve. - gdf_place = geocoder.geocode_to_gdf(query, which_result=which_result) - else: # pragma: no cover - msg = "query must be dict, string, or list of strings" - raise TypeError(msg) - # extract the geometry from the GeoDataFrame to use in query + gdf_place = geocoder.geocode_to_gdf(query, which_result=which_result) polygon = gdf_place["geometry"].unary_union utils.log("Constructed place geometry polygon(s) to query Overpass") diff --git a/osmnx/geocoder.py b/osmnx/geocoder.py index 2a278aa73..b772bcb30 100644 --- a/osmnx/geocoder.py +++ b/osmnx/geocoder.py @@ -101,10 +101,6 @@ def geocode_to_gdf( gdf : geopandas.GeoDataFrame a GeoDataFrame with one row for each query """ - if not isinstance(query, (str, dict, list)): # pragma: no cover - msg = "query must be a string, or dict, or list of strings/dicts" - raise TypeError(msg) - if isinstance(query, list): # if query is a list of queries but which_result is int/None, then # turn which_result into a list with same length as query list @@ -123,16 +119,9 @@ def geocode_to_gdf( msg = "which_result length must equal query length" raise ValueError(msg) - # for each query and which_result value - gdf = gpd.GeoDataFrame() - for q, wr in zip(query_list, which_result_list): - # ensure each query is correct type - if not isinstance(q, (str, dict)): # pragma: no cover - msg = "each query must be a string or dict" - raise TypeError(msg) - - # geocode each query then add to GeoDataFrame as a new row - gdf = pd.concat([gdf, _geocode_query_to_gdf(q, wr, by_osmid)]) + # geocode each query then add to GeoDataFrame as a new row + gdfs = (_geocode_query_to_gdf(q, wr, by_osmid) for q, wr in zip(query_list, which_result_list)) + gdf = pd.concat(gdfs) # reset GeoDataFrame index and set its CRS gdf = gdf.reset_index(drop=True).set_crs(settings.default_crs) diff --git a/osmnx/graph.py b/osmnx/graph.py index 54ebc6938..705f3ed72 100644 --- a/osmnx/graph.py +++ b/osmnx/graph.py @@ -313,16 +313,8 @@ def graph_from_place( function to automatically make multiple requests: see that function's documentation for caveats. """ - # create a GeoDataFrame with the spatial boundaries of the place(s) - if isinstance(query, (str, dict, list)): - # if string (place name) or dict (structured place query), this is a - # single place. if list, it contains multiple places to retrieve. - gdf_place = geocoder.geocode_to_gdf(query, which_result=which_result) - else: # pragma: no cover - msg = "query must be dict, string, or list of strings" - raise TypeError(msg) - # extract the geometry from the GeoDataFrame to use in query + gdf_place = geocoder.geocode_to_gdf(query, which_result=which_result) polygon = gdf_place["geometry"].unary_union utils.log("Constructed place geometry polygon(s) to query Overpass") diff --git a/osmnx/plot.py b/osmnx/plot.py index 066fee720..3820d855c 100644 --- a/osmnx/plot.py +++ b/osmnx/plot.py @@ -5,6 +5,7 @@ from collections.abc import Iterable from collections.abc import Sequence from pathlib import Path +from types import ModuleType from typing import Any from typing import Literal from typing import overload @@ -26,6 +27,8 @@ # matplotlib is an optional dependency needed for visualization try: + mpl: ModuleType | None + import matplotlib as mpl import matplotlib.pyplot as plt from matplotlib import cm from matplotlib import colormaps @@ -34,7 +37,7 @@ from matplotlib.figure import Figure from matplotlib.projections.polar import PolarAxes except ImportError: # pragma: no cover - plt = cm = colormaps = colors = None # type: ignore[assignment] + mpl = None def get_colors( @@ -1068,6 +1071,6 @@ def _verify_mpl() -> None: ------- None """ - if cm is None or colors is None or plt is None or colormaps is None: # pragma: no cover + if mpl is None: # pragma: no cover msg = "matplotlib must be installed as an optional dependency for visualization" raise ImportError(msg) diff --git a/pyproject.toml b/pyproject.toml index 045073a08..1a06d993f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,10 +60,10 @@ path = "osmnx/_version.py" [tool.mypy] cache_dir = "~/.cache/mypy" ignore_missing_imports = true -implicit_reexport = true python_version = "3.9" strict = true warn_no_return = true +warn_unreachable = true [tool.ruff] cache-dir = "~/.cache/ruff" diff --git a/tests/lint_test.sh b/tests/lint_test.sh index 222d1fdb5..65b6804b1 100644 --- a/tests/lint_test.sh +++ b/tests/lint_test.sh @@ -16,7 +16,7 @@ hatch build --clean twine check --strict ./dist/* # build the docs -make -C ./docs html +make -C ./docs html SPHINXOPTS="-W --keep-going" #python -m sphinx -b linkcheck ./docs/source ./docs/build/linkcheck # run the tests and report the test coverage diff --git a/tests/test_osmnx.py b/tests/test_osmnx.py index 19e892206..ab6790507 100755 --- a/tests/test_osmnx.py +++ b/tests/test_osmnx.py @@ -370,13 +370,13 @@ def test_api_endpoints() -> None: # test good and bad DNS resolution ox.settings.timeout = 1 - ip = ox._downloader._resolve_host_via_doh("overpass-api.de") - ip = ox._downloader._resolve_host_via_doh("AAAAAAAAAAA") + ip = ox._http._resolve_host_via_doh("overpass-api.de") + ip = ox._http._resolve_host_via_doh("AAAAAAAAAAA") _doh_url_template_default = ox.settings.doh_url_template ox.settings.doh_url_template = "http://aaaaaa.hostdoesntexist.org/nothinguseful" - ip = ox._downloader._resolve_host_via_doh("overpass-api.de") + ip = ox._http._resolve_host_via_doh("overpass-api.de") ox.settings.doh_url_template = None - ip = ox._downloader._resolve_host_via_doh("overpass-api.de") + ip = ox._http._resolve_host_via_doh("overpass-api.de") ox.settings.doh_url_template = _doh_url_template_default # Test changing the Overpass endpoint.