From 145b44fa5715efbb446b621746dc7f1f20a16818 Mon Sep 17 00:00:00 2001 From: Julien Castiaux Date: Wed, 4 Jan 2023 15:48:12 +0000 Subject: [PATCH] [FIX] core: cannot read country geoip on city db Start odoo-bin shell with `--geoip_country_db='/i/dont/exist'` and type the following code: from odoo.http import GeoIP GeoIP('8.8.8.8').country_code TypeError: The country method cannot be used with the GeoLite2-City database There are two "things" here: the raw country and city entries in the databases and the rich python country and city objects returned when an entry was found and parsed. Then there are two "readers", a reader capable of reading and parsing entries from the city database and **another** reader for the country. The two readers are **only** compatible with their specific database: the city reader cannot read or parse information from the country database and vis-versa. That's the bug reported by the TypeError that this commit fixes. But, the two python instances created from parsing the entries of respecting databases with respecting parsers **do** share a same API: the city record class inherits from the country record class. # Valid city_db = geoip2.database.Reader(config['geoip_city_db']) city_record = city_db.city('8.8.8.8') city_record.country.name # works, a city record also # holds country attributes # Invalid city_db = geoip2.database.Reader(config['geoip_city_db']) country_record = city_db.country('8.8.8.8') # TypeError closes odoo/odoo#109095 Signed-off-by: Julien Castiaux --- odoo/addons/test_http/tests/test_common.py | 7 ++++--- odoo/http.py | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/odoo/addons/test_http/tests/test_common.py b/odoo/addons/test_http/tests/test_common.py index a8c72ae272f..e2a4eabf262 100644 --- a/odoo/addons/test_http/tests/test_common.py +++ b/odoo/addons/test_http/tests/test_common.py @@ -16,11 +16,12 @@ class TestHttpBase(HttpCase): geoip_resolver = MemoryGeoipResolver() session_store = MemorySessionStore(session_class=Session) + lazy_property.reset_all(odoo.http.root) cls.addClassCleanup(lazy_property.reset_all, odoo.http.root) cls.classPatch(odoo.conf, 'server_wide_modules', ['base', 'web', 'test_http']) - cls.classPatch(odoo.http.root, 'session_store', session_store) - cls.classPatch(odoo.http.root, 'geoip_city_db', geoip_resolver) - cls.classPatch(odoo.http.root, 'geoip_country_db', geoip_resolver) + cls.classPatch(odoo.http.Application, 'session_store', session_store) + cls.classPatch(odoo.http.Application, 'geoip_city_db', geoip_resolver) + cls.classPatch(odoo.http.Application, 'geoip_country_db', geoip_resolver) def setUp(self): super().setUp() diff --git a/odoo/http.py b/odoo/http.py index 662496813db..7f8b92e250f 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -1045,6 +1045,8 @@ class GeoIP(collections.abc.Mapping): def _city_record(self): try: return root.geoip_city_db.city(self.ip) + except (OSError, maxminddb.InvalidDatabaseError): + return GEOIP_EMPTY_CITY except geoip2.errors.AddressNotFoundError: return GEOIP_EMPTY_CITY @@ -1056,6 +1058,8 @@ class GeoIP(collections.abc.Mapping): return self._city_record try: return root.geoip_country_db.country(self.ip) + except (OSError, maxminddb.InvalidDatabaseError): + return self._city_record except geoip2.errors.AddressNotFoundError: return GEOIP_EMPTY_COUNTRY @@ -2020,10 +2024,7 @@ class Application: "Couldn't load Geoip City file at %s. IP Resolver disabled.", config['geoip_city_db'], exc_info=True ) - return type('FakeReader', (), { - 'city': lambda self, ip: GEOIP_EMPTY_CITY, - 'country': lambda self, ip: GEOIP_EMPTY_COUNTRY - })() + raise @lazy_property def geoip_country_db(self): @@ -2031,7 +2032,7 @@ class Application: return geoip2.database.Reader(config['geoip_country_db']) except (OSError, maxminddb.InvalidDatabaseError) as exc: _logger.debug("Couldn't load Geoip Country file (%s). Fallbacks on Geoip City.", exc,) - return self.geoip_city_db + raise def set_csp(self, response): headers = response.headers