X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/75513a23a864190063ea4f798017913a3249c46f..899a04ad264c45197ec7509b164c934a05392f30:/nominatim/api/core.py diff --git a/nominatim/api/core.py b/nominatim/api/core.py index c21e03f6..44ac9160 100644 --- a/nominatim/api/core.py +++ b/nominatim/api/core.py @@ -29,7 +29,7 @@ import nominatim.api.types as ntyp from nominatim.api.results import DetailedResult, ReverseResult, SearchResults -class NominatimAPIAsync: +class NominatimAPIAsync: #pylint: disable=too-many-instance-attributes """ The main frontend to the Nominatim database implements the functions for lookup, forward and reverse geocoding using asynchronous functions. @@ -47,10 +47,10 @@ class NominatimAPIAsync: project_dir: Path to the [project directory](../admin/Import.md#creating-the-project-directory) of the local Nominatim installation. - environ: Mapping of additional - [configuration parameters](../customize/Settings.md). - These will override default configuration and configuration - from the project directory. + environ: Mapping of [configuration parameters](../customize/Settings.md). + When set, replaces any configuration via environment variables. + Settings in this mapping also have precedence over any + parameters found in the `.env` file of the project directory. loop: The asyncio event loop that will be used when calling functions. Only needed, when a custom event loop is used and the Python version is 3.9 or earlier. @@ -58,6 +58,7 @@ class NominatimAPIAsync: self.config = Configuration(project_dir, environ) self.query_timeout = self.config.get_int('QUERY_TIMEOUT') \ if self.config.QUERY_TIMEOUT else None + self.reverse_restrict_to_country_area = self.config.get_bool('SEARCH_WITHIN_COUNTRIES') self.server_version = 0 if sys.version_info >= (3, 10): @@ -80,21 +81,34 @@ class NominatimAPIAsync: if self._engine: return - dsn = self.config.get_database_params() - pool_size = self.config.get_int('API_POOL_SIZE') + extra_args: Dict[str, Any] = {'future': True, + 'echo': self.config.get_bool('DEBUG_SQL')} - query = {k: v for k, v in dsn.items() - if k not in ('user', 'password', 'dbname', 'host', 'port')} + is_sqlite = self.config.DATABASE_DSN.startswith('sqlite:') - dburl = sa.engine.URL.create( - f'postgresql+{PGCORE_LIB}', - database=dsn.get('dbname'), - username=dsn.get('user'), password=dsn.get('password'), - host=dsn.get('host'), port=int(dsn['port']) if 'port' in dsn else None, - query=query) - engine = sa_asyncio.create_async_engine(dburl, future=True, - max_overflow=0, pool_size=pool_size, - echo=self.config.get_bool('DEBUG_SQL')) + if is_sqlite: + params = dict((p.split('=', 1) + for p in self.config.DATABASE_DSN[7:].split(';'))) + dburl = sa.engine.URL.create('sqlite+aiosqlite', + database=params.get('dbname')) + + else: + dsn = self.config.get_database_params() + query = {k: v for k, v in dsn.items() + if k not in ('user', 'password', 'dbname', 'host', 'port')} + + dburl = sa.engine.URL.create( + f'postgresql+{PGCORE_LIB}', + database=dsn.get('dbname'), + username=dsn.get('user'), + password=dsn.get('password'), + host=dsn.get('host'), + port=int(dsn['port']) if 'port' in dsn else None, + query=query) + extra_args['max_overflow'] = 0 + extra_args['pool_size'] = self.config.get_int('API_POOL_SIZE') + + engine = sa_asyncio.create_async_engine(dburl, **extra_args) try: async with engine.begin() as conn: @@ -103,7 +117,7 @@ class NominatimAPIAsync: except (PGCORE_ERROR, sa.exc.OperationalError): server_version = 0 - if server_version >= 110000: + if server_version >= 110000 and not is_sqlite: @sa.event.listens_for(engine.sync_engine, "connect") def _on_connect(dbapi_con: Any, _: Any) -> None: cursor = dbapi_con.cursor() @@ -112,6 +126,15 @@ class NominatimAPIAsync: # Make sure that all connections get the new settings await self.close() + if is_sqlite: + @sa.event.listens_for(engine.sync_engine, "connect") + def _on_sqlite_connect(dbapi_con: Any, _: Any) -> None: + dbapi_con.run_async(lambda conn: conn.enable_load_extension(True)) + cursor = dbapi_con.cursor() + cursor.execute("SELECT load_extension('mod_spatialite')") + cursor.execute('SELECT SetDecimalPrecision(7)') + dbapi_con.run_async(lambda conn: conn.enable_load_extension(False)) + self._property_cache['DB:server_version'] = server_version self._tables = SearchTables(sa.MetaData(), engine.name) # pylint: disable=no-member @@ -201,7 +224,8 @@ class NominatimAPIAsync: conn.set_query_timeout(self.query_timeout) if details.keywords: await make_query_analyzer(conn) - geocoder = ReverseGeocoder(conn, details) + geocoder = ReverseGeocoder(conn, details, + self.reverse_restrict_to_country_area) return await geocoder.lookup(coord) @@ -321,10 +345,10 @@ class NominatimAPI: project_dir: Path to the [project directory](../admin/Import.md#creating-the-project-directory) of the local Nominatim installation. - environ: Mapping of additional - [configuration parameters](../customize/Settings.md). - These will override default configuration and configuration - from the project directory. + environ: Mapping of [configuration parameters](../customize/Settings.md). + When set, replaces any configuration via environment variables. + Settings in this mapping also have precedence over any + parameters found in the `.env` file of the project directory. """ self._loop = asyncio.new_event_loop() self._async_api = NominatimAPIAsync(project_dir, environ, loop=self._loop) @@ -373,7 +397,8 @@ class NominatimAPI: or `None` if the place could not be found in the database. Parameters: - place: Description of the place to look up. See PlaceRef below + place: Description of the place to look up. See + [Place identification](Input-Parameter-Types.md#place-identification) for the various ways to reference a place. Other parameters: @@ -455,7 +480,8 @@ class NominatimAPI: Each result is a dataclass with the fields detailed below. Parameters: - places: List of descriptions of the place to look up. See PlaceRef below + places: List of descriptions of the place to look up. See + [Place identification](Input-Parameter-Types.md#place-identification) for the various ways to reference a place. Other parameters: @@ -615,10 +641,15 @@ class NominatimAPI: Other parameters: max_results (int): Maximum number of results to return. The actual number of results may be less. (Default: 10) - min_rank (int): Lowest [address rank](../customize/Ranking.md#address-rank) to return. - max_rank (int): Highest address rank to return. + min_rank (int): Lowest permissible rank for the result. + For addressable places this is the minimum + [address rank](../customize/Ranking.md#address-rank). For all + other places the [search rank](../customize/Ranking.md#search-rank) + is used. + max_rank (int): Highest permissible rank for the result. See min_rank above. layers (enum): Defines the kind of data to take into account. - See description of layers below. (Default: addresses and POIs) + See [layers section](Input-Parameter-Types.md#layers) for details. + (Default: addresses and POIs) countries (list[str]): Restrict search to countries with the given ISO 3166-1 alpha-2 country code. An empty list (the default) disables this filter. @@ -727,10 +758,15 @@ class NominatimAPI: Other parameters: max_results (int): Maximum number of results to return. The actual number of results may be less. (Default: 10) - min_rank (int): Lowest [address rank](../customize/Ranking.md#address-rank) to return. - max_rank (int): Highest address rank to return. + min_rank (int): Lowest permissible rank for the result. + For addressable places this is the minimum + [address rank](../customize/Ranking.md#address-rank). For all + other places the [search rank](../customize/Ranking.md#search-rank) + is used. + max_rank (int): Highest permissible rank for the result. See min_rank above. layers (enum): Defines the kind of data to take into account. - See description of layers below. (Default: addresses and POIs) + See [layers section](Input-Parameter-Types.md#layers) for details. + (Default: addresses and POIs) countries (list[str]): Restrict search to countries with the given ISO 3166-1 alpha-2 country code. An empty list (the default) disables this filter. Do not use, when the country parameter @@ -834,10 +870,15 @@ class NominatimAPI: Other parameters: max_results (int): Maximum number of results to return. The actual number of results may be less. (Default: 10) - min_rank (int): Lowest [address rank](../customize/Ranking.md#address-rank) to return. - max_rank (int): Highest address rank to return. + min_rank (int): Lowest permissible rank for the result. + For addressable places this is the minimum + [address rank](../customize/Ranking.md#address-rank). For all + other places the [search rank](../customize/Ranking.md#search-rank) + is used. + max_rank (int): Highest permissible rank for the result. See min_rank above. layers (enum): Defines the kind of data to take into account. - See description of layers below. (Default: addresses and POIs) + See [layers section](Input-Parameter-Types.md#layers) for details. + (Default: addresses and POIs) countries (list[str]): Restrict search to countries with the given ISO 3166-1 alpha-2 country code. An empty list (the default) disables this filter.